diff options
Diffstat (limited to 'intern/cycles/render')
-rw-r--r-- | intern/cycles/render/attribute.cpp | 205 | ||||
-rw-r--r-- | intern/cycles/render/attribute.h | 46 | ||||
-rw-r--r-- | intern/cycles/render/curves.h | 3 | ||||
-rw-r--r-- | intern/cycles/render/light.cpp | 16 | ||||
-rw-r--r-- | intern/cycles/render/mesh.cpp | 316 | ||||
-rw-r--r-- | intern/cycles/render/mesh.h | 30 | ||||
-rw-r--r-- | intern/cycles/render/nodes.cpp | 13 | ||||
-rw-r--r-- | intern/cycles/render/nodes.h | 2 | ||||
-rw-r--r-- | intern/cycles/render/object.cpp | 26 | ||||
-rw-r--r-- | intern/cycles/render/scene.h | 5 |
10 files changed, 401 insertions, 261 deletions
diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index 95941c14b6c..758e4e5e820 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -26,7 +26,7 @@ CCL_NAMESPACE_BEGIN /* Attribute */ -void Attribute::set(ustring name_, TypeDesc type_, Element element_) +void Attribute::set(ustring name_, TypeDesc type_, AttributeElement element_) { name = name_; type = type_; @@ -39,12 +39,30 @@ void Attribute::set(ustring name_, TypeDesc type_, Element element_) type == TypeDesc::TypeNormal); } -void Attribute::reserve(int numverts, int numtris) +void Attribute::reserve(int numverts, int numtris, int numcurves, int numkeys) { - buffer.resize(buffer_size(numverts, numtris), 0); + buffer.resize(buffer_size(numverts, numtris, numcurves, numkeys), 0); } -size_t Attribute::data_sizeof() +void Attribute::add(const float& f) +{ + char *data = (char*)&f; + size_t size = sizeof(f); + + for(size_t i = 0; i < size; i++) + buffer.push_back(data[i]); +} + +void Attribute::add(const float3& f) +{ + char *data = (char*)&f; + size_t size = sizeof(f); + + for(size_t i = 0; i < size; i++) + buffer.push_back(data[i]); +} + +size_t Attribute::data_sizeof() const { if(type == TypeDesc::TypeFloat) return sizeof(float); @@ -52,19 +70,27 @@ size_t Attribute::data_sizeof() return sizeof(float3); } -size_t Attribute::element_size(int numverts, int numtris) +size_t Attribute::element_size(int numverts, int numtris, int numcurves, int numkeys) const { - if(element == VERTEX) + if(element == ATTR_ELEMENT_VALUE) + return 1; + if(element == ATTR_ELEMENT_VERTEX) return numverts; - else if(element == FACE) + else if(element == ATTR_ELEMENT_FACE) return numtris; - else + else if(element == ATTR_ELEMENT_CORNER) return numtris*3; + else if(element == ATTR_ELEMENT_CURVE_SEGMENT) + return numcurves; + else if(element == ATTR_ELEMENT_CURVE_KEY) + return numkeys; + + return 0; } -size_t Attribute::buffer_size(int numverts, int numtris) +size_t Attribute::buffer_size(int numverts, int numtris, int numcurves, int numkeys) const { - return element_size(numverts, numtris)*data_sizeof(); + return element_size(numverts, numtris, numcurves, numkeys)*data_sizeof(); } bool Attribute::same_storage(TypeDesc a, TypeDesc b) @@ -84,18 +110,51 @@ bool Attribute::same_storage(TypeDesc a, TypeDesc b) return false; } +const char *Attribute::standard_name(AttributeStandard std) +{ + if(std == ATTR_STD_VERTEX_NORMAL) + return "N"; + else if(std == ATTR_STD_FACE_NORMAL) + return "Ng"; + else if(std == ATTR_STD_UV) + return "uv"; + else if(std == ATTR_STD_GENERATED) + return "generated"; + else if(std == ATTR_STD_UV_TANGENT) + return "tangent"; + else if(std == ATTR_STD_UV_TANGENT_SIGN) + return "tangent_sign"; + else if(std == ATTR_STD_POSITION_UNDEFORMED) + return "undeformed"; + else if(std == ATTR_STD_POSITION_UNDISPLACED) + return "undisplaced"; + else if(std == ATTR_STD_MOTION_PRE) + return "motion_pre"; + else if(std == ATTR_STD_MOTION_POST) + return "motion_post"; + else if(std == ATTR_STD_PARTICLE) + return "particle"; + else if(std == ATTR_STD_CURVE_TANGENT) + return "curve_tangent"; + else if(std == ATTR_STD_CURVE_INTERCEPT) + return "curve_intercept"; + + return ""; +} + /* Attribute Set */ AttributeSet::AttributeSet() { - mesh = NULL; + triangle_mesh = NULL; + curve_mesh = NULL; } AttributeSet::~AttributeSet() { } -Attribute *AttributeSet::add(ustring name, TypeDesc type, Attribute::Element element) +Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement element) { Attribute *attr = find(name); @@ -111,24 +170,22 @@ Attribute *AttributeSet::add(ustring name, TypeDesc type, Attribute::Element ele attributes.push_back(Attribute()); attr = &attributes.back(); - if(element == Attribute::VERTEX) - attr->set(name, type, element); - else if(element == Attribute::FACE) - attr->set(name, type, element); - else if(element == Attribute::CORNER) - attr->set(name, type, element); + attr->set(name, type, element); - if(mesh) - attr->reserve(mesh->verts.size(), mesh->triangles.size()); + /* this is weak .. */ + if(triangle_mesh) + attr->reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), 0, 0); + if(curve_mesh) + attr->reserve(0, 0, curve_mesh->curve_segments.size(), curve_mesh->curve_keys.size()); return attr; } -Attribute *AttributeSet::find(ustring name) +Attribute *AttributeSet::find(ustring name) const { - foreach(Attribute& attr, attributes) + foreach(const Attribute& attr, attributes) if(attr.name == name) - return &attr; + return (Attribute*)&attr; return NULL; } @@ -154,41 +211,59 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name) Attribute *attr = NULL; if(name == ustring()) - name = attribute_standard_name(std); - - if(std == ATTR_STD_VERTEX_NORMAL) - attr = add(name, TypeDesc::TypeNormal, Attribute::VERTEX); - else if(std == ATTR_STD_FACE_NORMAL) - attr = add(name, TypeDesc::TypeNormal, Attribute::FACE); - else if(std == ATTR_STD_UV) - attr = add(name, TypeDesc::TypePoint, Attribute::CORNER); - else if(std == ATTR_STD_UV_TANGENT) - attr = add(name, TypeDesc::TypeVector, Attribute::CORNER); - else if(std == ATTR_STD_UV_TANGENT_SIGN) - attr = add(name, TypeDesc::TypeFloat, Attribute::CORNER); - else if(std == ATTR_STD_GENERATED) - attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX); - else if(std == ATTR_STD_POSITION_UNDEFORMED) - attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX); - else if(std == ATTR_STD_POSITION_UNDISPLACED) - attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX); - else if(std == ATTR_STD_MOTION_PRE) - attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX); - else if(std == ATTR_STD_MOTION_POST) - attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX); - else - assert(0); + name = Attribute::standard_name(std); + + if(triangle_mesh) { + if(std == ATTR_STD_VERTEX_NORMAL) + attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX); + else if(std == ATTR_STD_FACE_NORMAL) + attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_FACE); + else if(std == ATTR_STD_UV) + attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER); + else if(std == ATTR_STD_UV_TANGENT) + attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER); + else if(std == ATTR_STD_UV_TANGENT_SIGN) + attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER); + else if(std == ATTR_STD_GENERATED) + attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX); + else if(std == ATTR_STD_POSITION_UNDEFORMED) + attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX); + else if(std == ATTR_STD_POSITION_UNDISPLACED) + attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX); + else if(std == ATTR_STD_MOTION_PRE) + attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX); + else if(std == ATTR_STD_MOTION_POST) + attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX); + else + assert(0); + } + else if(curve_mesh) { + if(std == ATTR_STD_UV) + attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_SEGMENT); + else if(std == ATTR_STD_GENERATED) + attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_SEGMENT); + else if(std == ATTR_STD_MOTION_PRE) + attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY); + else if(std == ATTR_STD_MOTION_POST) + attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY); + else if(std == ATTR_STD_CURVE_TANGENT) + attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CURVE_KEY); + else if(std == ATTR_STD_CURVE_INTERCEPT) + attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE_KEY); + else + assert(0); + } attr->std = std; return attr; } -Attribute *AttributeSet::find(AttributeStandard std) +Attribute *AttributeSet::find(AttributeStandard std) const { - foreach(Attribute& attr, attributes) + foreach(const Attribute& attr, attributes) if(attr.std == std) - return &attr; + return (Attribute*)&attr; return NULL; } @@ -217,10 +292,14 @@ Attribute *AttributeSet::find(AttributeRequest& req) return find(req.std); } -void AttributeSet::reserve(int numverts, int numtris) +void AttributeSet::reserve() { - foreach(Attribute& attr, attributes) - attr.reserve(numverts, numtris); + foreach(Attribute& attr, attributes) { + if(triangle_mesh) + attr.reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), 0, 0); + if(curve_mesh) + attr.reserve(0, 0, curve_mesh->curve_segments.size(), curve_mesh->curve_keys.size()); + } } void AttributeSet::clear() @@ -235,9 +314,13 @@ AttributeRequest::AttributeRequest(ustring name_) name = name_; std = ATTR_STD_NONE; - type = TypeDesc::TypeFloat; - element = ATTR_ELEMENT_NONE; - offset = 0; + triangle_type = TypeDesc::TypeFloat; + triangle_element = ATTR_ELEMENT_NONE; + triangle_offset = 0; + + curve_type = TypeDesc::TypeFloat; + curve_element = ATTR_ELEMENT_NONE; + curve_offset = 0; } AttributeRequest::AttributeRequest(AttributeStandard std_) @@ -245,9 +328,13 @@ AttributeRequest::AttributeRequest(AttributeStandard std_) name = ustring(); std = std_; - type = TypeDesc::TypeFloat; - element = ATTR_ELEMENT_NONE; - offset = 0; + triangle_type = TypeDesc::TypeFloat; + triangle_element = ATTR_ELEMENT_NONE; + triangle_offset = 0; + + curve_type = TypeDesc::TypeFloat; + curve_element = ATTR_ELEMENT_NONE; + curve_offset = 0; } /* AttributeRequestSet */ diff --git a/intern/cycles/render/attribute.h b/intern/cycles/render/attribute.h index d05952edfd7..6c0c06d0425 100644 --- a/intern/cycles/render/attribute.h +++ b/intern/cycles/render/attribute.h @@ -21,7 +21,6 @@ #include "kernel_types.h" -#include "util_attribute.h" #include "util_list.h" #include "util_param.h" #include "util_types.h" @@ -42,36 +41,34 @@ class Mesh; class Attribute { public: - enum Element { - VERTEX, - FACE, - CORNER - }; - ustring name; AttributeStandard std; TypeDesc type; vector<char> buffer; - Element element; + AttributeElement element; Attribute() {} - void set(ustring name, TypeDesc type, Element element); - void reserve(int numverts, int numfaces); + void set(ustring name, TypeDesc type, AttributeElement element); + void reserve(int numverts, int numfaces, int numcurves, int numkeys); - size_t data_sizeof(); - size_t element_size(int numverts, int numfaces); - size_t buffer_size(int numverts, int numfaces); + size_t data_sizeof() const; + size_t element_size(int numverts, int numfaces, int numcurves, int numkeys) const; + size_t buffer_size(int numverts, int numfaces, int numcurves, int numkeys) const; char *data() { return (buffer.size())? &buffer[0]: NULL; }; float3 *data_float3() { return (float3*)data(); } float *data_float() { return (float*)data(); } const char *data() const { return (buffer.size())? &buffer[0]: NULL; } - const float3 *data_float3() const { return (float3*)data(); } - const float *data_float() const { return (float*)data(); } + const float3 *data_float3() const { return (const float3*)data(); } + const float *data_float() const { return (const float*)data(); } + + void add(const float& f); + void add(const float3& f); static bool same_storage(TypeDesc a, TypeDesc b); + static const char *standard_name(AttributeStandard std); }; /* Attribute Set @@ -80,23 +77,24 @@ public: class AttributeSet { public: - Mesh *mesh; + Mesh *triangle_mesh; + Mesh *curve_mesh; list<Attribute> attributes; AttributeSet(); ~AttributeSet(); - Attribute *add(ustring name, TypeDesc type, Attribute::Element element); - Attribute *find(ustring name); + Attribute *add(ustring name, TypeDesc type, AttributeElement element); + Attribute *find(ustring name) const; void remove(ustring name); Attribute *add(AttributeStandard std, ustring name = ustring()); - Attribute *find(AttributeStandard std); + Attribute *find(AttributeStandard std) const; void remove(AttributeStandard std); Attribute *find(AttributeRequest& req); - void reserve(int numverts, int numfaces); + void reserve(); void clear(); }; @@ -104,7 +102,7 @@ public: * * Request from a shader to use a certain attribute, so we can figure out * which ones we need to export from the host app end store for the kernel. - * The attribute is found either by name or by standard. */ + * The attribute is found either by name or by standard attribute type. */ class AttributeRequest { public: @@ -112,9 +110,9 @@ public: AttributeStandard std; /* temporary variables used by MeshManager */ - TypeDesc type; - AttributeElement element; - int offset; + TypeDesc triangle_type, curve_type; + AttributeElement triangle_element, curve_element; + int triangle_offset, curve_offset; AttributeRequest(ustring name_); AttributeRequest(AttributeStandard std); diff --git a/intern/cycles/render/curves.h b/intern/cycles/render/curves.h index 581b3010d77..85a549082f2 100644 --- a/intern/cycles/render/curves.h +++ b/intern/cycles/render/curves.h @@ -80,8 +80,7 @@ public: vector<int> curve_firstkey; vector<int> curve_keynum; vector<float> curve_length; - vector<float> curve_u; - vector<float> curve_v; + vector<float3> curve_uv; vector<float3> curvekey_co; vector<float> curvekey_time; diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 66e528c7230..cab6008dd7c 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -142,7 +142,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen /* count */ size_t num_lights = scene->lights.size(); size_t num_triangles = 0; - size_t num_curve_segs = 0; + size_t num_curve_segments = 0; foreach(Object *object, scene->objects) { Mesh *mesh = object->mesh; @@ -172,16 +172,16 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen } /* disabled for strands*/ - /*for(size_t i = 0; i < mesh->curve_segs.size(); i++) { - * Shader *shader = scene->shaders[mesh->curve_segs[i].curveshader]; + /*for(size_t i = 0; i < mesh->curve_segments.size(); i++) { + * Shader *shader = scene->shaders[mesh->curve_segments[i].shader]; * * if(shader->sample_as_light && shader->has_surface_emission) - * num_curve_segs++; + * num_curve_segments++; }*/ } } - size_t num_distribution = num_triangles + num_curve_segs; + size_t num_distribution = num_triangles + num_curve_segments; num_distribution += num_lights; /* emission area */ @@ -245,8 +245,8 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen } /*sample as light disabled for strands*/ - /*for(size_t i = 0; i < mesh->curve_segs.size(); i++) { - * Shader *shader = scene->shaders[mesh->curve_segs[i].curveshader]; + /*for(size_t i = 0; i < mesh->curve_segments.size(); i++) { + * Shader *shader = scene->shaders[mesh->curve_segments[i].shader]; * * if(shader->sample_as_light && shader->has_surface_emission) { * distribution[offset].x = totarea; @@ -255,7 +255,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen * distribution[offset].w = __int_as_float(object_id); * offset++; * - * Mesh::CurveSeg s = mesh->curve_segs[i]; + * Mesh::CurveSeg s = mesh->curve_segments[i]; * float3 p1 = mesh->curve_keys[s.v[0]].loc; * float r1 = mesh->curve_keys[s.v[0]].radius; * float3 p2 = mesh->curve_keys[s.v[1]].loc; diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index b20e5cebdc5..53cae53ef69 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -54,7 +54,8 @@ Mesh::Mesh() curveseg_offset = 0; curvekey_offset = 0; - attributes.mesh = this; + attributes.triangle_mesh = this; + curve_attributes.curve_mesh = this; } Mesh::~Mesh() @@ -62,15 +63,18 @@ Mesh::~Mesh() delete bvh; } -void Mesh::reserve(int numverts, int numtris) +void Mesh::reserve(int numverts, int numtris, int numcurves, int numcurvekeys) { /* reserve space to add verts and triangles later */ verts.resize(numverts); triangles.resize(numtris); shader.resize(numtris); smooth.resize(numtris); - /*currently no need in hair segment resize and curve data needs including*/ - attributes.reserve(numverts, numtris); + curve_keys.resize(numcurvekeys); + curve_segments.resize(numcurves); + + attributes.reserve(); + curve_attributes.reserve(); } void Mesh::clear() @@ -82,11 +86,10 @@ void Mesh::clear() smooth.clear(); curve_keys.clear(); - curve_keysCD.clear(); - curve_segs.clear(); - curve_attrib.clear(); + curve_segments.clear(); attributes.clear(); + curve_attributes.clear(); used_shaders.clear(); transform_applied = false; @@ -105,34 +108,24 @@ void Mesh::add_triangle(int v0, int v1, int v2, int shader_, bool smooth_) smooth.push_back(smooth_); } -void Mesh::add_curvekey(float3 loc, float radius, float time) +void Mesh::add_curve_key(float3 co, float radius) { CurveKey ck; - ck.loc = loc; + ck.co = co; ck.radius = radius; - ck.time = time; curve_keys.push_back(ck); } -void Mesh::add_curve(int v0, int v1, int shader, int curveid) +void Mesh::add_curve_segment(int v0, int v1, int shader, int curveid) { - CurveSeg s; + CurveSegment s; s.v[0] = v0; s.v[1] = v1; - s.curveshader = shader; + s.shader = shader; s.curve = curveid; - curve_segs.push_back(s); -} - -void Mesh::add_curveattrib(float u, float v) -{ - Curve_Attribute s; - s.uv[0] = u; - s.uv[1] = v; - - curve_attrib.push_back(s); + curve_segments.push_back(s); } void Mesh::compute_bounds() @@ -145,7 +138,7 @@ void Mesh::compute_bounds() bnds.grow(verts[i]); for(size_t i = 0; i < curve_keys_size; i++) - bnds.grow(curve_keys[i].loc, curve_keys[i].radius); + bnds.grow(curve_keys[i].co, curve_keys[i].radius); /* happens mostly on empty meshes */ if(!bnds.valid()) @@ -296,29 +289,31 @@ void Mesh::pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_seg_key size_t curve_keys_size = curve_keys.size(); CurveKey *keys_ptr = NULL; + /* pack curve keys */ if(curve_keys_size) { - keys_ptr = &curve_keys[0]; for(size_t i = 0; i < curve_keys_size; i++) { - float3 p = keys_ptr[i].loc; - curve_key_co[i] = make_float4(p.x, p.y, p.z, keys_ptr[i].radius); + float3 p = keys_ptr[i].co; + float radius = keys_ptr[i].radius; + + curve_key_co[i] = make_float4(p.x, p.y, p.z, radius); } } - size_t curve_seg_num = curve_segs.size(); + /* pack curve segments */ + size_t curve_seg_num = curve_segments.size(); if(curve_seg_num) { - CurveSeg *curve_ptr = &curve_segs[0]; - + CurveSegment *curve_ptr = &curve_segments[0]; int shader_id = 0; for(size_t i = 0; i < curve_seg_num; i++) { - CurveSeg s = curve_ptr[i]; - shader_id = scene->shader_manager->get_shader_id(s.curveshader, this, false); + CurveSegment s = curve_ptr[i]; + shader_id = scene->shader_manager->get_shader_id(s.shader, this, false); - float3 p1 = keys_ptr[s.v[0]].loc; - float3 p2 = keys_ptr[s.v[1]].loc; + float3 p1 = keys_ptr[s.v[0]].co; + float3 p2 = keys_ptr[s.v[1]].co; float length = len(p2 - p1); curve_seg_keys[i] = make_float4( @@ -414,7 +409,7 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att og->attribute_map.clear(); og->object_names.clear(); - og->attribute_map.resize(scene->objects.size()); + og->attribute_map.resize(scene->objects.size()*ATTR_PRIM_TYPES); for(size_t i = 0; i < scene->objects.size(); i++) { /* set object name to object index map */ @@ -430,7 +425,8 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att osl_attr.elem = ATTR_ELEMENT_VALUE; osl_attr.value = attr; - og->attribute_map[i][attr.name()] = osl_attr; + og->attribute_map[i*ATTR_PRIM_TYPES][attr.name()] = osl_attr; + og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][attr.name()] = osl_attr; } /* find mesh attributes */ @@ -444,27 +440,46 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att /* set object attributes */ foreach(AttributeRequest& req, attributes.requests) { - if(req.element == ATTR_ELEMENT_NONE) - continue; - OSLGlobals::Attribute osl_attr; - osl_attr.elem = req.element; - osl_attr.offset = req.offset; - - if(req.type == TypeDesc::TypeFloat) - osl_attr.type = TypeDesc::TypeFloat; - else - osl_attr.type = TypeDesc::TypeColor; - - if(req.std != ATTR_STD_NONE) { - /* if standard attribute, add lookup by geom: name convention */ - ustring stdname(string("geom:") + string(attribute_standard_name(req.std))); - og->attribute_map[i][stdname] = osl_attr; + if(req.triangle_element != ATTR_ELEMENT_NONE) { + osl_attr.elem = req.triangle_element; + osl_attr.offset = req.triangle_offset; + + if(req.triangle_type == TypeDesc::TypeFloat) + osl_attr.type = TypeDesc::TypeFloat; + else + osl_attr.type = TypeDesc::TypeColor; + + if(req.std != ATTR_STD_NONE) { + /* if standard attribute, add lookup by geom: name convention */ + ustring stdname(string("geom:") + string(Attribute::standard_name(req.std))); + og->attribute_map[i*ATTR_PRIM_TYPES][stdname] = osl_attr; + } + else if(req.name != ustring()) { + /* add lookup by mesh attribute name */ + og->attribute_map[i*ATTR_PRIM_TYPES][req.name] = osl_attr; + } } - else if(req.name != ustring()) { - /* add lookup by mesh attribute name */ - og->attribute_map[i][req.name] = osl_attr; + + if(req.curve_element != ATTR_ELEMENT_NONE) { + osl_attr.elem = req.curve_element; + osl_attr.offset = req.curve_offset; + + if(req.curve_type == TypeDesc::TypeFloat) + osl_attr.type = TypeDesc::TypeFloat; + else + osl_attr.type = TypeDesc::TypeColor; + + if(req.std != ATTR_STD_NONE) { + /* if standard attribute, add lookup by geom: name convention */ + ustring stdname(string("geom:") + string(Attribute::standard_name(req.std))); + og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][stdname] = osl_attr; + } + else if(req.name != ustring()) { + /* add lookup by mesh attribute name */ + og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][req.name] = osl_attr; + } } } } @@ -480,7 +495,7 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce int attr_map_stride = 0; for(size_t i = 0; i < scene->meshes.size(); i++) - attr_map_stride = max(attr_map_stride, mesh_attributes[i].size()+1); + attr_map_stride = max(attr_map_stride, (mesh_attributes[i].size() + 1)*ATTR_PRIM_TYPES); if(attr_map_stride == 0) return; @@ -491,12 +506,13 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce for(size_t i = 0; i < scene->objects.size(); i++) { Object *object = scene->objects[i]; + Mesh *mesh = object->mesh; /* find mesh attributes */ size_t j; for(j = 0; j < scene->meshes.size(); j++) - if(scene->meshes[j] == object->mesh) + if(scene->meshes[j] == mesh) break; AttributeRequestSet& attributes = mesh_attributes[j]; @@ -512,14 +528,29 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce else id = scene->shader_manager->get_attribute_id(req.std); - attr_map[index].x = id; - attr_map[index].y = req.element; - attr_map[index].z = as_uint(req.offset); + if(mesh->triangles.size()) { + attr_map[index].x = id; + attr_map[index].y = req.triangle_element; + attr_map[index].z = as_uint(req.triangle_offset); - if(req.type == TypeDesc::TypeFloat) - attr_map[index].w = NODE_ATTR_FLOAT; - else - attr_map[index].w = NODE_ATTR_FLOAT3; + if(req.triangle_type == TypeDesc::TypeFloat) + attr_map[index].w = NODE_ATTR_FLOAT; + else + attr_map[index].w = NODE_ATTR_FLOAT3; + } + + index++; + + if(mesh->curve_segments.size()) { + attr_map[index].x = id; + attr_map[index].y = req.curve_element; + attr_map[index].z = as_uint(req.curve_offset); + + if(req.curve_type == TypeDesc::TypeFloat) + attr_map[index].w = NODE_ATTR_FLOAT; + else + attr_map[index].w = NODE_ATTR_FLOAT3; + } index++; } @@ -529,6 +560,15 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce attr_map[index].y = 0; attr_map[index].z = 0; attr_map[index].w = 0; + + index++; + + attr_map[index].x = ATTR_STD_NONE; + attr_map[index].y = 0; + attr_map[index].z = 0; + attr_map[index].w = 0; + + index++; } /* copy to device */ @@ -536,6 +576,60 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce device->tex_alloc("__attributes_map", dscene->attributes_map); } +static void update_attribute_element_offset(Mesh *mesh, vector<float>& attr_float, vector<float4>& attr_float3, + Attribute *mattr, TypeDesc& type, int& offset, AttributeElement& element) +{ + if(mattr) { + /* store element and type */ + element = mattr->element; + type = mattr->type; + + /* store attribute data in arrays */ + size_t size = mattr->element_size( + mesh->verts.size(), + mesh->triangles.size(), + mesh->curve_segments.size(), + mesh->curve_keys.size()); + + if(mattr->type == TypeDesc::TypeFloat) { + float *data = mattr->data_float(); + offset = attr_float.size(); + + attr_float.resize(attr_float.size() + size); + + for(size_t k = 0; k < size; k++) + attr_float[offset+k] = data[k]; + } + else { + float3 *data = mattr->data_float3(); + offset = attr_float3.size(); + + attr_float3.resize(attr_float3.size() + size); + + for(size_t k = 0; k < size; k++) + attr_float3[offset+k] = float3_to_float4(data[k]); + } + + /* mesh vertex/curve index is global, not per object, so we sneak + * a correction for that in here */ + if(element == ATTR_ELEMENT_VERTEX) + offset -= mesh->vert_offset; + else if(element == ATTR_ELEMENT_FACE) + offset -= mesh->tri_offset; + else if(element == ATTR_ELEMENT_CORNER) + offset -= 3*mesh->tri_offset; + else if(element == ATTR_ELEMENT_CURVE_SEGMENT) + offset -= mesh->curveseg_offset; + else if(element == ATTR_ELEMENT_CURVE_KEY) + offset -= mesh->curvekey_offset; + } + else { + /* attribute not found */ + element = ATTR_ELEMENT_NONE; + offset = 0; + } +} + void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) { progress.set_status("Updating Mesh", "Computing attributes"); @@ -569,66 +663,24 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, /* todo: we now store std and name attributes from requests even if * they actually refer to the same mesh attributes, optimize */ foreach(AttributeRequest& req, attributes.requests) { - Attribute *mattr = mesh->attributes.find(req); - - /* todo: get rid of this exception */ - if(!mattr && req.std == ATTR_STD_GENERATED) { - mattr = mesh->attributes.add(ATTR_STD_GENERATED); + Attribute *triangle_mattr = mesh->attributes.find(req); + Attribute *curve_mattr = mesh->curve_attributes.find(req); + + /* todo: get rid of this exception, it's only here for giving some + * working texture coordinate for subdivision as we can't preserve + * any attributes yet */ + if(!triangle_mattr && req.std == ATTR_STD_GENERATED) { + triangle_mattr = mesh->attributes.add(ATTR_STD_GENERATED); if(mesh->verts.size()) - memcpy(mattr->data_float3(), &mesh->verts[0], sizeof(float3)*mesh->verts.size()); + memcpy(triangle_mattr->data_float3(), &mesh->verts[0], sizeof(float3)*mesh->verts.size()); } - /* attribute not found */ - if(!mattr) { - req.element = ATTR_ELEMENT_NONE; - req.offset = 0; - continue; - } - - /* we abuse AttributeRequest to pass on info like element and - * offset, it doesn't really make sense but is convenient */ - - /* store element and type */ - if(mattr->element == Attribute::VERTEX) - req.element = ATTR_ELEMENT_VERTEX; - else if(mattr->element == Attribute::FACE) - req.element = ATTR_ELEMENT_FACE; - else if(mattr->element == Attribute::CORNER) - req.element = ATTR_ELEMENT_CORNER; - - req.type = mattr->type; - - /* store attribute data in arrays */ - size_t size = mattr->element_size(mesh->verts.size(), mesh->triangles.size()); - - if(mattr->type == TypeDesc::TypeFloat) { - float *data = mattr->data_float(); - req.offset = attr_float.size(); - - attr_float.resize(attr_float.size() + size); - - for(size_t k = 0; k < size; k++) - attr_float[req.offset+k] = data[k]; - } - else { - float3 *data = mattr->data_float3(); - req.offset = attr_float3.size(); - - attr_float3.resize(attr_float3.size() + size); - - for(size_t k = 0; k < size; k++) - attr_float3[req.offset+k] = float3_to_float4(data[k]); - } - - /* mesh vertex/triangle index is global, not per object, so we sneak - * a correction for that in here */ - if(req.element == ATTR_ELEMENT_VERTEX) - req.offset -= mesh->vert_offset; - else if(mattr->element == Attribute::FACE) - req.offset -= mesh->tri_offset; - else if(mattr->element == Attribute::CORNER) - req.offset -= 3*mesh->tri_offset; + update_attribute_element_offset(mesh, attr_float, attr_float3, triangle_mattr, + req.triangle_type, req.triangle_offset, req.triangle_element); + update_attribute_element_offset(mesh, attr_float, attr_float3, curve_mattr, + req.curve_type, req.curve_offset, req.curve_element); + if(progress.get_cancel()) return; } } @@ -660,21 +712,21 @@ void MeshManager::device_update_mesh(Device *device, DeviceScene *dscene, Scene size_t vert_size = 0; size_t tri_size = 0; - size_t CurveKey_size = 0; + size_t curve_key_size = 0; size_t curve_seg_keys = 0; foreach(Mesh *mesh, scene->meshes) { mesh->vert_offset = vert_size; mesh->tri_offset = tri_size; - mesh->curvekey_offset = CurveKey_size; + mesh->curvekey_offset = curve_key_size; mesh->curveseg_offset = curve_seg_keys; vert_size += mesh->verts.size(); tri_size += mesh->triangles.size(); - CurveKey_size += mesh->curve_keys.size(); - curve_seg_keys += mesh->curve_segs.size(); + curve_key_size += mesh->curve_keys.size(); + curve_seg_keys += mesh->curve_segments.size(); } if(tri_size != 0) { @@ -705,16 +757,16 @@ void MeshManager::device_update_mesh(Device *device, DeviceScene *dscene, Scene if(curve_seg_keys != 0) { progress.set_status("Updating Mesh", "Copying Strands to device"); - float4 *cur_keys = dscene->cur_keys.resize(CurveKey_size); - float4 *cur_segs = dscene->cur_segs.resize(curve_seg_keys); + float4 *curve_keys = dscene->curve_keys.resize(curve_key_size); + float4 *curve_segments = dscene->curve_segments.resize(curve_seg_keys); foreach(Mesh *mesh, scene->meshes) { - mesh->pack_curves(scene, &cur_keys[mesh->curvekey_offset], &cur_segs[mesh->curveseg_offset], mesh->curvekey_offset); + mesh->pack_curves(scene, &curve_keys[mesh->curvekey_offset], &curve_segments[mesh->curveseg_offset], mesh->curvekey_offset); if(progress.get_cancel()) return; } - device->tex_alloc("__cur_keys", dscene->cur_keys); - device->tex_alloc("__cur_segs", dscene->cur_segs); + device->tex_alloc("__curve_keys", dscene->curve_keys); + device->tex_alloc("__curve_segments", dscene->curve_segments); } } @@ -873,8 +925,8 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene) device->tex_free(dscene->tri_vnormal); device->tex_free(dscene->tri_vindex); device->tex_free(dscene->tri_verts); - device->tex_free(dscene->cur_segs); - device->tex_free(dscene->cur_keys); + device->tex_free(dscene->curve_segments); + device->tex_free(dscene->curve_keys); device->tex_free(dscene->attributes_map); device->tex_free(dscene->attributes_float); device->tex_free(dscene->attributes_float3); @@ -890,8 +942,8 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene) dscene->tri_vnormal.clear(); dscene->tri_vindex.clear(); dscene->tri_verts.clear(); - dscene->cur_segs.clear(); - dscene->cur_keys.clear(); + dscene->curve_segments.clear(); + dscene->curve_keys.clear(); dscene->attributes_map.clear(); dscene->attributes_float.clear(); dscene->attributes_float3.clear(); diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h index 24d3f02e082..ca8c755671f 100644 --- a/intern/cycles/render/mesh.h +++ b/intern/cycles/render/mesh.h @@ -50,26 +50,16 @@ public: int v[3]; }; - /* Mesh Strand Data*/ - struct CurveSeg { + /* Mesh Curve */ + struct CurveSegment { int v[2]; - uint curveshader; + uint shader; int curve; }; - struct Curve_Attribute { - float uv[2]; - }; - struct CurveKey { - float3 loc; + float3 co; float radius; - float time; - }; - - /*curve data for hair - currently only contains key tangent instead*/ - struct CurveData { - float3 tg; }; /* Displacement */ @@ -88,12 +78,11 @@ public: vector<bool> smooth; vector<CurveKey> curve_keys; - vector<CurveData> curve_keysCD; - vector<CurveSeg> curve_segs; - vector<Curve_Attribute> curve_attrib; + vector<CurveSegment> curve_segments; vector<uint> used_shaders; AttributeSet attributes; + AttributeSet curve_attributes; BoundBox bounds; bool transform_applied; @@ -116,12 +105,11 @@ public: Mesh(); ~Mesh(); - void reserve(int numverts, int numfaces); + void reserve(int numverts, int numfaces, int numcurves, int numcurvekeys); void clear(); void add_triangle(int v0, int v1, int v2, int shader, bool smooth); - void add_curvekey(float3 loc, float radius, float time); - void add_curve(int v0, int v1, int shader, int curveid); - void add_curveattrib(float u, float v); + void add_curve_key(float3 loc, float radius); + void add_curve_segment(int v0, int v1, int shader, int curveid); void compute_bounds(); void add_face_normals(); diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 13e9ae81cf0..14ef3c68ad3 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -2251,6 +2251,16 @@ HairInfoNode::HairInfoNode() add_output("Tangent Normal", SHADER_SOCKET_NORMAL); } +void HairInfoNode::attributes(AttributeRequestSet *attributes) +{ + ShaderOutput *intercept_out = output("Intercept"); + + if(!intercept_out->links.empty()) + attributes->add(ATTR_STD_CURVE_INTERCEPT); + + ShaderNode::attributes(attributes); +} + void HairInfoNode::compile(SVMCompiler& compiler) { ShaderOutput *out; @@ -2263,8 +2273,9 @@ void HairInfoNode::compile(SVMCompiler& compiler) out = output("Intercept"); if(!out->links.empty()) { + int attr = compiler.attribute(ATTR_STD_CURVE_INTERCEPT); compiler.stack_assign(out); - compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_INTERCEPT, out->stack_offset); + compiler.add_node(NODE_ATTR, attr, out->stack_offset, NODE_ATTR_FLOAT); } out = output("Thickness"); diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index ee7afccb0e1..564ceee5a5b 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -334,6 +334,8 @@ public: class HairInfoNode : public ShaderNode { public: SHADER_NODE_CLASS(HairInfoNode) + + void attributes(AttributeRequestSet *attributes); }; class ValueNode : public ShaderNode { diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 588b4d50e1b..4862b47c342 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -89,12 +89,9 @@ void Object::apply_transform() mesh->verts[i] = transform_point(&tfm, mesh->verts[i]); for(size_t i = 0; i < mesh->curve_keys.size(); i++) - mesh->curve_keys[i].loc = transform_point(&tfm, mesh->curve_keys[i].loc); - - for(size_t i = 0; i < mesh->curve_keysCD.size(); i++) - mesh->curve_keysCD[i].tg = transform_direction(&tfm, mesh->curve_keysCD[i].tg); - + mesh->curve_keys[i].co = transform_point(&tfm, mesh->curve_keys[i].co); + Attribute *attr_tangent = mesh->curve_attributes.find(ATTR_STD_CURVE_TANGENT); Attribute *attr_fN = mesh->attributes.find(ATTR_STD_FACE_NORMAL); Attribute *attr_vN = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL); @@ -119,6 +116,13 @@ void Object::apply_transform() vN[i] = transform_direction(&ntfm, vN[i]); } + if(attr_tangent) { + float3 *tangent = attr_tangent->data_float3(); + + for(size_t i = 0; i < mesh->curve_keys.size(); i++) + tangent[i] = transform_direction(&tfm, tangent[i]); + } + if(bounds.valid()) { mesh->compute_bounds(); compute_bounds(false, 0.0f); @@ -199,10 +203,10 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene surface_area += triangle_area(p1, p2, p3); } - foreach(Mesh::CurveSeg& t, mesh->curve_segs) { - float3 p1 = mesh->curve_keys[t.v[0]].loc; + foreach(Mesh::CurveSegment& t, mesh->curve_segments) { + float3 p1 = mesh->curve_keys[t.v[0]].co; float r1 = mesh->curve_keys[t.v[0]].radius; - float3 p2 = mesh->curve_keys[t.v[1]].loc; + float3 p2 = mesh->curve_keys[t.v[1]].co; float r2 = mesh->curve_keys[t.v[1]].radius; /* currently ignores segment overlaps*/ @@ -225,10 +229,10 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene surface_area += triangle_area(p1, p2, p3); } - foreach(Mesh::CurveSeg& t, mesh->curve_segs) { - float3 p1 = mesh->curve_keys[t.v[0]].loc; + foreach(Mesh::CurveSegment& t, mesh->curve_segments) { + float3 p1 = mesh->curve_keys[t.v[0]].co; float r1 = mesh->curve_keys[t.v[0]].radius; - float3 p2 = mesh->curve_keys[t.v[1]].loc; + float3 p2 = mesh->curve_keys[t.v[1]].co; float r2 = mesh->curve_keys[t.v[1]].radius; /* currently ignores segment overlaps*/ diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index 8b121d3b2fb..9490fd96be0 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -25,7 +25,6 @@ #include "kernel_types.h" -#include "util_attribute.h" #include "util_param.h" #include "util_string.h" #include "util_thread.h" @@ -74,8 +73,8 @@ public: device_vector<float4> tri_vindex; device_vector<float4> tri_verts; - device_vector<float4> cur_segs; - device_vector<float4> cur_keys; + device_vector<float4> curve_segments; + device_vector<float4> curve_keys; /* objects */ device_vector<float4> objects; |