diff options
author | Mai Lavelle <mai.lavelle@gmail.com> | 2016-07-17 02:42:28 +0300 |
---|---|---|
committer | Mai Lavelle <mai.lavelle@gmail.com> | 2016-07-29 10:36:30 +0300 |
commit | c96ae81160ad1a943fafaca44a7d5e97c2d7a0d7 (patch) | |
tree | 83905d5a6bf2583f44d9dcf90410b5a0c024822c /intern/cycles/render/attribute.cpp | |
parent | f74645578c9dd38c2543d1211b779a019363b04f (diff) |
Cycles microdisplacement: ngons and attributes for subdivision meshes
This adds support for ngons and attributes on subdivision meshes. Ngons are
needed for proper attribute interpolation as well as correct Catmull-Clark
subdivision. Several changes are made to achieve this:
- new primitive `SubdFace` added to `Mesh`
- 3 more textures are used to store info on patches from subd meshes
- Blender export uses loop interface instead of tessface for subd meshes
- `Attribute` class is updated with a simplified way to pass primitive counts
around and to support ngons.
- extra points for ngons are generated for O(1) attribute interpolation
- curves are temporally disabled on subd meshes to avoid various bugs with
implementation
- old unneeded code is removed from `subd/`
- various fixes and improvements
Reviewed By: brecht
Differential Revision: https://developer.blender.org/D2108
Diffstat (limited to 'intern/cycles/render/attribute.cpp')
-rw-r--r-- | intern/cycles/render/attribute.cpp | 96 |
1 files changed, 75 insertions, 21 deletions
diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index 71a3cba6811..e8ff81fe08e 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -51,13 +51,13 @@ void Attribute::set(ustring name_, TypeDesc type_, AttributeElement element_) type == TypeDesc::TypeNormal || type == TypeDesc::TypeMatrix); } -void Attribute::resize(int numverts, int numtris, int numsteps, int numcurves, int numkeys, bool reserve_only) +void Attribute::resize(Mesh *mesh, AttributePrimitive prim, bool reserve_only) { if(reserve_only) { - buffer.reserve(buffer_size(numverts, numtris, numsteps, numcurves, numkeys)); + buffer.reserve(buffer_size(mesh, prim)); } else { - buffer.resize(buffer_size(numverts, numtris, numsteps, numcurves, numkeys), 0); + buffer.resize(buffer_size(mesh, prim), 0); } } @@ -118,6 +118,8 @@ size_t Attribute::data_sizeof() const { if(element == ATTR_ELEMENT_VOXEL) return sizeof(VoxelAttribute); + else if(element == ATTR_ELEMENT_CORNER_BYTE) + return sizeof(uchar4); else if(type == TypeDesc::TypeFloat) return sizeof(float); else if(type == TypeDesc::TypeMatrix) @@ -126,10 +128,10 @@ size_t Attribute::data_sizeof() const return sizeof(float3); } -size_t Attribute::element_size(int numverts, int numtris, int numsteps, int numcurves, int numkeys) const +size_t Attribute::element_size(Mesh *mesh, AttributePrimitive prim) const { size_t size; - + switch(element) { case ATTR_ELEMENT_OBJECT: case ATTR_ELEMENT_MESH: @@ -137,38 +139,54 @@ size_t Attribute::element_size(int numverts, int numtris, int numsteps, int numc size = 1; break; case ATTR_ELEMENT_VERTEX: - size = numverts; + size = mesh->verts.size() + mesh->num_ngons; + if(prim == ATTR_PRIM_SUBD) { + size -= mesh->num_subd_verts; + } break; case ATTR_ELEMENT_VERTEX_MOTION: - size = numverts * (numsteps - 1); + size = (mesh->verts.size() + mesh->num_ngons) * (mesh->motion_steps - 1); + if(prim == ATTR_PRIM_SUBD) { + size -= mesh->num_subd_verts * (mesh->motion_steps - 1); + } break; case ATTR_ELEMENT_FACE: - size = numtris; + if(prim == ATTR_PRIM_TRIANGLE) { + size = mesh->num_triangles(); + } + else { + size = mesh->subd_faces.size() + mesh->num_ngons; + } break; case ATTR_ELEMENT_CORNER: case ATTR_ELEMENT_CORNER_BYTE: - size = numtris*3; + if(prim == ATTR_PRIM_TRIANGLE) { + size = mesh->num_triangles()*3; + } + else { + size = mesh->subd_face_corners.size() + mesh->num_ngons; + } break; case ATTR_ELEMENT_CURVE: - size = numcurves; + size = mesh->num_curves(); break; case ATTR_ELEMENT_CURVE_KEY: - size = numkeys; + size = mesh->curve_keys.size(); break; case ATTR_ELEMENT_CURVE_KEY_MOTION: - size = numkeys * (numsteps - 1); + size = mesh->curve_keys.size() * (mesh->motion_steps - 1); break; default: size = 0; break; } - + return size; } -size_t Attribute::buffer_size(int numverts, int numtris, int numsteps, int numcurves, int numkeys) const +size_t Attribute::buffer_size(Mesh *mesh, AttributePrimitive prim) const { - return element_size(numverts, numtris, numsteps, numcurves, numkeys)*data_sizeof(); + return element_size(mesh, prim)*data_sizeof(); } bool Attribute::same_storage(TypeDesc a, TypeDesc b) @@ -188,6 +206,29 @@ bool Attribute::same_storage(TypeDesc a, TypeDesc b) return false; } +void Attribute::zero_data(void* dst) +{ + memset(dst, 0, data_sizeof()); +} + +void Attribute::add_with_weight(void* dst, void* src, float weight) +{ + if(element == ATTR_ELEMENT_CORNER_BYTE) { + for(int i = 0; i < 4; i++) { + ((uchar*)dst)[i] += uchar(((uchar*)src)[i] * weight); + } + } + else if(same_storage(type, TypeDesc::TypeFloat)) { + *((float*)dst) += *((float*)src) * weight; + } + else if(same_storage(type, TypeDesc::TypeVector)) { + *((float4*)dst) += *((float4*)src) * weight; + } + else { + assert(!"not implemented for this type"); + } +} + const char *Attribute::standard_name(AttributeStandard std) { switch(std) { @@ -257,6 +298,7 @@ AttributeSet::AttributeSet() { triangle_mesh = NULL; curve_mesh = NULL; + subd_mesh = NULL; } AttributeSet::~AttributeSet() @@ -291,10 +333,12 @@ Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement eleme /* this is weak .. */ if(triangle_mesh) - attr->resize(triangle_mesh->verts.size(), triangle_mesh->num_triangles(), triangle_mesh->motion_steps, 0, 0, false); + attr->resize(triangle_mesh, ATTR_PRIM_TRIANGLE, false); if(curve_mesh) - attr->resize(0, 0, curve_mesh->motion_steps, curve_mesh->num_curves(), curve_mesh->curve_keys.size(), false); - + attr->resize(curve_mesh, ATTR_PRIM_CURVE, false); + if(subd_mesh) + attr->resize(subd_mesh, ATTR_PRIM_SUBD, false); + return attr; } @@ -330,7 +374,7 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name) if(name == ustring()) name = Attribute::standard_name(std); - if(triangle_mesh) { + if(triangle_mesh || subd_mesh) { switch(std) { case ATTR_STD_VERTEX_NORMAL: attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX); @@ -452,9 +496,11 @@ void AttributeSet::resize(bool reserve_only) { foreach(Attribute& attr, attributes) { if(triangle_mesh) - attr.resize(triangle_mesh->verts.size(), triangle_mesh->num_triangles(), triangle_mesh->motion_steps, 0, 0, reserve_only); + attr.resize(triangle_mesh, ATTR_PRIM_TRIANGLE, reserve_only); if(curve_mesh) - attr.resize(0, 0, 0, curve_mesh->num_curves(), curve_mesh->curve_keys.size(), reserve_only); + attr.resize(curve_mesh, ATTR_PRIM_CURVE, reserve_only); + if(subd_mesh) + attr.resize(subd_mesh, ATTR_PRIM_SUBD, reserve_only); } } @@ -477,6 +523,10 @@ AttributeRequest::AttributeRequest(ustring name_) curve_type = TypeDesc::TypeFloat; curve_element = ATTR_ELEMENT_NONE; curve_offset = 0; + + subd_type = TypeDesc::TypeFloat; + subd_element = ATTR_ELEMENT_NONE; + subd_offset = 0; } AttributeRequest::AttributeRequest(AttributeStandard std_) @@ -491,6 +541,10 @@ AttributeRequest::AttributeRequest(AttributeStandard std_) curve_type = TypeDesc::TypeFloat; curve_element = ATTR_ELEMENT_NONE; curve_offset = 0; + + subd_type = TypeDesc::TypeFloat; + subd_element = ATTR_ELEMENT_NONE; + subd_offset = 0; } /* AttributeRequestSet */ |