2015-07-20 15:27:47 +02:00
|
|
|
/*
|
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
*/
|
|
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup bke
|
2015-07-20 15:27:47 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifdef WITH_OPENSUBDIV
|
|
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
#include "BLI_sys_types.h" // for intptr_t support
|
|
|
|
|
|
|
|
|
|
#include "BLI_utildefines.h" /* for BLI_assert */
|
2015-11-04 21:30:25 +05:00
|
|
|
#include "BLI_listbase.h"
|
2015-07-20 15:27:47 +02:00
|
|
|
#include "BLI_math.h"
|
2015-11-04 21:30:25 +05:00
|
|
|
#include "BLI_threads.h"
|
2015-07-20 15:27:47 +02:00
|
|
|
|
|
|
|
|
#include "CCGSubSurf.h"
|
|
|
|
|
#include "CCGSubSurf_intern.h"
|
|
|
|
|
|
|
|
|
|
#include "BKE_DerivedMesh.h"
|
2015-11-04 21:30:25 +05:00
|
|
|
#include "BKE_subsurf.h"
|
2015-07-20 15:27:47 +02:00
|
|
|
|
|
|
|
|
#include "DNA_userdef_types.h"
|
|
|
|
|
|
|
|
|
|
#include "opensubdiv_capi.h"
|
|
|
|
|
#include "opensubdiv_converter_capi.h"
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
#include "opensubdiv_evaluator_capi.h"
|
|
|
|
|
#include "opensubdiv_gl_mesh_capi.h"
|
|
|
|
|
#include "opensubdiv_topology_refiner_capi.h"
|
2015-07-20 15:27:47 +02:00
|
|
|
|
2017-04-07 13:03:24 +02:00
|
|
|
#include "GPU_glew.h"
|
2015-12-18 23:16:52 +05:00
|
|
|
#include "GPU_extensions.h"
|
2015-07-20 15:27:47 +02:00
|
|
|
|
|
|
|
|
#define OSD_LOG if (false) printf
|
|
|
|
|
|
|
|
|
|
static bool compare_ccg_derivedmesh_topology(CCGSubSurf *ss, DerivedMesh *dm)
|
|
|
|
|
{
|
|
|
|
|
const int num_verts = dm->getNumVerts(dm);
|
|
|
|
|
const int num_edges = dm->getNumEdges(dm);
|
|
|
|
|
const int num_polys = dm->getNumPolys(dm);
|
|
|
|
|
const MEdge *medge = dm->getEdgeArray(dm);
|
|
|
|
|
const MLoop *mloop = dm->getLoopArray(dm);
|
|
|
|
|
const MPoly *mpoly = dm->getPolyArray(dm);
|
|
|
|
|
|
|
|
|
|
/* Quick preliminary tests based on the number of verts and facces. */
|
|
|
|
|
{
|
|
|
|
|
if (num_verts != ss->vMap->numEntries ||
|
|
|
|
|
num_edges != ss->eMap->numEntries ||
|
|
|
|
|
num_polys != ss->fMap->numEntries)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Rather slow check for faces topology change. */
|
|
|
|
|
{
|
|
|
|
|
CCGFaceIterator ccg_face_iter;
|
|
|
|
|
for (ccgSubSurf_initFaceIterator(ss, &ccg_face_iter);
|
|
|
|
|
!ccgFaceIterator_isStopped(&ccg_face_iter);
|
|
|
|
|
ccgFaceIterator_next(&ccg_face_iter))
|
|
|
|
|
{
|
|
|
|
|
/*const*/ CCGFace *ccg_face = ccgFaceIterator_getCurrent(&ccg_face_iter);
|
2018-09-19 12:05:58 +10:00
|
|
|
const int poly_index = POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(ccg_face));
|
2015-07-20 15:27:47 +02:00
|
|
|
const MPoly *mp = &mpoly[poly_index];
|
|
|
|
|
int corner;
|
|
|
|
|
if (ccg_face->numVerts != mp->totloop) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
for (corner = 0; corner < ccg_face->numVerts; corner++) {
|
|
|
|
|
/*const*/ CCGVert *ccg_vert = FACE_getVerts(ccg_face)[corner];
|
2018-09-19 12:05:58 +10:00
|
|
|
const int vert_index = POINTER_AS_INT(ccgSubSurf_getVertVertHandle(ccg_vert));
|
2015-07-20 15:27:47 +02:00
|
|
|
if (vert_index != mloop[mp->loopstart + corner].v) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check for edge topology change. */
|
|
|
|
|
{
|
|
|
|
|
CCGEdgeIterator ccg_edge_iter;
|
|
|
|
|
for (ccgSubSurf_initEdgeIterator(ss, &ccg_edge_iter);
|
|
|
|
|
!ccgEdgeIterator_isStopped(&ccg_edge_iter);
|
|
|
|
|
ccgEdgeIterator_next(&ccg_edge_iter))
|
|
|
|
|
{
|
|
|
|
|
/* const */ CCGEdge *ccg_edge = ccgEdgeIterator_getCurrent(&ccg_edge_iter);
|
|
|
|
|
/* const */ CCGVert *ccg_vert1 = ccg_edge->v0;
|
|
|
|
|
/* const */ CCGVert *ccg_vert2 = ccg_edge->v1;
|
2018-09-19 12:05:58 +10:00
|
|
|
const int ccg_vert1_index = POINTER_AS_INT(ccgSubSurf_getVertVertHandle(ccg_vert1));
|
|
|
|
|
const int ccg_vert2_index = POINTER_AS_INT(ccgSubSurf_getVertVertHandle(ccg_vert2));
|
|
|
|
|
const int edge_index = POINTER_AS_INT(ccgSubSurf_getEdgeEdgeHandle(ccg_edge));
|
2015-07-20 15:27:47 +02:00
|
|
|
const MEdge *me = &medge[edge_index];
|
|
|
|
|
if (me->v1 != ccg_vert1_index || me->v2 != ccg_vert2_index) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* TODO(sergey): Crease topology changes detection. */
|
|
|
|
|
{
|
|
|
|
|
CCGEdgeIterator ccg_edge_iter;
|
|
|
|
|
for (ccgSubSurf_initEdgeIterator(ss, &ccg_edge_iter);
|
|
|
|
|
!ccgEdgeIterator_isStopped(&ccg_edge_iter);
|
|
|
|
|
ccgEdgeIterator_next(&ccg_edge_iter))
|
|
|
|
|
{
|
|
|
|
|
/* const */ CCGEdge *ccg_edge = ccgEdgeIterator_getCurrent(&ccg_edge_iter);
|
2018-09-19 12:05:58 +10:00
|
|
|
const int edge_index = POINTER_AS_INT(ccgSubSurf_getEdgeEdgeHandle(ccg_edge));
|
2015-07-20 15:27:47 +02:00
|
|
|
if (ccg_edge->crease != medge[edge_index].crease) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool compare_osd_derivedmesh_topology(CCGSubSurf *ss, DerivedMesh *dm)
|
|
|
|
|
{
|
|
|
|
|
OpenSubdiv_Converter converter;
|
|
|
|
|
bool result;
|
|
|
|
|
if (ss->osd_mesh == NULL && ss->osd_topology_refiner == NULL) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
/* TODO(sergey): De-duplicate with topology counter at the bottom of
|
|
|
|
|
* the file.
|
|
|
|
|
*/
|
|
|
|
|
ccgSubSurf_converter_setup_from_derivedmesh(ss, dm, &converter);
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
result = openSubdiv_topologyRefinerCompareWithConverter(
|
|
|
|
|
ss->osd_topology_refiner,
|
|
|
|
|
&converter);
|
2015-07-20 15:27:47 +02:00
|
|
|
ccgSubSurf_converter_free(&converter);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool opensubdiv_is_topology_changed(CCGSubSurf *ss, DerivedMesh *dm)
|
|
|
|
|
{
|
|
|
|
|
if (ss->osd_compute != U.opensubdiv_compute_type) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (ss->osd_topology_refiner != NULL) {
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
const int levels = ss->osd_topology_refiner->getSubdivisionLevel(
|
2015-07-20 15:27:47 +02:00
|
|
|
ss->osd_topology_refiner);
|
|
|
|
|
BLI_assert(ss->osd_mesh_invalid == true);
|
|
|
|
|
if (levels != ss->subdivLevels) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (ss->skip_grids == false) {
|
|
|
|
|
return compare_ccg_derivedmesh_topology(ss, dm) == false;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
return compare_osd_derivedmesh_topology(ss, dm) == false;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ccgSubSurf_checkTopologyChanged(CCGSubSurf *ss, DerivedMesh *dm)
|
|
|
|
|
{
|
|
|
|
|
if (opensubdiv_is_topology_changed(ss, dm)) {
|
|
|
|
|
/* ** Make sure both GPU and CPU backends are properly reset. ** */
|
|
|
|
|
|
|
|
|
|
ss->osd_coarse_coords_invalid = true;
|
|
|
|
|
|
|
|
|
|
/* Reset GPU part. */
|
|
|
|
|
ss->osd_mesh_invalid = true;
|
|
|
|
|
if (ss->osd_topology_refiner != NULL) {
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
openSubdiv_deleteTopologyRefiner(ss->osd_topology_refiner);
|
2015-07-20 15:27:47 +02:00
|
|
|
ss->osd_topology_refiner = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-11 10:36:13 +02:00
|
|
|
/* Reset CPU side. */
|
2015-07-20 15:27:47 +02:00
|
|
|
if (ss->osd_evaluator != NULL) {
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
openSubdiv_deleteEvaluator(ss->osd_evaluator);
|
2015-07-20 15:27:47 +02:00
|
|
|
ss->osd_evaluator = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ccgSubSurf__updateGLMeshCoords(CCGSubSurf *ss)
|
|
|
|
|
{
|
|
|
|
|
BLI_assert(ss->meshIFC.numLayers == 3);
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
ss->osd_mesh->setCoarsePositions(ss->osd_mesh,
|
|
|
|
|
(float *) ss->osd_coarse_coords,
|
|
|
|
|
0,
|
|
|
|
|
ss->osd_num_coarse_coords);
|
2015-07-20 15:27:47 +02:00
|
|
|
}
|
|
|
|
|
|
2016-07-22 14:46:13 +02:00
|
|
|
bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss,
|
|
|
|
|
bool use_osd_glsl,
|
|
|
|
|
int active_uv_index)
|
2015-07-20 15:27:47 +02:00
|
|
|
{
|
|
|
|
|
int compute_type;
|
|
|
|
|
|
|
|
|
|
switch (U.opensubdiv_compute_type) {
|
|
|
|
|
#define CHECK_COMPUTE_TYPE(type) \
|
|
|
|
|
case USER_OPENSUBDIV_COMPUTE_ ## type: \
|
|
|
|
|
compute_type = OPENSUBDIV_EVALUATOR_ ## type; \
|
|
|
|
|
break;
|
|
|
|
|
CHECK_COMPUTE_TYPE(CPU)
|
|
|
|
|
CHECK_COMPUTE_TYPE(OPENMP)
|
|
|
|
|
CHECK_COMPUTE_TYPE(OPENCL)
|
|
|
|
|
CHECK_COMPUTE_TYPE(CUDA)
|
|
|
|
|
CHECK_COMPUTE_TYPE(GLSL_TRANSFORM_FEEDBACK)
|
|
|
|
|
CHECK_COMPUTE_TYPE(GLSL_COMPUTE)
|
2018-05-02 10:32:01 +02:00
|
|
|
default:
|
|
|
|
|
compute_type = OPENSUBDIV_EVALUATOR_CPU;
|
|
|
|
|
break;
|
2015-07-20 15:27:47 +02:00
|
|
|
#undef CHECK_COMPUTE_TYPE
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ss->osd_vao == 0) {
|
|
|
|
|
glGenVertexArrays(1, &ss->osd_vao);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ss->osd_mesh_invalid) {
|
|
|
|
|
if (ss->osd_mesh != NULL) {
|
2015-11-04 21:30:25 +05:00
|
|
|
ccgSubSurf__delete_osdGLMesh(ss->osd_mesh);
|
2015-07-20 15:27:47 +02:00
|
|
|
ss->osd_mesh = NULL;
|
|
|
|
|
}
|
|
|
|
|
ss->osd_mesh_invalid = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ss->osd_mesh == NULL) {
|
2015-07-29 13:09:49 +02:00
|
|
|
if (ss->osd_topology_refiner == NULL) {
|
|
|
|
|
/* Happens with empty meshes. */
|
2015-07-29 17:12:55 +02:00
|
|
|
/* TODO(sergey): Add assert that mesh is indeed empty. */
|
2015-07-29 13:09:49 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-20 15:27:47 +02:00
|
|
|
ss->osd_mesh = openSubdiv_createOsdGLMeshFromTopologyRefiner(
|
|
|
|
|
ss->osd_topology_refiner,
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
compute_type);
|
2015-07-20 15:27:47 +02:00
|
|
|
|
|
|
|
|
if (UNLIKELY(ss->osd_mesh == NULL)) {
|
|
|
|
|
/* Most likely compute device is not available. */
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ccgSubSurf__updateGLMeshCoords(ss);
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
ss->osd_mesh->refine(ss->osd_mesh);
|
|
|
|
|
ss->osd_mesh->synchronize(ss->osd_mesh);
|
2015-08-05 16:06:18 +02:00
|
|
|
ss->osd_coarse_coords_invalid = false;
|
2015-07-20 15:27:47 +02:00
|
|
|
|
|
|
|
|
glBindVertexArray(ss->osd_vao);
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
ss->osd_mesh->bindVertexBuffer(ss->osd_mesh);
|
2015-07-20 15:27:47 +02:00
|
|
|
|
|
|
|
|
glEnableVertexAttribArray(0);
|
|
|
|
|
glEnableVertexAttribArray(1);
|
|
|
|
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
|
|
|
|
|
sizeof(GLfloat) * 6, 0);
|
|
|
|
|
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,
|
|
|
|
|
sizeof(GLfloat) * 6, (float *)12);
|
|
|
|
|
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
2017-10-17 12:12:15 +02:00
|
|
|
glBindVertexArray(0);
|
2015-07-20 15:27:47 +02:00
|
|
|
}
|
|
|
|
|
else if (ss->osd_coarse_coords_invalid) {
|
|
|
|
|
ccgSubSurf__updateGLMeshCoords(ss);
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
ss->osd_mesh->refine(ss->osd_mesh);
|
|
|
|
|
ss->osd_mesh->synchronize(ss->osd_mesh);
|
2015-07-20 15:27:47 +02:00
|
|
|
ss->osd_coarse_coords_invalid = false;
|
|
|
|
|
}
|
|
|
|
|
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
ss->osd_mesh->prepareDraw(ss->osd_mesh, use_osd_glsl, active_uv_index);
|
2015-07-20 15:27:47 +02:00
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ccgSubSurf_drawGLMesh(CCGSubSurf *ss, bool fill_quads,
|
|
|
|
|
int start_partition, int num_partitions)
|
|
|
|
|
{
|
|
|
|
|
if (LIKELY(ss->osd_mesh != NULL)) {
|
2017-10-17 12:12:15 +02:00
|
|
|
glBindVertexArray(ss->osd_vao);
|
2015-07-20 15:27:47 +02:00
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
ss->osd_mesh->getPatchIndexBuffer(ss->osd_mesh));
|
2015-07-20 15:27:47 +02:00
|
|
|
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
ss->osd_mesh->bindVertexBuffer(ss->osd_mesh);
|
2015-07-20 15:27:47 +02:00
|
|
|
glBindVertexArray(ss->osd_vao);
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
ss->osd_mesh->drawPatches(ss->osd_mesh, fill_quads,
|
|
|
|
|
start_partition, num_partitions);
|
2015-07-20 15:27:47 +02:00
|
|
|
glBindVertexArray(0);
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-25 15:05:28 +02:00
|
|
|
int ccgSubSurf_getNumGLMeshBaseFaces(CCGSubSurf *ss)
|
|
|
|
|
{
|
|
|
|
|
if (ss->osd_topology_refiner != NULL) {
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
return ss->osd_topology_refiner->getNumFaces(
|
|
|
|
|
ss->osd_topology_refiner);
|
2015-09-22 21:10:23 +05:00
|
|
|
}
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
return 0;
|
2015-08-25 15:05:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get number of vertices in base faces in a particular GL mesh. */
|
|
|
|
|
int ccgSubSurf_getNumGLMeshBaseFaceVerts(CCGSubSurf *ss, int face)
|
|
|
|
|
{
|
|
|
|
|
if (ss->osd_topology_refiner != NULL) {
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
return ss->osd_topology_refiner->getNumFaceVertices(
|
|
|
|
|
ss->osd_topology_refiner, face);
|
2015-09-22 21:10:23 +05:00
|
|
|
}
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
return 0;
|
2015-08-25 15:05:28 +02:00
|
|
|
}
|
|
|
|
|
|
2015-07-20 15:27:47 +02:00
|
|
|
void ccgSubSurf_setSkipGrids(CCGSubSurf *ss, bool skip_grids)
|
|
|
|
|
{
|
|
|
|
|
ss->skip_grids = skip_grids;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ccgSubSurf_needGrids(CCGSubSurf *ss)
|
|
|
|
|
{
|
|
|
|
|
return ss->skip_grids == false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLI_INLINE void ccgSubSurf__mapGridToFace(int S, float grid_u, float grid_v,
|
|
|
|
|
float *face_u, float *face_v)
|
|
|
|
|
{
|
|
|
|
|
float u, v;
|
|
|
|
|
|
|
|
|
|
/* - Each grid covers half of the face along the edges.
|
|
|
|
|
* - Grid's (0, 0) starts from the middle of the face.
|
|
|
|
|
*/
|
|
|
|
|
u = 0.5f - 0.5f * grid_u;
|
|
|
|
|
v = 0.5f - 0.5f * grid_v;
|
|
|
|
|
|
|
|
|
|
if (S == 0) {
|
|
|
|
|
*face_u = v;
|
|
|
|
|
*face_v = u;
|
|
|
|
|
}
|
|
|
|
|
else if (S == 1) {
|
|
|
|
|
*face_u = 1.0f - u;
|
|
|
|
|
*face_v = v;
|
|
|
|
|
}
|
|
|
|
|
else if (S == 2) {
|
|
|
|
|
*face_u = 1.0f - v;
|
|
|
|
|
*face_v = 1.0f - u;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
*face_u = u;
|
|
|
|
|
*face_v = 1.0f - v;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLI_INLINE void ccgSubSurf__mapEdgeToFace(int S,
|
|
|
|
|
int edge_segment,
|
|
|
|
|
bool inverse_edge,
|
|
|
|
|
int edgeSize,
|
|
|
|
|
float *face_u, float *face_v)
|
|
|
|
|
{
|
|
|
|
|
int t = inverse_edge ? edgeSize - edge_segment - 1 : edge_segment;
|
|
|
|
|
if (S == 0) {
|
|
|
|
|
*face_u = (float) t / (edgeSize - 1);
|
|
|
|
|
*face_v = 0.0f;
|
|
|
|
|
}
|
|
|
|
|
else if (S == 1) {
|
|
|
|
|
*face_u = 1.0f;
|
|
|
|
|
*face_v = (float) t / (edgeSize - 1);
|
|
|
|
|
}
|
|
|
|
|
else if (S == 2) {
|
|
|
|
|
*face_u = 1.0f - (float) t / (edgeSize - 1);
|
|
|
|
|
*face_v = 1.0f;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
*face_u = 0.0f;
|
|
|
|
|
*face_v = 1.0f - (float) t / (edgeSize - 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ccgSubSurf_evaluatorSetFVarUV(CCGSubSurf *ss,
|
|
|
|
|
DerivedMesh *dm,
|
|
|
|
|
int layer_index)
|
|
|
|
|
{
|
|
|
|
|
MPoly *mpoly = dm->getPolyArray(dm);
|
|
|
|
|
MLoopUV *mloopuv = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, layer_index);
|
|
|
|
|
int num_polys = dm->getNumPolys(dm);
|
|
|
|
|
int index, poly;
|
|
|
|
|
BLI_assert(ss->osd_evaluator != NULL);
|
|
|
|
|
for (poly = 0, index = 0; poly < num_polys; poly++) {
|
|
|
|
|
int loop;
|
|
|
|
|
MPoly *mp = &mpoly[poly];
|
|
|
|
|
for (loop = 0; loop < mp->totloop; loop++, index++) {
|
|
|
|
|
MLoopUV *mluv = &mloopuv[loop + mp->loopstart];
|
|
|
|
|
(void)mluv;
|
|
|
|
|
/* TODO(sergey): Send mluv->uv to the evaluator's face varying
|
|
|
|
|
* buffer.
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
(void)ss;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ccgSubSurf_evaluatorFVarUV(CCGSubSurf *ss,
|
|
|
|
|
int face_index, int S,
|
|
|
|
|
float grid_u, float grid_v,
|
|
|
|
|
float uv[2])
|
|
|
|
|
{
|
|
|
|
|
float face_u, face_v;
|
|
|
|
|
ccgSubSurf__mapGridToFace(S,
|
|
|
|
|
grid_u, grid_v,
|
|
|
|
|
&face_u, &face_v);
|
|
|
|
|
(void)ss;
|
|
|
|
|
(void)face_index;
|
|
|
|
|
/* TODO(sergey): Evaluate face varying coordinate. */
|
|
|
|
|
zero_v2(uv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool opensubdiv_createEvaluator(CCGSubSurf *ss)
|
|
|
|
|
{
|
|
|
|
|
OpenSubdiv_Converter converter;
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
OpenSubdiv_TopologyRefiner *topology_refiner;
|
2015-07-29 13:09:49 +02:00
|
|
|
if (ss->fMap->numEntries == 0) {
|
2015-07-29 17:12:55 +02:00
|
|
|
/* OpenSubdiv doesn't support meshes without faces. */
|
2015-07-29 13:09:49 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
2015-07-20 15:27:47 +02:00
|
|
|
ccgSubSurf_converter_setup_from_ccg(ss, &converter);
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
OpenSubdiv_TopologyRefinerSettings settings;
|
|
|
|
|
settings.level = ss->subdivLevels;
|
|
|
|
|
settings.is_adaptive = false;
|
|
|
|
|
topology_refiner =
|
|
|
|
|
openSubdiv_createTopologyRefinerFromConverter(
|
|
|
|
|
&converter, &settings);
|
2015-07-20 15:27:47 +02:00
|
|
|
ccgSubSurf_converter_free(&converter);
|
|
|
|
|
ss->osd_evaluator =
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
openSubdiv_createEvaluatorFromTopologyRefiner(topology_refiner);
|
2015-07-29 13:09:49 +02:00
|
|
|
if (ss->osd_evaluator == NULL) {
|
2015-07-29 17:12:55 +02:00
|
|
|
BLI_assert(!"OpenSubdiv initialization failed, should not happen.");
|
2015-07-29 13:09:49 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
2015-07-20 15:27:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool opensubdiv_ensureEvaluator(CCGSubSurf *ss)
|
|
|
|
|
{
|
|
|
|
|
if (ss->osd_evaluator == NULL) {
|
|
|
|
|
OSD_LOG("Allocating new evaluator, %d verts\n", ss->vMap->numEntries);
|
|
|
|
|
opensubdiv_createEvaluator(ss);
|
|
|
|
|
}
|
|
|
|
|
return ss->osd_evaluator != NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void opensubdiv_updateEvaluatorCoarsePositions(CCGSubSurf *ss)
|
|
|
|
|
{
|
|
|
|
|
float (*positions)[3];
|
|
|
|
|
int vertDataSize = ss->meshIFC.vertDataSize;
|
|
|
|
|
int num_basis_verts = ss->vMap->numEntries;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
/* TODO(sergey): Avoid allocation on every update. We could either update
|
|
|
|
|
* coordinates in chunks of 1K vertices (which will only use stack memory)
|
|
|
|
|
* or do some callback magic for OSD evaluator can invoke it and fill in
|
|
|
|
|
* buffer directly.
|
|
|
|
|
*/
|
|
|
|
|
if (ss->meshIFC.numLayers == 3) {
|
|
|
|
|
/* If all the components are to be initialized, no need to memset the
|
|
|
|
|
* new memory block.
|
|
|
|
|
*/
|
|
|
|
|
positions = MEM_mallocN(3 * sizeof(float) * num_basis_verts,
|
|
|
|
|
"OpenSubdiv coarse points");
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* Calloc in order to have z component initialized to 0 for Uvs */
|
|
|
|
|
positions = MEM_callocN(3 * sizeof(float) * num_basis_verts,
|
|
|
|
|
"OpenSubdiv coarse points");
|
|
|
|
|
}
|
|
|
|
|
#pragma omp parallel for
|
|
|
|
|
for (i = 0; i < ss->vMap->curSize; i++) {
|
|
|
|
|
CCGVert *v = (CCGVert *) ss->vMap->buckets[i];
|
|
|
|
|
for (; v; v = v->next) {
|
|
|
|
|
float *co = VERT_getCo(v, 0);
|
|
|
|
|
BLI_assert(v->osd_index < ss->vMap->numEntries);
|
|
|
|
|
VertDataCopy(positions[v->osd_index], co, ss);
|
|
|
|
|
OSD_LOG("Point %d has value %f %f %f\n",
|
|
|
|
|
v->osd_index,
|
|
|
|
|
positions[v->osd_index][0],
|
|
|
|
|
positions[v->osd_index][1],
|
|
|
|
|
positions[v->osd_index][2]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
ss->osd_evaluator->setCoarsePositions(ss->osd_evaluator,
|
|
|
|
|
(float *)positions,
|
|
|
|
|
0,
|
|
|
|
|
num_basis_verts);
|
|
|
|
|
ss->osd_evaluator->refine(ss->osd_evaluator);
|
2015-07-20 15:27:47 +02:00
|
|
|
|
|
|
|
|
MEM_freeN(positions);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void opensubdiv_evaluateQuadFaceGrids(CCGSubSurf *ss,
|
|
|
|
|
CCGFace *face,
|
|
|
|
|
const int osd_face_index)
|
|
|
|
|
{
|
|
|
|
|
int normalDataOffset = ss->normalDataOffset;
|
|
|
|
|
int subdivLevels = ss->subdivLevels;
|
|
|
|
|
int gridSize = ccg_gridsize(subdivLevels);
|
|
|
|
|
int edgeSize = ccg_edgesize(subdivLevels);
|
|
|
|
|
int vertDataSize = ss->meshIFC.vertDataSize;
|
|
|
|
|
int S;
|
|
|
|
|
bool do_normals = ss->meshIFC.numLayers == 3;
|
|
|
|
|
|
|
|
|
|
#pragma omp parallel for
|
|
|
|
|
for (S = 0; S < face->numVerts; S++) {
|
|
|
|
|
int x, y, k;
|
|
|
|
|
CCGEdge *edge = NULL;
|
2018-05-13 14:10:05 +02:00
|
|
|
bool inverse_edge = false;
|
2015-07-20 15:27:47 +02:00
|
|
|
|
|
|
|
|
for (x = 0; x < gridSize; x++) {
|
|
|
|
|
for (y = 0; y < gridSize; y++) {
|
|
|
|
|
float *co = FACE_getIFCo(face, subdivLevels, S, x, y);
|
|
|
|
|
float *no = FACE_getIFNo(face, subdivLevels, S, x, y);
|
|
|
|
|
float grid_u = (float) x / (gridSize - 1),
|
|
|
|
|
grid_v = (float) y / (gridSize - 1);
|
|
|
|
|
float face_u, face_v;
|
|
|
|
|
float P[3], dPdu[3], dPdv[3];
|
|
|
|
|
|
|
|
|
|
ccgSubSurf__mapGridToFace(S, grid_u, grid_v, &face_u, &face_v);
|
|
|
|
|
|
|
|
|
|
/* TODO(sergey): Need proper port. */
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
ss->osd_evaluator->evaluateLimit(
|
|
|
|
|
ss->osd_evaluator, osd_face_index,
|
|
|
|
|
face_u, face_v,
|
|
|
|
|
P,
|
|
|
|
|
do_normals ? dPdu : NULL,
|
|
|
|
|
do_normals ? dPdv : NULL);
|
2015-07-20 15:27:47 +02:00
|
|
|
|
|
|
|
|
OSD_LOG("face=%d, corner=%d, grid_u=%f, grid_v=%f, face_u=%f, face_v=%f, P=(%f, %f, %f)\n",
|
|
|
|
|
osd_face_index, S, grid_u, grid_v, face_u, face_v, P[0], P[1], P[2]);
|
|
|
|
|
|
|
|
|
|
VertDataCopy(co, P, ss);
|
|
|
|
|
if (do_normals) {
|
|
|
|
|
cross_v3_v3v3(no, dPdu, dPdv);
|
|
|
|
|
normalize_v3(no);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (x == gridSize - 1 && y == gridSize - 1) {
|
|
|
|
|
float *vert_co = VERT_getCo(FACE_getVerts(face)[S], subdivLevels);
|
|
|
|
|
VertDataCopy(vert_co, co, ss);
|
|
|
|
|
if (do_normals) {
|
|
|
|
|
float *vert_no = VERT_getNo(FACE_getVerts(face)[S], subdivLevels);
|
|
|
|
|
VertDataCopy(vert_no, no, ss);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (S == 0 && x == 0 && y == 0) {
|
|
|
|
|
float *center_co = (float *)FACE_getCenterData(face);
|
|
|
|
|
VertDataCopy(center_co, co, ss);
|
|
|
|
|
if (do_normals) {
|
|
|
|
|
float *center_no = (float *)((byte *)FACE_getCenterData(face) + normalDataOffset);
|
|
|
|
|
VertDataCopy(center_no, no, ss);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (x = 0; x < gridSize; x++) {
|
|
|
|
|
VertDataCopy(FACE_getIECo(face, subdivLevels, S, x),
|
|
|
|
|
FACE_getIFCo(face, subdivLevels, S, x, 0), ss);
|
|
|
|
|
if (do_normals) {
|
|
|
|
|
VertDataCopy(FACE_getIENo(face, subdivLevels, S, x),
|
|
|
|
|
FACE_getIFNo(face, subdivLevels, S, x, 0), ss);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (k = 0; k < face->numVerts; k++) {
|
|
|
|
|
CCGEdge *current_edge = FACE_getEdges(face)[k];
|
|
|
|
|
CCGVert **face_verts = FACE_getVerts(face);
|
|
|
|
|
if (current_edge->v0 == face_verts[S] &&
|
|
|
|
|
current_edge->v1 == face_verts[(S + 1) % face->numVerts])
|
|
|
|
|
{
|
|
|
|
|
edge = current_edge;
|
|
|
|
|
inverse_edge = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (current_edge->v1 == face_verts[S] &&
|
|
|
|
|
current_edge->v0 == face_verts[(S + 1) % face->numVerts])
|
|
|
|
|
{
|
|
|
|
|
edge = current_edge;
|
|
|
|
|
inverse_edge = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLI_assert(edge != NULL);
|
|
|
|
|
|
|
|
|
|
for (x = 0; x < edgeSize; x++) {
|
|
|
|
|
float u = 0, v = 0;
|
|
|
|
|
float *co = EDGE_getCo(edge, subdivLevels, x);
|
|
|
|
|
float *no = EDGE_getNo(edge, subdivLevels, x);
|
|
|
|
|
float P[3], dPdu[3], dPdv[3];
|
|
|
|
|
ccgSubSurf__mapEdgeToFace(S, x,
|
|
|
|
|
inverse_edge,
|
|
|
|
|
edgeSize,
|
|
|
|
|
&u, &v);
|
|
|
|
|
|
|
|
|
|
/* TODO(sergey): Ideally we will re-use grid here, but for now
|
|
|
|
|
* let's just re-evaluate for simplicity.
|
|
|
|
|
*/
|
|
|
|
|
/* TODO(sergey): Need proper port. */
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
ss->osd_evaluator->evaluateLimit(
|
|
|
|
|
ss->osd_evaluator,
|
|
|
|
|
osd_face_index,
|
|
|
|
|
u, v,
|
|
|
|
|
P, dPdu, dPdv);
|
2015-07-20 15:27:47 +02:00
|
|
|
VertDataCopy(co, P, ss);
|
|
|
|
|
if (do_normals) {
|
|
|
|
|
cross_v3_v3v3(no, dPdu, dPdv);
|
|
|
|
|
normalize_v3(no);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void opensubdiv_evaluateNGonFaceGrids(CCGSubSurf *ss,
|
|
|
|
|
CCGFace *face,
|
|
|
|
|
const int osd_face_index)
|
|
|
|
|
{
|
|
|
|
|
CCGVert **all_verts = FACE_getVerts(face);
|
|
|
|
|
int normalDataOffset = ss->normalDataOffset;
|
|
|
|
|
int subdivLevels = ss->subdivLevels;
|
|
|
|
|
int gridSize = ccg_gridsize(subdivLevels);
|
|
|
|
|
int edgeSize = ccg_edgesize(subdivLevels);
|
|
|
|
|
int vertDataSize = ss->meshIFC.vertDataSize;
|
|
|
|
|
int S;
|
|
|
|
|
bool do_normals = ss->meshIFC.numLayers == 3;
|
|
|
|
|
|
|
|
|
|
/* Note about handling non-quad faces.
|
|
|
|
|
*
|
|
|
|
|
* In order to deal with non-quad faces we need to split them
|
|
|
|
|
* into a quads in the following way:
|
|
|
|
|
*
|
|
|
|
|
* |
|
|
|
|
|
* (vert_next)
|
|
|
|
|
* |
|
|
|
|
|
* |
|
|
|
|
|
* |
|
|
|
|
|
* (face_center) ------------------- (v2)
|
|
|
|
|
* | (o)--------------------> |
|
|
|
|
|
* | | v |
|
|
|
|
|
* | | |
|
|
|
|
|
* | | |
|
|
|
|
|
* | | |
|
|
|
|
|
* | | y ^ |
|
|
|
|
|
* | | | |
|
|
|
|
|
* | v u x | |
|
|
|
|
|
* | <---(o) |
|
|
|
|
|
* ---- (vert_prev) ---- (v1) -------------------- (vert)
|
|
|
|
|
*
|
|
|
|
|
* This is how grids are expected to be stored and it's how
|
|
|
|
|
* OpenSubdiv deals with non-quad faces using ptex face indices.
|
|
|
|
|
* We only need to convert ptex (x, y) to grid (u, v) by some
|
|
|
|
|
* simple flips and evaluate the ptex face.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* Evaluate face grids. */
|
|
|
|
|
#pragma omp parallel for
|
|
|
|
|
for (S = 0; S < face->numVerts; S++) {
|
|
|
|
|
int x, y;
|
|
|
|
|
for (x = 0; x < gridSize; x++) {
|
|
|
|
|
for (y = 0; y < gridSize; y++) {
|
|
|
|
|
float *co = FACE_getIFCo(face, subdivLevels, S, x, y);
|
|
|
|
|
float *no = FACE_getIFNo(face, subdivLevels, S, x, y);
|
|
|
|
|
float u = 1.0f - (float) y / (gridSize - 1),
|
|
|
|
|
v = 1.0f - (float) x / (gridSize - 1);
|
|
|
|
|
float P[3], dPdu[3], dPdv[3];
|
|
|
|
|
|
|
|
|
|
/* TODO(sergey): Need proper port. */
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
ss->osd_evaluator->evaluateLimit(
|
|
|
|
|
ss->osd_evaluator,
|
|
|
|
|
osd_face_index + S,
|
|
|
|
|
u, v,
|
|
|
|
|
P, dPdu, dPdv);
|
2015-07-20 15:27:47 +02:00
|
|
|
|
|
|
|
|
OSD_LOG("face=%d, corner=%d, u=%f, v=%f, P=(%f, %f, %f)\n",
|
|
|
|
|
osd_face_index + S, S, u, v, P[0], P[1], P[2]);
|
|
|
|
|
|
|
|
|
|
VertDataCopy(co, P, ss);
|
|
|
|
|
if (do_normals) {
|
|
|
|
|
cross_v3_v3v3(no, dPdu, dPdv);
|
|
|
|
|
normalize_v3(no);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* TODO(sergey): De-dpuplicate with the quad case. */
|
|
|
|
|
if (x == gridSize - 1 && y == gridSize - 1) {
|
|
|
|
|
float *vert_co = VERT_getCo(FACE_getVerts(face)[S], subdivLevels);
|
|
|
|
|
VertDataCopy(vert_co, co, ss);
|
|
|
|
|
if (do_normals) {
|
|
|
|
|
float *vert_no = VERT_getNo(FACE_getVerts(face)[S], subdivLevels);
|
|
|
|
|
VertDataCopy(vert_no, no, ss);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (S == 0 && x == 0 && y == 0) {
|
|
|
|
|
float *center_co = (float *)FACE_getCenterData(face);
|
|
|
|
|
VertDataCopy(center_co, co, ss);
|
|
|
|
|
if (do_normals) {
|
|
|
|
|
float *center_no = (float *)((byte *)FACE_getCenterData(face) + normalDataOffset);
|
|
|
|
|
VertDataCopy(center_no, no, ss);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (x = 0; x < gridSize; x++) {
|
|
|
|
|
VertDataCopy(FACE_getIECo(face, subdivLevels, S, x),
|
|
|
|
|
FACE_getIFCo(face, subdivLevels, S, x, 0), ss);
|
|
|
|
|
if (do_normals) {
|
|
|
|
|
VertDataCopy(FACE_getIENo(face, subdivLevels, S, x),
|
|
|
|
|
FACE_getIFNo(face, subdivLevels, S, x, 0), ss);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Evaluate edges. */
|
|
|
|
|
for (S = 0; S < face->numVerts; S++) {
|
|
|
|
|
CCGEdge *edge = FACE_getEdges(face)[S];
|
2018-05-02 10:32:01 +02:00
|
|
|
int x, S0 = 0, S1 = 0;
|
2015-07-20 15:27:47 +02:00
|
|
|
bool flip;
|
|
|
|
|
|
|
|
|
|
for (x = 0; x < face->numVerts; ++x) {
|
|
|
|
|
if (all_verts[x] == edge->v0) {
|
|
|
|
|
S0 = x;
|
|
|
|
|
}
|
|
|
|
|
else if (all_verts[x] == edge->v1) {
|
|
|
|
|
S1 = x;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (S == face->numVerts - 1) {
|
|
|
|
|
flip = S0 > S1;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
flip = S0 < S1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (x = 0; x <= edgeSize / 2; x++) {
|
|
|
|
|
float *edge_co = EDGE_getCo(edge, subdivLevels, x);
|
|
|
|
|
float *edge_no = EDGE_getNo(edge, subdivLevels, x);
|
|
|
|
|
float *face_edge_co;
|
|
|
|
|
float *face_edge_no;
|
|
|
|
|
if (flip) {
|
|
|
|
|
face_edge_co = FACE_getIFCo(face, subdivLevels, S0, gridSize - 1, gridSize - 1 - x);
|
|
|
|
|
face_edge_no = FACE_getIFNo(face, subdivLevels, S0, gridSize - 1, gridSize - 1 - x);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
face_edge_co = FACE_getIFCo(face, subdivLevels, S0, gridSize - 1 - x, gridSize - 1);
|
|
|
|
|
face_edge_no = FACE_getIFNo(face, subdivLevels, S0, gridSize - 1 - x, gridSize - 1);
|
|
|
|
|
}
|
|
|
|
|
VertDataCopy(edge_co, face_edge_co, ss);
|
|
|
|
|
if (do_normals) {
|
|
|
|
|
VertDataCopy(edge_no, face_edge_no, ss);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (x = edgeSize / 2 + 1; x < edgeSize; x++) {
|
|
|
|
|
float *edge_co = EDGE_getCo(edge, subdivLevels, x);
|
|
|
|
|
float *edge_no = EDGE_getNo(edge, subdivLevels, x);
|
|
|
|
|
float *face_edge_co;
|
|
|
|
|
float *face_edge_no;
|
|
|
|
|
if (flip) {
|
|
|
|
|
face_edge_co = FACE_getIFCo(face, subdivLevels, S1, x - edgeSize / 2, gridSize - 1);
|
|
|
|
|
face_edge_no = FACE_getIFNo(face, subdivLevels, S1, x - edgeSize / 2, gridSize - 1);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
face_edge_co = FACE_getIFCo(face, subdivLevels, S1, gridSize - 1, x - edgeSize / 2);
|
|
|
|
|
face_edge_no = FACE_getIFNo(face, subdivLevels, S1, gridSize - 1, x - edgeSize / 2);
|
|
|
|
|
}
|
|
|
|
|
VertDataCopy(edge_co, face_edge_co, ss);
|
|
|
|
|
if (do_normals) {
|
|
|
|
|
VertDataCopy(edge_no, face_edge_no, ss);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void opensubdiv_evaluateGrids(CCGSubSurf *ss)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
for (i = 0; i < ss->fMap->curSize; i++) {
|
|
|
|
|
CCGFace *face = (CCGFace *) ss->fMap->buckets[i];
|
|
|
|
|
for (; face; face = face->next) {
|
|
|
|
|
if (face->numVerts == 4) {
|
|
|
|
|
/* For quads we do special magic with converting face coords
|
|
|
|
|
* into corner coords and interpolating grids from it.
|
|
|
|
|
*/
|
|
|
|
|
opensubdiv_evaluateQuadFaceGrids(ss, face, face->osd_index);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* NGons and tris are split into separate osd faces which
|
|
|
|
|
* evaluates onto grids directly.
|
|
|
|
|
*/
|
|
|
|
|
opensubdiv_evaluateNGonFaceGrids(ss, face, face->osd_index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CCGError ccgSubSurf_initOpenSubdivSync(CCGSubSurf *ss)
|
|
|
|
|
{
|
|
|
|
|
if (ss->syncState != eSyncState_None) {
|
|
|
|
|
return eCCGError_InvalidSyncState;
|
|
|
|
|
}
|
|
|
|
|
ss->syncState = eSyncState_OpenSubdiv;
|
|
|
|
|
return eCCGError_None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ccgSubSurf_prepareTopologyRefiner(CCGSubSurf *ss, DerivedMesh *dm)
|
|
|
|
|
{
|
|
|
|
|
if (ss->osd_mesh == NULL || ss->osd_mesh_invalid) {
|
2015-07-29 13:09:49 +02:00
|
|
|
if (dm->getNumPolys(dm) != 0) {
|
|
|
|
|
OpenSubdiv_Converter converter;
|
|
|
|
|
ccgSubSurf_converter_setup_from_derivedmesh(ss, dm, &converter);
|
|
|
|
|
/* TODO(sergey): Remove possibly previously allocated refiner. */
|
OpenSubdiv: Re-work C-API integration
Main goal is to make API simpler to follow (at least ion terms what
is defined/declared where, as opposite of handful big headers which
includes all the declarations), and also avoid a big set of long and
obscure functions.
Now C-API files are split into smaller ones, following OpenSubdiv
behavior more closely, and also function pointers in structures
used a lot more, which shortens functions names,
UV integration part in GL Mesh is mainly stripped away, it needs
to be done differently. On a related topic, UV coordinates API in
converter needs to be removed as well, we do not need coordinates,
only island connectivity information there.
Additional changes:
- Varying interpolation in evaluator API are temporarily disabled,
need to extend API somewhere (probably, evaluator's API) to inform
layout information of vertex data (whether it contains varying
data, width, stride and such).
- Evaluator now can interpolate face-varying data.
Only works for adaptive refiner, since some issues in OpenSubdiv
itself.
Planned changes:
- Remove uv coordinates from TopologyConverter.
- Support evaluation of patches (as opposite to individual coordinates
as it happens currently).
- Support more flexible layout of varying and face-varying data.
It is stupid to assume varying is 3 floats and face-varying 2 floats.
- Support of second order derivatives.
- Everything else what i'm missing in this list.
2018-07-16 09:28:05 +02:00
|
|
|
OpenSubdiv_TopologyRefinerSettings settings;
|
|
|
|
|
settings.level = ss->subdivLevels;
|
|
|
|
|
settings.is_adaptive = false;
|
|
|
|
|
ss->osd_topology_refiner =
|
|
|
|
|
openSubdiv_createTopologyRefinerFromConverter(
|
|
|
|
|
&converter, &settings);
|
2015-07-29 13:09:49 +02:00
|
|
|
ccgSubSurf_converter_free(&converter);
|
|
|
|
|
}
|
2015-07-20 15:27:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Update number of grids, needed for things like final faces
|
|
|
|
|
* counter, used by display drawing.
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
const int num_polys = dm->getNumPolys(dm);
|
|
|
|
|
const MPoly *mpoly = dm->getPolyArray(dm);
|
|
|
|
|
int poly;
|
|
|
|
|
ss->numGrids = 0;
|
|
|
|
|
for (poly = 0; poly < num_polys; ++poly) {
|
|
|
|
|
ss->numGrids += mpoly[poly].totloop;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const int num_verts = dm->getNumVerts(dm);
|
|
|
|
|
const MVert *mvert = dm->getVertArray(dm);
|
|
|
|
|
int vert;
|
|
|
|
|
if (ss->osd_coarse_coords != NULL &&
|
|
|
|
|
num_verts != ss->osd_num_coarse_coords)
|
|
|
|
|
{
|
|
|
|
|
MEM_freeN(ss->osd_coarse_coords);
|
|
|
|
|
ss->osd_coarse_coords = NULL;
|
|
|
|
|
}
|
|
|
|
|
if (ss->osd_coarse_coords == NULL) {
|
|
|
|
|
ss->osd_coarse_coords = MEM_mallocN(sizeof(float) * 6 * num_verts, "osd coarse positions");
|
|
|
|
|
}
|
|
|
|
|
for (vert = 0; vert < num_verts; vert++) {
|
|
|
|
|
copy_v3_v3(ss->osd_coarse_coords[vert * 2 + 0], mvert[vert].co);
|
|
|
|
|
normal_short_to_float_v3(ss->osd_coarse_coords[vert * 2 + 1], mvert[vert].no);
|
|
|
|
|
}
|
|
|
|
|
ss->osd_num_coarse_coords = num_verts;
|
|
|
|
|
ss->osd_coarse_coords_invalid = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ccgSubSurf__sync_opensubdiv(CCGSubSurf *ss)
|
|
|
|
|
{
|
|
|
|
|
BLI_assert(ss->meshIFC.numLayers == 2 || ss->meshIFC.numLayers == 3);
|
|
|
|
|
|
|
|
|
|
/* Common synchronization steps */
|
|
|
|
|
ss->osd_compute = U.opensubdiv_compute_type;
|
|
|
|
|
|
|
|
|
|
if (ss->skip_grids == false) {
|
|
|
|
|
/* Make sure OSD evaluator is up-to-date. */
|
|
|
|
|
if (opensubdiv_ensureEvaluator(ss)) {
|
|
|
|
|
/* Update coarse points in the OpenSubdiv evaluator. */
|
|
|
|
|
opensubdiv_updateEvaluatorCoarsePositions(ss);
|
|
|
|
|
|
|
|
|
|
/* Evaluate opensubdiv mesh into the CCG grids. */
|
|
|
|
|
opensubdiv_evaluateGrids(ss);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
BLI_assert(ss->meshIFC.numLayers == 3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef DUMP_RESULT_GRIDS
|
|
|
|
|
ccgSubSurf__dumpCoords(ss);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-05 14:15:46 +02:00
|
|
|
void ccgSubSurf_free_osd_mesh(CCGSubSurf *ss)
|
|
|
|
|
{
|
|
|
|
|
if (ss->osd_mesh != NULL) {
|
2015-11-04 21:30:25 +05:00
|
|
|
ccgSubSurf__delete_osdGLMesh(ss->osd_mesh);
|
2015-08-05 14:15:46 +02:00
|
|
|
ss->osd_mesh = NULL;
|
|
|
|
|
}
|
|
|
|
|
if (ss->osd_vao != 0) {
|
|
|
|
|
glDeleteVertexArrays(1, &ss->osd_vao);
|
|
|
|
|
ss->osd_vao = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-05 14:43:51 +02:00
|
|
|
void ccgSubSurf_getMinMax(CCGSubSurf *ss, float r_min[3], float r_max[3])
|
|
|
|
|
{
|
|
|
|
|
int i;
|
2015-08-05 14:46:27 +02:00
|
|
|
BLI_assert(ss->skip_grids == true);
|
2015-09-30 20:59:19 +05:00
|
|
|
if (ss->osd_num_coarse_coords == 0) {
|
|
|
|
|
zero_v3(r_min);
|
|
|
|
|
zero_v3(r_max);
|
|
|
|
|
}
|
2015-08-05 14:43:51 +02:00
|
|
|
for (i = 0; i < ss->osd_num_coarse_coords; i++) {
|
2015-08-26 17:12:08 +02:00
|
|
|
/* Coarse coordinates has normals interleaved into the array. */
|
|
|
|
|
DO_MINMAX(ss->osd_coarse_coords[2 * i], r_min, r_max);
|
2015-08-05 14:43:51 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-04 21:30:25 +05:00
|
|
|
/* ** Delayed delete routines ** */
|
|
|
|
|
|
|
|
|
|
typedef struct OsdDeletePendingItem {
|
|
|
|
|
struct OsdDeletePendingItem *next, *prev;
|
|
|
|
|
OpenSubdiv_GLMesh *osd_mesh;
|
|
|
|
|
unsigned int vao;
|
|
|
|
|
} OsdDeletePendingItem;
|
|
|
|
|
|
|
|
|
|
static SpinLock delete_spin;
|
|
|
|
|
static ListBase delete_pool = {NULL, NULL};
|
|
|
|
|
|
|
|
|
|
static void delete_pending_push(OpenSubdiv_GLMesh *osd_mesh,
|
|
|
|
|
unsigned int vao)
|
|
|
|
|
{
|
|
|
|
|
OsdDeletePendingItem *new_entry = MEM_mallocN(sizeof(OsdDeletePendingItem),
|
|
|
|
|
"opensubdiv delete entry");
|
|
|
|
|
new_entry->osd_mesh = osd_mesh;
|
|
|
|
|
new_entry->vao = vao;
|
|
|
|
|
BLI_spin_lock(&delete_spin);
|
|
|
|
|
BLI_addtail(&delete_pool, new_entry);
|
|
|
|
|
BLI_spin_unlock(&delete_spin);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ccgSubSurf__delete_osdGLMesh(OpenSubdiv_GLMesh *osd_mesh)
|
|
|
|
|
{
|
|
|
|
|
if (BLI_thread_is_main()) {
|
|
|
|
|
openSubdiv_deleteOsdGLMesh(osd_mesh);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
delete_pending_push(osd_mesh, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ccgSubSurf__delete_vertex_array(unsigned int vao)
|
|
|
|
|
{
|
|
|
|
|
if (BLI_thread_is_main()) {
|
|
|
|
|
glDeleteVertexArrays(1, &vao);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
delete_pending_push(NULL, vao);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ccgSubSurf__delete_pending(void)
|
|
|
|
|
{
|
|
|
|
|
OsdDeletePendingItem *entry;
|
|
|
|
|
BLI_assert(BLI_thread_is_main());
|
|
|
|
|
BLI_spin_lock(&delete_spin);
|
|
|
|
|
for (entry = delete_pool.first; entry != NULL; entry = entry->next) {
|
|
|
|
|
if (entry->osd_mesh != NULL) {
|
|
|
|
|
openSubdiv_deleteOsdGLMesh(entry->osd_mesh);
|
|
|
|
|
}
|
|
|
|
|
if (entry->vao != 0) {
|
|
|
|
|
glDeleteVertexArrays(1, &entry->vao);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
BLI_freelistN(&delete_pool);
|
|
|
|
|
BLI_spin_unlock(&delete_spin);
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-22 17:52:30 +02:00
|
|
|
void ccgSubSurf__sync_subdivUvs(CCGSubSurf *ss, bool subdiv_uvs)
|
|
|
|
|
{
|
|
|
|
|
ss->osd_subdiv_uvs = subdiv_uvs;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-04 21:30:25 +05:00
|
|
|
/* ** Public API ** */
|
|
|
|
|
|
|
|
|
|
void BKE_subsurf_osd_init(void)
|
|
|
|
|
{
|
2017-05-18 17:28:04 -04:00
|
|
|
openSubdiv_init();
|
2015-11-04 21:30:25 +05:00
|
|
|
BLI_spin_init(&delete_spin);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_subsurf_free_unused_buffers(void)
|
|
|
|
|
{
|
|
|
|
|
ccgSubSurf__delete_pending();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_subsurf_osd_cleanup(void)
|
|
|
|
|
{
|
|
|
|
|
openSubdiv_cleanup();
|
|
|
|
|
ccgSubSurf__delete_pending();
|
|
|
|
|
BLI_spin_end(&delete_spin);
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-20 15:27:47 +02:00
|
|
|
#endif /* WITH_OPENSUBDIV */
|