[Bf-blender-cvs] [c78414c] temp-cycles-microdisplacement: Add basic OpenSubDiv support
Mai Lavelle
noreply at git.blender.org
Tue Apr 12 18:45:49 CEST 2016
Commit: c78414cefaa208a65184362736b783c37e7a6f5f
Author: Mai Lavelle
Date: Sun Jan 31 22:03:00 2016 -0500
Branches: temp-cycles-microdisplacement
https://developer.blender.org/rBc78414cefaa208a65184362736b783c37e7a6f5f
Add basic OpenSubDiv support
===================================================================
M intern/cycles/blender/blender_mesh.cpp
M intern/cycles/render/CMakeLists.txt
M intern/cycles/render/mesh.cpp
M intern/cycles/render/mesh.h
M intern/cycles/render/mesh_subdivision.cpp
===================================================================
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index b075bfb..410d520 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -677,6 +677,7 @@ static void create_subd_mesh(Scene *scene,
bool preview)
{
Mesh *basemesh = new Mesh();
+ basemesh->subdivision_type = (Mesh::SubdivisionType)RNA_enum_get(cmesh, "subdivision_type");
create_mesh(scene, basemesh, b_mesh, used_shaders, true);
SubdParams sdparams(mesh, used_shaders[0], true, false);
diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt
index ab0e571..1783c8c 100644
--- a/intern/cycles/render/CMakeLists.txt
+++ b/intern/cycles/render/CMakeLists.txt
@@ -12,6 +12,7 @@ set(INC
set(INC_SYS
${GLEW_INCLUDE_DIR}
+ ${OPENSUBDIV_INCLUDE_DIR}
)
set(SRC
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index aa862d1..2a059a0 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -85,6 +85,7 @@ Mesh::Mesh()
motion_steps = 3;
use_motion_blur = false;
+ subdivision_type = SUBDIVISION_NONE;
displacement_scale = 1.0f;
bvh = NULL;
@@ -100,11 +101,14 @@ Mesh::Mesh()
has_volume = false;
has_surface_bssrdf = false;
+
+ osd_data = NULL;
}
Mesh::~Mesh()
{
delete bvh;
+ free_osd_data();
}
void Mesh::reserve(int numverts, int numtris, int numcurves, int numcurvekeys, int numpatches)
@@ -140,6 +144,7 @@ void Mesh::clear()
curves.clear();
patches.clear();
+ free_osd_data();
attributes.clear();
curve_attributes.clear();
diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h
index 188fedd..89233fe 100644
--- a/intern/cycles/render/mesh.h
+++ b/intern/cycles/render/mesh.h
@@ -40,6 +40,7 @@ class Progress;
class Scene;
class SceneParams;
class AttributeRequest;
+class MeshOsdData;
/* Mesh */
@@ -103,6 +104,14 @@ public:
DISPLACE_NUM_METHODS,
};
+ enum SubdivisionType {
+ SUBDIVISION_NONE,
+ SUBDIVISION_LINEAR,
+ SUBDIVISION_CATMALL_CLARK,
+ };
+
+ SubdivisionType subdivision_type;
+
ustring name;
/* Mesh Data */
@@ -128,6 +137,7 @@ public:
vector<Patch> patches;
vector<SubPatch> subpatches;
+ MeshOsdData* osd_data;
vector<uint> used_shaders;
AttributeSet attributes;
@@ -198,6 +208,9 @@ public:
/* Check if the mesh should be treated as instanced. */
bool is_instanced() const;
+ void update_osd();
+ void free_osd_data();
+
void dice_subpatch(int p, SubdParams& params);
void tessellate(DiagSplit *split);
};
diff --git a/intern/cycles/render/mesh_subdivision.cpp b/intern/cycles/render/mesh_subdivision.cpp
index 4409682..6c650f8 100644
--- a/intern/cycles/render/mesh_subdivision.cpp
+++ b/intern/cycles/render/mesh_subdivision.cpp
@@ -14,6 +14,13 @@
* limitations under the License.
*/
+
+#include <opensubdiv/far/topologyDescriptor.h>
+#include <opensubdiv/far/primvarRefiner.h>
+#include <opensubdiv/far/patchTableFactory.h>
+#include <opensubdiv/far/patchMap.h>
+#include <opensubdiv/far/ptexIndices.h>
+
#include "bvh.h"
#include "bvh_build.h"
@@ -38,8 +45,206 @@
#include "../subd/subd_split.h"
#include "../subd/subd_patch.h"
+using namespace OpenSubdiv;
+
CCL_NAMESPACE_BEGIN
+struct OsdVertex {
+ float3 v;
+
+ OsdVertex() {}
+
+ void Clear(void* = 0) {
+ v = make_float3(0.0f, 0.0f, 0.0f);
+ }
+
+ void AddWithWeight(OsdVertex const& src, float weight) {
+ v += src.v * weight;
+ }
+};
+
+struct MeshOsdData {
+ Far::PatchTable* patch_table;
+ Far::PatchMap* patch_map;
+ Far::PtexIndices* ptex_indices;
+ vector<OsdVertex> verts;
+
+ vector<int> num_verts_per_face;
+ vector<int> face_verts;
+};
+
+void Mesh::free_osd_data()
+{
+ if(!osd_data)
+ return;
+
+ delete osd_data->patch_table;
+ delete osd_data->patch_map;
+ delete osd_data->ptex_indices;
+
+ delete osd_data;
+ osd_data = NULL;
+}
+
+void Mesh::update_osd()
+{
+ assert(!osd_data);
+
+ if(subdivision_type != Mesh::SUBDIVISION_CATMALL_CLARK)
+ return;
+
+ osd_data = new MeshOsdData;
+
+ Sdc::SchemeType type = Sdc::SCHEME_CATMARK;
+
+ Sdc::Options options;
+ options.SetVtxBoundaryInterpolation(Sdc::Options::VTX_BOUNDARY_EDGE_ONLY);
+
+ Far::TopologyDescriptor desc;
+ desc.numVertices = verts.size();
+ desc.numFaces = patches.size();
+
+ size_t num_face_verts = 0;
+ osd_data->num_verts_per_face.resize(patches.size());
+
+ for(int i = 0; i < patches.size(); i++) {
+ osd_data->num_verts_per_face[i] = patches[i].is_quad() ? 4 : 3;
+ num_face_verts += osd_data->num_verts_per_face[i];
+ }
+
+ desc.numVertsPerFace = &osd_data->num_verts_per_face[0];
+
+ osd_data->face_verts.resize(num_face_verts);
+
+ int* fv = &osd_data->face_verts[0];
+ for(int i = 0; i < patches.size(); i++) {
+ Patch& patch = patches[i];
+
+ if(patch.is_quad()) {
+ *fv++ = patch.v[0];
+ *fv++ = patch.v[1];
+ *fv++ = patch.v[2];
+ *fv++ = patch.v[3];
+ }
+ else {
+ *fv++ = patch.v[0];
+ *fv++ = patch.v[1];
+ *fv++ = patch.v[2];
+ }
+ }
+
+ desc.vertIndicesPerFace = &osd_data->face_verts[0];
+
+ Far::TopologyRefiner* refiner = Far::TopologyRefinerFactory<Far::TopologyDescriptor>::Create(
+ desc, Far::TopologyRefinerFactory<Far::TopologyDescriptor>::Options(type, options));
+
+ int max_isolation = 10;
+ refiner->RefineAdaptive(Far::TopologyRefiner::AdaptiveOptions(max_isolation));
+
+ Far::PatchTableFactory::Options patch_options;
+ patch_options.endCapType = Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS;
+
+ osd_data->patch_table = Far::PatchTableFactory::Create(*refiner, patch_options);
+
+ int num_refiner_verts = refiner->GetNumVerticesTotal();
+ int num_local_points = osd_data->patch_table->GetNumLocalPoints();
+
+ osd_data->verts.resize(num_refiner_verts + num_local_points);
+ for(int i = 0; i < verts.size(); i++) {
+ osd_data->verts[i].v = verts[i];
+ }
+
+ OsdVertex* src = &osd_data->verts[0];
+ for(int i = 0; i < refiner->GetMaxLevel(); i++) {
+ OsdVertex* dest = src + refiner->GetLevel(i).GetNumVertices();
+ Far::PrimvarRefiner(*refiner).Interpolate(i+1, src, dest);
+ src = dest;
+ }
+
+ osd_data->patch_table->ComputeLocalPointValues(&osd_data->verts[0], &osd_data->verts[num_refiner_verts]);
+
+ osd_data->patch_map = new Far::PatchMap(*osd_data->patch_table);
+ osd_data->ptex_indices = new Far::PtexIndices(*refiner);
+}
+
+struct OsdPatch : Patch {
+ Mesh* mesh;
+ int patch;
+
+ void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v)
+ {
+ int patch_ = patch;
+ patch_uv_to_ptex_uv(patch_, u, v);
+
+ const Far::PatchTable::PatchHandle* handle = mesh->osd_data->patch_map->FindPatch(patch_, u, v);
+ assert(handle);
+
+ float p_weights[20], du_weights[20], dv_weights[20];
+ mesh->osd_data->patch_table->EvaluateBasis(*handle, u, v, p_weights, du_weights, dv_weights);
+
+ Far::ConstIndexArray cv = mesh->osd_data->patch_table->GetPatchVertices(*handle);
+
+ float3 du, dv;
+ if(P) *P = make_float3(0.0f, 0.0f, 0.0f);
+ du = make_float3(0.0f, 0.0f, 0.0f);
+ dv = make_float3(0.0f, 0.0f, 0.0f);
+
+ for(int i = 0; i < cv.size(); i++) {
+ float3 p = mesh->osd_data->verts[cv[i]].v;
+
+ if(P) *P += p * p_weights[i];
+ du += p * du_weights[i];
+ dv += p * dv_weights[i];
+ }
+
+ if(dPdu) *dPdu = du;
+ if(dPdv) *dPdv = dv;
+ if(N) *N = normalize(cross(du, dv));
+ }
+
+ void patch_uv_to_ptex_uv(int& patch, float& u, float& v)
+ {
+ bool is_quad = mesh->patches[patch].is_quad();
+ patch = mesh->osd_data->ptex_indices->GetFaceId(patch);
+
+ if(!is_quad) {
+ float w = 1.0f - u - v;
+
+ int quad = util_max_axis(make_float3(u, v, w));
+ patch += quad;
+
+ float u_, v_;
+
+ switch(quad) {
+ case 0: { u_ = v; v_ = w; break; }
+ case 1: { u_ = w; v_ = u; break; }
+ case 2: { u_ = u; v_ = v; break; }
+ default: assert(0);
+ }
+
+ u_ *= 2.0f;
+ v_ *= 2.0f;
+
+ float s = sqrtf(u_*u_ + v_*v_ - 2.0f*u_*v_ - 6.0f*u_ - 6.0f*v_ + 9.0f);
+
+ u = u_ - v_ + s - 3.0f;
+ if(fabsf(u) > 0.000001f)
+ u = clamp(3.0f*(u_ + v_ + s - 3.0f)/u, 0.0f, 1.0f);
+ else
+ u = u_;
+
+ v = v_ - u_ + s - 3.0f;
+ if(fabsf(v) > 0.000001f)
+ v = clamp(3.0f*(v_ + u_ + s - 3.0f)/v, 0.0f, 1.0f);
+ else
+ v = v_;
+ }
+ }
+
+ bool is_triangle() { return !mesh->patches[patch].is_quad(); }
+ BoundBox bound() { return BoundBox::empty; }
+};
+
static float3 patch_normal(Mesh* mesh, int patch) {
Mesh::Patch& t = mesh->patches[patch];
@@ -63,50 +268,56 @@ void Mesh::dice_subpatch(int subpatch_id, SubdParams& params)
params.shader = patches[subpatches[p].patch].shader;
+ OsdPatch osd_patch;
LinearQuadPatch quad_patch;
LinearTrianglePatch tri_patch;
ccl::Patch* subd_patch;
- //Attribute *attr_vF = attributes.find(ATTR_STD_FACE_NORMAL);
- //float3 *vF = attr_vF->data_float3();
+ if(subdivision_type == SUBDIVISION_CATMALL_CLARK) {
+ osd_patch.mesh = this;
+ osd_patch.patch = subpatches[subpatch_id].patch;
- Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL);
- float3 *vN = attr_vN->data_float3();
-
- if(patch.is_quad()) {
- for(int i = 0; i < 4; i++) {
- quad_patch.hull[i] = verts[patch.v[i]];
- }
+ subd_patch = &osd_patch;
+ }
+ else {
+ Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL);
+ float3 *vN = attr_vN->data_float3();
- if(patch.smooth) {
- for(int i = 0; i < 4; i++)
- quad_patch.normals[i] = vN[patch.v[i]];
- }
- else {
- for(int i = 0; i < 4; i++)
- quad_patch.normals[i] = patch_normal(this, subpatch.patch);
- }
+ if(patch.is_quad()) {
+ for(int i = 0; i < 4; i++) {
+ quad_patch.hull[i] = verts[patch.v[i]];
+ }
- swap(quad_patch.hull[2], quad_patch.hull[3]);
- swap(quad_patch.normals[2], quad_patch.normals[3]);
+ if(patch.smooth) {
+ for(int i = 0; i < 4; i++)
+ quad_patch.normals[i] = vN[patch.v[i]];
+ }
+ else {
+ for(int i = 0; i < 4; i++)
+ quad_patch.normals[i] = patch_normal(this, subpatch.patch);
+ }
- subd_patch = &quad_patch;
- }
- else {
- for(int i = 0; i < 3; i++) {
- tri_patch.hull[i] = verts[patch.v[i]];
- }
+ swap(quad_patch.hull[2], quad_patch.hull[3]);
+ swap(quad_patch.normals[2], quad_patch.normals[3]);
- if(patch.smooth) {
- for(int i = 0; i < 3; i++)
- tri_
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list