Add Chromium-only Blender WebEngine parity work
This commit is contained in:
47
blender-5.2.0/extern/opensubdiv-source/examples/glEvalLimit/CMakeLists.txt
vendored
Normal file
47
blender-5.2.0/extern/opensubdiv-source/examples/glEvalLimit/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
#
|
||||
# Copyright 2013 Pixar
|
||||
#
|
||||
# Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
# https://opensubdiv.org/license.
|
||||
#
|
||||
|
||||
# *** glEvalLimit ***
|
||||
|
||||
include_directories(
|
||||
"${OPENSUBDIV_INCLUDE_DIR}"
|
||||
"${OPENGL_LOADER_INCLUDE_DIRS}"
|
||||
"${GLFW_INCLUDE_DIR}"
|
||||
)
|
||||
|
||||
list(APPEND PLATFORM_LIBRARIES
|
||||
"${OSD_LINK_TARGET}"
|
||||
"${OPENGL_LOADER_LIBRARIES}"
|
||||
"${GLFW_LIBRARIES}"
|
||||
)
|
||||
|
||||
if (OPENCL_FOUND)
|
||||
include_directories("${OPENCL_INCLUDE_DIRS}")
|
||||
list(APPEND PLATFORM_LIBRARIES OpenGL::GL)
|
||||
endif()
|
||||
|
||||
if( TBB_FOUND )
|
||||
list(APPEND PLATFORM_LIBRARIES
|
||||
TBB::tbb
|
||||
)
|
||||
endif()
|
||||
|
||||
osd_add_glfw_executable(glEvalLimit "examples"
|
||||
glEvalLimit.cpp
|
||||
particles.cpp
|
||||
particles.h
|
||||
"${INC_FILES}"
|
||||
$<TARGET_OBJECTS:regression_common_obj>
|
||||
$<TARGET_OBJECTS:regression_far_utils_obj>
|
||||
$<TARGET_OBJECTS:examples_common_gl_obj>
|
||||
)
|
||||
|
||||
target_link_libraries(glEvalLimit
|
||||
${PLATFORM_LIBRARIES}
|
||||
)
|
||||
|
||||
install(TARGETS glEvalLimit DESTINATION "${CMAKE_BINDIR_BASE}")
|
||||
1538
blender-5.2.0/extern/opensubdiv-source/examples/glEvalLimit/glEvalLimit.cpp
vendored
Normal file
1538
blender-5.2.0/extern/opensubdiv-source/examples/glEvalLimit/glEvalLimit.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
82
blender-5.2.0/extern/opensubdiv-source/examples/glEvalLimit/init_shapes.h
vendored
Normal file
82
blender-5.2.0/extern/opensubdiv-source/examples/glEvalLimit/init_shapes.h
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "../../regression/common/shape_utils.h"
|
||||
#include "../../regression/shapes/all.h"
|
||||
|
||||
|
||||
static std::vector<ShapeDesc> g_defaultShapes;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void initShapes() {
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_toroidal_tet", catmark_toroidal_tet, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cube", catmark_cube, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cubes_semisharp", catmark_cubes_semisharp, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_cubes_infsharp", catmark_cubes_infsharp, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pyramid", catmark_pyramid, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pyramid_creases0", catmark_pyramid_creases0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pyramid_creases1", catmark_pyramid_creases1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_torus", catmark_torus, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_torus_creases0", catmark_torus_creases0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_torus_creases1", catmark_torus_creases1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_edgecorner", catmark_edgecorner, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_edgeonly", catmark_edgeonly, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_edgenone", catmark_edgenone, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_quadstrips", catmark_quadstrips, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_xord_interior", catmark_xord_interior, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_xord_boundary", catmark_xord_boundary, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_val2_interior", catmark_val2_interior, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_nonquads", catmark_nonquads, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_single_crease", catmark_single_crease, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_inf_crease0", catmark_inf_crease0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_inf_crease1", catmark_inf_crease1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_nonman_verts", catmark_nonman_verts, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_nonman_edges", catmark_nonman_edges, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test1", catmark_hole_test1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test2", catmark_hole_test2, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test3", catmark_hole_test3, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_hole_test4", catmark_hole_test4, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_chaikin0", catmark_chaikin0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_chaikin1", catmark_chaikin1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_chaikin2", catmark_chaikin2, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_smoothtris0", catmark_smoothtris0, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_smoothtris1", catmark_smoothtris1, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pole8", catmark_pole8, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pole64", catmark_pole64, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_nonman_quadpole64",catmark_nonman_quadpole64,kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_nonman_edge100", catmark_nonman_edge100, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_helmet", catmark_helmet, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_bishop", catmark_bishop, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_pawn", catmark_pawn, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_rook", catmark_rook, kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc("catmark_car", catmark_car, kCatmark));
|
||||
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_toroidal_tet", loop_toroidal_tet, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_tetrahedron", loop_tetrahedron, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cube", loop_cube, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cubes_semisharp", loop_cubes_semisharp, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cubes_infsharp", loop_cubes_infsharp, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_cube_asymmetric", loop_cube_asymmetric, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_icosahedron", loop_icosahedron, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_icos_semisharp", loop_icos_semisharp, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_icos_infsharp", loop_icos_infsharp, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_triangle_edgecorner", loop_triangle_edgecorner, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_triangle_edgeonly", loop_triangle_edgeonly, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_triangle_edgenone", loop_triangle_edgenone, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_xord_interior", loop_xord_interior, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_xord_boundary", loop_xord_boundary, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_nonman_verts", loop_nonman_verts, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_nonman_edges", loop_nonman_edges, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_pole64", loop_pole64, kLoop));
|
||||
g_defaultShapes.push_back(ShapeDesc("loop_nonman_edge100", loop_nonman_edge100, kLoop));
|
||||
|
||||
g_defaultShapes.push_back(ShapeDesc("bilinear_cube", bilinear_cube, kBilinear));
|
||||
g_defaultShapes.push_back(ShapeDesc("bilinear_nonplanar", bilinear_nonplanar, kBilinear));
|
||||
g_defaultShapes.push_back(ShapeDesc("bilinear_nonquads0", bilinear_nonquads0, kBilinear));
|
||||
g_defaultShapes.push_back(ShapeDesc("bilinear_nonquads1", bilinear_nonquads1, kBilinear));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
442
blender-5.2.0/extern/opensubdiv-source/examples/glEvalLimit/particles.cpp
vendored
Normal file
442
blender-5.2.0/extern/opensubdiv-source/examples/glEvalLimit/particles.cpp
vendored
Normal file
@@ -0,0 +1,442 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "particles.h"
|
||||
|
||||
#include <opensubdiv/far/ptexIndices.h>
|
||||
#include <opensubdiv/far/patchMap.h>
|
||||
#include <opensubdiv/sdc/types.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
|
||||
using namespace OpenSubdiv;
|
||||
|
||||
void
|
||||
UpdateParticle(float speed,
|
||||
STParticles::Position *p,
|
||||
float *dp,
|
||||
Osd::PatchCoord *patchCoord,
|
||||
int regFaceSize,
|
||||
std::vector<STParticles::FaceInfo> const &adjacency,
|
||||
Far::PatchMap const *patchMap);
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_TBB
|
||||
#include <tbb/parallel_for.h>
|
||||
class TbbUpdateKernel {
|
||||
public:
|
||||
TbbUpdateKernel(float speed,
|
||||
STParticles::Position *positions,
|
||||
float *velocities,
|
||||
Osd::PatchCoord *patchCoords,
|
||||
int regFaceSize,
|
||||
std::vector<STParticles::FaceInfo> const &adjacency,
|
||||
Far::PatchMap const *patchMap) :
|
||||
_speed(speed), _positions(positions), _velocities(velocities),
|
||||
_patchCoords(patchCoords),
|
||||
_regFaceSize(regFaceSize), _adjacency(adjacency), _patchMap(patchMap) {
|
||||
}
|
||||
|
||||
void operator () (tbb::blocked_range<int> const &r) const {
|
||||
for (int i = r.begin(); i < r.end(); ++i) {
|
||||
STParticles::Position * p = _positions + i;
|
||||
float *dp = _velocities + i*2;
|
||||
Osd::PatchCoord *patchCoord = &_patchCoords[i];
|
||||
|
||||
UpdateParticle(_speed, p, dp, patchCoord, _regFaceSize, _adjacency, _patchMap);
|
||||
}
|
||||
}
|
||||
private:
|
||||
float _speed;
|
||||
STParticles::Position *_positions;
|
||||
float *_velocities;
|
||||
Osd::PatchCoord *_patchCoords;
|
||||
int _regFaceSize;
|
||||
std::vector<STParticles::FaceInfo> const &_adjacency;
|
||||
Far::PatchMap const *_patchMap;
|
||||
};
|
||||
#endif
|
||||
|
||||
STParticles::STParticles(Refiner const & refiner,
|
||||
PatchTable const *patchTable,
|
||||
int nParticles, bool centered)
|
||||
: _speed(1.0f)
|
||||
, _regFaceSize(
|
||||
Sdc::SchemeTypeTraits::GetRegularFaceSize(refiner.GetSchemeType())) {
|
||||
|
||||
Far::PtexIndices ptexIndices(refiner);
|
||||
|
||||
// Create a far patch map
|
||||
_patchMap = new Far::PatchMap(*patchTable);
|
||||
|
||||
int nPtexFaces = ptexIndices.GetNumFaces();
|
||||
|
||||
srand(static_cast<int>(2147483647));
|
||||
|
||||
{ // initialize positions
|
||||
|
||||
_positions.resize(nParticles);
|
||||
Position * pos = &_positions[0];
|
||||
|
||||
for (int i = 0; i < nParticles; ++i) {
|
||||
pos->ptexIndex = std::min(
|
||||
(int)(((float)rand()/(float)RAND_MAX) * nPtexFaces), nPtexFaces-1);
|
||||
if (_regFaceSize==3) {
|
||||
pos->s = centered ? 1.0f/3.0f : (float)rand()/(float)RAND_MAX;
|
||||
pos->t = centered ? 1.0f/3.0f : (float)rand()/(float)RAND_MAX;
|
||||
// Keep locations within the triangular parametric domain
|
||||
if ((pos->s+pos->t) >= 1.0f) {
|
||||
pos->s = 1.0f - pos->s;
|
||||
pos->t = 1.0f - pos->t;
|
||||
}
|
||||
} else {
|
||||
pos->s = centered ? 0.5f : (float)rand()/(float)RAND_MAX;
|
||||
pos->t = centered ? 0.5f : (float)rand()/(float)RAND_MAX;
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
|
||||
{ // initialize velocities
|
||||
_velocities.resize(nParticles * 2);
|
||||
|
||||
for (int i = 0; i < nParticles; ++i) {
|
||||
// initialize normalized random directions
|
||||
float s = 2.0f*(float)rand()/(float)RAND_MAX - 1.0f,
|
||||
t = 2.0f*(float)rand()/(float)RAND_MAX - 1.0f,
|
||||
l = sqrtf(s*s+t*t);
|
||||
|
||||
_velocities[2*i ] = s / l;
|
||||
_velocities[2*i+1] = t / l;
|
||||
}
|
||||
}
|
||||
|
||||
if (_regFaceSize == 4) { // initialize topology adjacency
|
||||
_adjacency.resize(nPtexFaces);
|
||||
|
||||
Far::TopologyLevel const & refBaseLevel = refiner.GetLevel(0);
|
||||
|
||||
int nfaces = refBaseLevel.GetNumFaces(),
|
||||
adjfaces[4],
|
||||
adjedges[4];
|
||||
|
||||
for (int face=0, ptexface=0; face<nfaces; ++face) {
|
||||
|
||||
Far::ConstIndexArray fverts = refBaseLevel.GetFaceVertices(face);
|
||||
|
||||
if (fverts.size()==_regFaceSize) {
|
||||
ptexIndices.GetAdjacency(refiner, face, 0, adjfaces, adjedges);
|
||||
_adjacency[ptexface] = FaceInfo(adjfaces, adjedges, false);
|
||||
++ptexface;
|
||||
} else {
|
||||
for (int vert=0; vert<fverts.size(); ++vert) {
|
||||
ptexIndices.GetAdjacency(refiner, face, vert, adjfaces, adjedges);
|
||||
_adjacency[ptexface+vert] =
|
||||
FaceInfo(adjfaces, adjedges, true);
|
||||
}
|
||||
ptexface+=fverts.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
//std::cout << *this;
|
||||
}
|
||||
|
||||
STParticles::~STParticles() {
|
||||
delete _patchMap;
|
||||
}
|
||||
|
||||
inline void
|
||||
FlipS(STParticles::Position * p, float * dp) {
|
||||
p->s = 1.0f-p->s;
|
||||
dp[0] = - dp[0];
|
||||
}
|
||||
|
||||
inline void
|
||||
FlipT(STParticles::Position * p, float * dp) {
|
||||
p->t = 1.0f-p->t;
|
||||
dp[1] = -dp[1];
|
||||
}
|
||||
|
||||
inline void
|
||||
SwapST(STParticles::Position * p, float * dp) {
|
||||
std::swap(p->s, p->t);
|
||||
std::swap(dp[0], dp[1]);
|
||||
}
|
||||
|
||||
inline void
|
||||
RotateQuad(int rot, STParticles::Position * p, float * dp) {
|
||||
switch (rot & 3) {
|
||||
default: return;
|
||||
case 1: FlipS(p, dp); SwapST(p, dp); break;
|
||||
case 2: FlipS(p, dp); FlipT(p, dp); break;
|
||||
case 3: FlipT(p, dp); SwapST(p, dp); break;
|
||||
}
|
||||
assert((p->s>=0.0f) && (p->s<=1.0f) && (p->t>=0.0f) && (p->t<=1.0f));
|
||||
}
|
||||
|
||||
inline void
|
||||
TrimQuad(STParticles::Position * p) {
|
||||
if (p->s <0.0f) p->s = 1.0f + p->s;
|
||||
if (p->s>=1.0f) p->s = p->s - 1.0f;
|
||||
if (p->t <0.0f) p->t = 1.0f + p->t;
|
||||
if (p->t>=1.0f) p->t = p->t - 1.0f;
|
||||
assert((p->s>=0.0f) && (p->s<=1.0f) && (p->t>=0.0f) && (p->t<=1.0f));
|
||||
}
|
||||
|
||||
inline void
|
||||
ClampQuad(STParticles::Position * p) {
|
||||
if (p->s<0.0f) {
|
||||
p->s=0.0f;
|
||||
} else if (p->s>1.0f) {
|
||||
p->s=1.0f;
|
||||
}
|
||||
if (p->t<0.0f) {
|
||||
p->t=0.0f;
|
||||
} else if (p->t>1.0f) {
|
||||
p->t=1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
BounceQuad(int edge, STParticles::Position * p, float * dp) {
|
||||
switch (edge) {
|
||||
case 0: assert(p->t<=0.0f); p->t = -p->t; dp[1] = -dp[1]; break;
|
||||
case 1: assert(p->s>=1.0f); p->s = 2.0f - p->s; dp[0] = -dp[0]; break;
|
||||
case 2: assert(p->t>=1.0f); p->t = 2.0f - p->t; dp[1] = -dp[1]; break;
|
||||
case 3: assert(p->s<=0.0f); p->s = -p->s; dp[0] = -dp[0]; break;
|
||||
}
|
||||
|
||||
// because 'diagonal' cases aren't handled, stick particles to edges when
|
||||
// if they cross 2 boundaries
|
||||
ClampQuad(p);
|
||||
assert((p->s>=0.0f) && (p->s<=1.0f) && (p->t>=0.0f) && (p->t<=1.0f));
|
||||
}
|
||||
|
||||
void
|
||||
WarpQuad(std::vector<STParticles::FaceInfo> const &adjacency,
|
||||
int edge, STParticles::Position * p, float * dp) {
|
||||
assert(p->ptexIndex<(int)adjacency.size() && (edge>=0 && edge<4));
|
||||
|
||||
STParticles::FaceInfo const & f = adjacency[p->ptexIndex];
|
||||
|
||||
int afid = f.adjface(edge),
|
||||
aeid = f.adjedge(edge);
|
||||
|
||||
if (afid==-1) {
|
||||
// boundary detected: bounce the particle
|
||||
BounceQuad(edge, p, dp);
|
||||
} else {
|
||||
STParticles::FaceInfo const & af = adjacency[afid];
|
||||
int rot = edge - aeid + 2;
|
||||
|
||||
bool fIsSubface = f.isSubface(),
|
||||
afIsSubface = af.isSubface();
|
||||
|
||||
if (fIsSubface != afIsSubface) {
|
||||
// XXXX manuelk domain should be split properly
|
||||
BounceQuad(edge, p, dp);
|
||||
} else {
|
||||
TrimQuad(p);
|
||||
RotateQuad(rot, p, dp);
|
||||
p->ptexIndex = afid; // move particle to adjacent face
|
||||
}
|
||||
}
|
||||
assert((p->s>=0.0f) && (p->s<=1.0f) && (p->t>=0.0f) && (p->t<=1.0f));
|
||||
}
|
||||
|
||||
void
|
||||
ConstrainQuad(STParticles::Position *p,
|
||||
float *dp,
|
||||
std::vector<STParticles::FaceInfo> const &adjacency) {
|
||||
|
||||
// make sure particles can't skip more than 1 face boundary at a time
|
||||
assert((p->s>-2.0f) && (p->s<2.0f) && (p->t>-2.0f) && (p->t<2.0f));
|
||||
|
||||
// check if the particle is jumping a boundary
|
||||
// note: a particle can jump 2 edges at a time (a "diagonal" jump)
|
||||
// this is not treated here.
|
||||
int edge = -1;
|
||||
if (p->s >= 1.0f) edge = 1;
|
||||
if (p->s <= 0.0f) edge = 3;
|
||||
if (p->t >= 1.0f) edge = 2;
|
||||
if (p->t <= 0.0f) edge = 0;
|
||||
|
||||
if (edge>=0) {
|
||||
// warp the particle to the other side of the boundary
|
||||
WarpQuad(adjacency, edge, p, dp);
|
||||
}
|
||||
assert((p->s>=0.0f) && (p->s<=1.0f) && (p->t>=0.0f) && (p->t<=1.0f));
|
||||
}
|
||||
|
||||
inline void
|
||||
ClampTri(STParticles::Position * p) {
|
||||
if (p->s<0.0f) {
|
||||
p->s=0.0f;
|
||||
} else if (p->s>1.0f) {
|
||||
p->s=1.0f;
|
||||
}
|
||||
if (p->t<0.0f) {
|
||||
p->t=0.0f;
|
||||
} else if (p->t>1.0f) {
|
||||
p->t=1.0f;
|
||||
}
|
||||
if ((p->s+p->t)>=1.0f) {
|
||||
p->s = 1.0f-p->t;
|
||||
p->t = 1.0f-p->s;
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
BounceTri(int edge, STParticles::Position * p, float * dp) {
|
||||
switch (edge) {
|
||||
case 0:
|
||||
assert(p->t<=0.0f);
|
||||
p->t = -p->t; dp[1] = -dp[1];
|
||||
break;
|
||||
case 1:
|
||||
assert((p->s+p->t)>=1.0f);
|
||||
p->s = 1.0f-p->s; dp[0] = -dp[0];
|
||||
p->t = 1.0f-p->t; dp[1] = -dp[1];
|
||||
break;
|
||||
case 2:
|
||||
assert(p->s<=0.0f);
|
||||
p->s = -p->s; dp[0] = -dp[0];
|
||||
break;
|
||||
}
|
||||
|
||||
// because 'diagonal' cases aren't handled, stick particles to edges when
|
||||
// if they cross 2 boundaries
|
||||
ClampTri(p);
|
||||
assert((p->s>=0.0f) && (p->s<=1.0f) && (p->t>=0.0f) && (p->t<=1.0f) &&
|
||||
((p->s+p->t)<=1.0f));
|
||||
}
|
||||
|
||||
void
|
||||
WarpTri(std::vector<STParticles::FaceInfo> const &,
|
||||
int edge, STParticles::Position * p, float * dp) {
|
||||
|
||||
// For now, particles on triangle meshes just bounce.
|
||||
BounceTri(edge, p, dp);
|
||||
assert((p->s>=0.0f) && (p->s<=1.0f) && (p->t>=0.0f) && (p->t<=1.0f) &&
|
||||
((p->s+p->t)<=1.0f));
|
||||
}
|
||||
|
||||
void
|
||||
ConstrainTri(STParticles::Position *p,
|
||||
float *dp,
|
||||
std::vector<STParticles::FaceInfo> const &adjacency) {
|
||||
|
||||
// make sure particles can't skip more than 1 face boundary at a time
|
||||
assert((p->s>-2.0f) && (p->s<2.0f) && (p->t>-2.0f) && (p->t<2.0f) &&
|
||||
((p->s+p->t)>-2.0f) && ((p->s+p->t)<2.0f));
|
||||
|
||||
// check if the particle is jumping a boundary
|
||||
// note: a particle can jump 2 edges at a time (a "diagonal" jump)
|
||||
// this is not treated here.
|
||||
int edge = -1;
|
||||
if (p->t <= 0.0f) edge = 0;
|
||||
if (p->s <= 0.0f) edge = 2;
|
||||
if ((p->s+p->t) >= 1.0f) edge = 1;
|
||||
|
||||
if (edge>=0) {
|
||||
// warp the particle to the other side of the boundary
|
||||
WarpTri(adjacency, edge, p, dp);
|
||||
}
|
||||
|
||||
assert((p->s>-2.0f) && (p->s<2.0f) && (p->t>-2.0f) && (p->t<2.0f) &&
|
||||
((p->s+p->t)>-2.0f) && ((p->s+p->t)<2.0f));
|
||||
}
|
||||
|
||||
void
|
||||
UpdateParticle(float speed,
|
||||
STParticles::Position *p,
|
||||
float *dp,
|
||||
Osd::PatchCoord *patchCoord,
|
||||
int regFaceSize,
|
||||
std::vector<STParticles::FaceInfo> const &adjacency,
|
||||
Far::PatchMap const *patchMap) {
|
||||
|
||||
// apply velocity
|
||||
p->s += dp[0] * speed;
|
||||
p->t += dp[1] * speed;
|
||||
|
||||
if (regFaceSize == 3) {
|
||||
ConstrainTri(p, dp, adjacency);
|
||||
} else {
|
||||
ConstrainQuad(p, dp, adjacency);
|
||||
}
|
||||
|
||||
// resolve particle positions into patch handles
|
||||
Far::PatchTable::PatchHandle const *handle =
|
||||
patchMap->FindPatch(p->ptexIndex, p->s, p->t);
|
||||
if (handle) {
|
||||
*patchCoord = Osd::PatchCoord(*handle, p->s, p->t);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
STParticles::Update(float deltaTime) {
|
||||
|
||||
if (deltaTime == 0) return;
|
||||
float speed = GetSpeed() * std::max(0.001f, std::min(deltaTime, 0.5f));
|
||||
|
||||
_patchCoords.resize(GetNumParticles());
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_TBB
|
||||
TbbUpdateKernel kernel(speed, &_positions[0], &_velocities[0],
|
||||
&_patchCoords[0],
|
||||
_regFaceSize, _adjacency, _patchMap);
|
||||
tbb::blocked_range<int> range(0, GetNumParticles(), 256);
|
||||
tbb::parallel_for(range, kernel);
|
||||
#else
|
||||
for (int i=0; i<GetNumParticles(); ++i) {
|
||||
Position * p = &_positions[i];
|
||||
float * dp = &_velocities[i*2];
|
||||
Osd::PatchCoord *patchCoord = &_patchCoords[i];
|
||||
|
||||
UpdateParticle(speed, p, dp, patchCoord, _regFaceSize, _adjacency, _patchMap);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Dump adjacency info
|
||||
std::ostream & operator << (std::ostream & os,
|
||||
STParticles::FaceInfo const & f) {
|
||||
|
||||
os << " adjface: " << f.adjfaces[0] << ' '
|
||||
<< f.adjfaces[1] << ' '
|
||||
<< f.adjfaces[2] << ' '
|
||||
<< f.adjfaces[3]
|
||||
<< " adjedge: " << f.adjedge(0) << ' '
|
||||
<< f.adjedge(1) << ' '
|
||||
<< f.adjedge(2) << ' '
|
||||
<< f.adjedge(3)
|
||||
<< " flags:";
|
||||
|
||||
if (f.flags == 0) {
|
||||
os << " (none)";
|
||||
} else {
|
||||
if (f.isSubface()) {
|
||||
std::cout << " subface";
|
||||
}
|
||||
}
|
||||
os << std::endl;
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream & operator << (std::ostream & os,
|
||||
STParticles const & particles) {
|
||||
|
||||
for (int i=0; i<(int)particles._adjacency.size(); ++i) {
|
||||
os << particles._adjacency[i];
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
155
blender-5.2.0/extern/opensubdiv-source/examples/glEvalLimit/particles.h
vendored
Normal file
155
blender-5.2.0/extern/opensubdiv-source/examples/glEvalLimit/particles.h
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef ST_PARTICLES_H
|
||||
#define ST_PARTICLES_H
|
||||
|
||||
#include <opensubdiv/far/topologyRefiner.h>
|
||||
#include <opensubdiv/far/patchMap.h>
|
||||
#include <opensubdiv/osd/types.h>
|
||||
#include <iostream>
|
||||
|
||||
//
|
||||
// In order to emphasize the dynamic nature of the EvalLimit API, where the
|
||||
// locations can be arbitrarily updated before each evaluation, the glEvalLimit
|
||||
// example treats each sample as a 'ST particle'.
|
||||
//
|
||||
// ST Particles are a simplified parametric-space particle dynamics simulation: each
|
||||
// particle is assigned a location on the subdivision surface limit that is
|
||||
// composed of a unique ptex face index, with a local (s,t) parametric pair.
|
||||
//
|
||||
// The system also generates an array of parametric velocities (ds, dt) for each
|
||||
// particle. An Update() function then applies the velocities to the locations and
|
||||
// moves the points along the parametric space.
|
||||
//
|
||||
// Face boundaries are managed using a ptex adjacency table obtained from the
|
||||
// Far::TopologyRefiner. Every time a particle moves outside of the [0.0f, 1.0f]
|
||||
// parametric range, a 'warp' function moves it to the neighboring face, or
|
||||
// bounces it, if the edge happens to be a boundary.
|
||||
//
|
||||
// Note: currently the adjacency code does not handle 'diagonal' crossings, nor
|
||||
// crossings between quad and non-quad faces.
|
||||
//
|
||||
class STParticles {
|
||||
|
||||
public:
|
||||
/// \brief Coordinates set on a limit surface
|
||||
///
|
||||
struct Position {
|
||||
Position() { }
|
||||
|
||||
/// \brief Constructor
|
||||
///
|
||||
/// @param f Ptex face id
|
||||
///
|
||||
/// @param x parametric location on face
|
||||
///
|
||||
/// @param y parametric location on face
|
||||
///
|
||||
Position(int f, float x, float y) : ptexIndex(f), s(x), t(y) { }
|
||||
|
||||
int ptexIndex; ///< ptex face index
|
||||
float s, t; ///< parametric location on face
|
||||
};
|
||||
|
||||
//
|
||||
// Topology adjacency (borrowed from Ptexture.h)
|
||||
//
|
||||
struct FaceInfo {
|
||||
|
||||
enum { flag_subface = 8 };
|
||||
|
||||
FaceInfo() : adjedges(0), flags(0) {
|
||||
adjfaces[0] = adjfaces[1] = adjfaces[2] = adjfaces[3] = -1;
|
||||
}
|
||||
|
||||
FaceInfo(int adjfaces_[4], int adjedges_[4], bool isSubface=false) :
|
||||
flags(isSubface ? flag_subface : 0) {
|
||||
setadjfaces(adjfaces_[0], adjfaces_[1], adjfaces_[2], adjfaces_[3]);
|
||||
setadjedges(adjedges_[0], adjedges_[1], adjedges_[2], adjedges_[3]);
|
||||
}
|
||||
|
||||
void setadjfaces(int f0, int f1, int f2, int f3) {
|
||||
adjfaces[0] = f0;
|
||||
adjfaces[1] = f1;
|
||||
adjfaces[2] = f2;
|
||||
adjfaces[3] = f3;
|
||||
}
|
||||
|
||||
void setadjedges(int e0, int e1, int e2, int e3) {
|
||||
adjedges = (e0&3) | ((e1&3)<<2) | ((e2&3)<<4) | ((e3&3)<<6);
|
||||
}
|
||||
|
||||
int adjface(int eid) const { return adjfaces[eid]; }
|
||||
|
||||
int adjedge(int eid) const { return int((adjedges >> (2*eid)) & 3); }
|
||||
|
||||
bool isSubface() const { return (flags & flag_subface) != 0; }
|
||||
|
||||
unsigned int adjedges :8,
|
||||
flags :8;
|
||||
int adjfaces[4];
|
||||
};
|
||||
|
||||
typedef OpenSubdiv::Far::TopologyRefiner Refiner;
|
||||
typedef OpenSubdiv::Far::PatchTable PatchTable;
|
||||
|
||||
STParticles(Refiner const & refiner, PatchTable const *patchTable,
|
||||
int nparticles, bool centered=false);
|
||||
|
||||
~STParticles();
|
||||
|
||||
void Update(float deltaTime);
|
||||
|
||||
int GetNumParticles() const {
|
||||
return (int)_positions.size();
|
||||
}
|
||||
|
||||
void SetSpeed(float speed) {
|
||||
_speed = std::max(-1.0f, std::min(1.0f, speed));
|
||||
}
|
||||
|
||||
float GetSpeed() const {
|
||||
return _speed;
|
||||
}
|
||||
|
||||
std::vector<Position> & GetPositions() {
|
||||
return _positions;
|
||||
}
|
||||
|
||||
std::vector<float> & GetVelocities() {
|
||||
return _velocities;
|
||||
}
|
||||
|
||||
std::vector<OpenSubdiv::Osd::PatchCoord> GetPatchCoords() const {
|
||||
return _patchCoords;
|
||||
}
|
||||
|
||||
friend std::ostream & operator << (std::ostream & os, STParticles const & f);
|
||||
|
||||
private:
|
||||
|
||||
//
|
||||
// Particle "Dynamics"
|
||||
//
|
||||
std::vector<Position> _positions;
|
||||
|
||||
std::vector<float> _velocities;
|
||||
|
||||
std::vector<OpenSubdiv::Osd::PatchCoord> _patchCoords;
|
||||
|
||||
float _speed; // velocity multiplier
|
||||
int _regFaceSize;
|
||||
|
||||
friend std::ostream & operator << (std::ostream & os, FaceInfo const & f);
|
||||
|
||||
|
||||
std::vector<FaceInfo> _adjacency;
|
||||
OpenSubdiv::Far::PatchMap const *_patchMap;
|
||||
};
|
||||
|
||||
#endif // ST_PARTICLES_H
|
||||
Reference in New Issue
Block a user