Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2013-01-03 16:08:54 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2013-01-03 16:08:54 +0400
commit57cf48e7c6fd04f864072c21433a822907774f78 (patch)
tree45f3fa51f532a03e25c4d8ffa0c1be58027d01b2 /intern/cycles/render
parent8ca977b16e745f716d044a5b6ccbb5be4a70ac94 (diff)
Cycles Hair: refactoring to support generic attributes for hair curves. There
should be no functional changes yet. UV, tangent and intercept are now stored as attributes, with the intention to add more like multiple uv's, vertex colors, generated coordinates and motion vectors later. Things got a bit messy due to having both triangle and curve data in the same mesh data structure, which also gives us two sets of attributes. This will get cleaned up when we split the mesh class.
Diffstat (limited to 'intern/cycles/render')
-rw-r--r--intern/cycles/render/attribute.cpp205
-rw-r--r--intern/cycles/render/attribute.h46
-rw-r--r--intern/cycles/render/curves.h3
-rw-r--r--intern/cycles/render/light.cpp16
-rw-r--r--intern/cycles/render/mesh.cpp316
-rw-r--r--intern/cycles/render/mesh.h30
-rw-r--r--intern/cycles/render/nodes.cpp13
-rw-r--r--intern/cycles/render/nodes.h2
-rw-r--r--intern/cycles/render/object.cpp26
-rw-r--r--intern/cycles/render/scene.h5
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;