diff options
author | Stuart Broadfoot <gbroadfoot@hotmail.com> | 2012-12-28 18:21:30 +0400 |
---|---|---|
committer | Stuart Broadfoot <gbroadfoot@hotmail.com> | 2012-12-28 18:21:30 +0400 |
commit | e9ba345c46c93a193193f01d4bfac714a666d384 (patch) | |
tree | 49df9d78dc9327de642779e300e1592e5d7b3a42 /intern/cycles/render | |
parent | 857df8065face58eff5556953cdf2dd72e09f2b6 (diff) |
New feature
Patch [#33445] - Experimental Cycles Hair Rendering (CPU only)
This patch allows hair data to be exported to cycles and introduces a new line segment primitive to render with.
The UI appears under the particle tab and there is a new hair info node available.
It is only available under the experimental feature set and for cpu rendering.
Diffstat (limited to 'intern/cycles/render')
-rw-r--r-- | intern/cycles/render/CMakeLists.txt | 2 | ||||
-rw-r--r-- | intern/cycles/render/curves.cpp | 160 | ||||
-rw-r--r-- | intern/cycles/render/curves.h | 134 | ||||
-rw-r--r-- | intern/cycles/render/light.cpp | 37 | ||||
-rw-r--r-- | intern/cycles/render/mesh.cpp | 151 | ||||
-rw-r--r-- | intern/cycles/render/mesh.h | 34 | ||||
-rw-r--r-- | intern/cycles/render/nodes.cpp | 46 | ||||
-rw-r--r-- | intern/cycles/render/nodes.h | 5 | ||||
-rw-r--r-- | intern/cycles/render/object.cpp | 31 | ||||
-rw-r--r-- | intern/cycles/render/object.h | 1 | ||||
-rw-r--r-- | intern/cycles/render/scene.cpp | 12 | ||||
-rw-r--r-- | intern/cycles/render/scene.h | 6 |
12 files changed, 599 insertions, 20 deletions
diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt index 7907061c19c..d67a686d1e8 100644 --- a/intern/cycles/render/CMakeLists.txt +++ b/intern/cycles/render/CMakeLists.txt @@ -31,6 +31,7 @@ set(SRC object.cpp osl.cpp particles.cpp + curves.cpp scene.cpp session.cpp shader.cpp @@ -56,6 +57,7 @@ set(SRC_HEADERS object.h osl.h particles.h + curves.h scene.h session.h shader.h diff --git a/intern/cycles/render/curves.cpp b/intern/cycles/render/curves.cpp new file mode 100644 index 00000000000..3299503b4ab --- /dev/null +++ b/intern/cycles/render/curves.cpp @@ -0,0 +1,160 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "device.h" +#include "curves.h" +#include "mesh.h" +#include "object.h" +#include "scene.h" + +#include "util_foreach.h" +#include "util_map.h" +#include "util_progress.h" +#include "util_vector.h" + +CCL_NAMESPACE_BEGIN + +/* Hair System Manager */ + +CurveSystemManager::CurveSystemManager() +{ + primitive = CURVE_LINE_SEGMENTS; + line_method = CURVE_CORRECTED; + interpolation = CURVE_CARDINAL; + triangle_method = CURVE_CAMERA; + resolution = 3; + segments = 1; + + normalmix = 1.0f; + encasing_ratio = 1.01f; + + use_curves = true; + use_smooth = true; + use_cache = true; + use_parents = false; + use_encasing = true; + use_backfacing = false; + use_joined = false; + use_tangent_normal = false; + use_tangent_normal_geometry = false; + use_tangent_normal_correction = false; + + need_update = true; + need_mesh_update = false; +} + +CurveSystemManager::~CurveSystemManager() +{ +} + +void CurveSystemManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) +{ + if(!need_update) + return; + + device_free(device, dscene); + + progress.set_status("Updating Hair settings", "Copying Hair settings to device"); + + KernelCurves *kcurve= &dscene->data.curve_kernel_data; + + kcurve->curveflags = 0; + + if(primitive == CURVE_SEGMENTS) + kcurve->curveflags |= CURVE_KN_INTERPOLATE; + + if(line_method == CURVE_ACCURATE) + kcurve->curveflags |= CURVE_KN_ACCURATE; + if(line_method == CURVE_CORRECTED) + kcurve->curveflags |= CURVE_KN_INTERSECTCORRECTION; + if(line_method == CURVE_POSTCORRECTED) + kcurve->curveflags |= CURVE_KN_POSTINTERSECTCORRECTION; + + if(use_tangent_normal) + kcurve->curveflags |= CURVE_KN_TANGENTGNORMAL; + if(use_tangent_normal_correction) + kcurve->curveflags |= CURVE_KN_NORMALCORRECTION; + if(use_tangent_normal_geometry) + kcurve->curveflags |= CURVE_KN_TRUETANGENTGNORMAL; + if(use_joined) + kcurve->curveflags |= CURVE_KN_CURVEDATA; + if(use_backfacing) + kcurve->curveflags |= CURVE_KN_BACKFACING; + if(use_encasing) + kcurve->curveflags |= CURVE_KN_ENCLOSEFILTER; + + kcurve->normalmix = normalmix; + kcurve->encasing_ratio = encasing_ratio; + + if(progress.get_cancel()) return; + + need_update = false; +} + +void CurveSystemManager::device_free(Device *device, DeviceScene *dscene) +{ + +} + +bool CurveSystemManager::modified(const CurveSystemManager& CurveSystemManager) +{ + return !(line_method == CurveSystemManager.line_method && + interpolation == CurveSystemManager.interpolation && + primitive == CurveSystemManager.primitive && + use_encasing == CurveSystemManager.use_encasing && + use_tangent_normal == CurveSystemManager.use_tangent_normal && + use_tangent_normal_correction == CurveSystemManager.use_tangent_normal_correction && + use_tangent_normal_geometry == CurveSystemManager.use_tangent_normal_geometry && + encasing_ratio == CurveSystemManager.encasing_ratio && + use_backfacing == CurveSystemManager.use_backfacing && + normalmix == CurveSystemManager.normalmix && + use_cache == CurveSystemManager.use_cache && + use_smooth == CurveSystemManager.use_smooth && + triangle_method == CurveSystemManager.triangle_method && + resolution == CurveSystemManager.resolution && + use_curves == CurveSystemManager.use_curves && + use_joined == CurveSystemManager.use_joined && + segments == CurveSystemManager.segments && + use_parents == CurveSystemManager.use_parents); +} + +bool CurveSystemManager::modified_mesh(const CurveSystemManager& CurveSystemManager) +{ + return !(primitive == CurveSystemManager.primitive && + interpolation == CurveSystemManager.interpolation && + use_parents == CurveSystemManager.use_parents && + use_smooth == CurveSystemManager.use_smooth && + triangle_method == CurveSystemManager.triangle_method && + resolution == CurveSystemManager.resolution && + use_curves == CurveSystemManager.use_curves && + use_joined == CurveSystemManager.use_joined && + segments == CurveSystemManager.segments && + use_cache == CurveSystemManager.use_cache); +} + +void CurveSystemManager::tag_update(Scene *scene) +{ + need_update = true; +} + +void CurveSystemManager::tag_update_mesh() +{ + need_mesh_update = true; +} +CCL_NAMESPACE_END + diff --git a/intern/cycles/render/curves.h b/intern/cycles/render/curves.h new file mode 100644 index 00000000000..581b3010d77 --- /dev/null +++ b/intern/cycles/render/curves.h @@ -0,0 +1,134 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __CURVES_H__ +#define __CURVES_H__ + +#include "util_types.h" +#include "util_vector.h" + +CCL_NAMESPACE_BEGIN + +class Device; +class DeviceScene; +class Progress; +class Scene; + +typedef enum curve_presets { + CURVE_CUSTOM, + CURVE_TANGENT_SHADING, + CURVE_TRUE_NORMAL, + CURVE_ACCURATE_PRESET +} curve_presets; + +typedef enum curve_primitives { + CURVE_TRIANGLES, + CURVE_LINE_SEGMENTS, + CURVE_SEGMENTS +} curve_primitives; + +typedef enum curve_triangles { + CURVE_CAMERA, + CURVE_RIBBONS, + CURVE_TESSELATED +} curve_triangles; + +typedef enum curve_lines { + CURVE_ACCURATE, + CURVE_CORRECTED, + CURVE_POSTCORRECTED, + CURVE_UNCORRECTED +} curve_lines; + +typedef enum curve_interpolation { + CURVE_LINEAR, + CURVE_CARDINAL, + CURVE_BSPLINE +} curve_interpolation; + +class ParticleCurveData { + +public: + + ParticleCurveData(); + ~ParticleCurveData(); + + vector<int> psys_firstcurve; + vector<int> psys_curvenum; + vector<int> psys_shader; + + vector<float> psys_rootradius; + vector<float> psys_tipradius; + vector<float> psys_shape; + vector<bool> psys_closetip; + + vector<int> curve_firstkey; + vector<int> curve_keynum; + vector<float> curve_length; + vector<float> curve_u; + vector<float> curve_v; + + vector<float3> curvekey_co; + vector<float> curvekey_time; +}; + +/* HairSystem Manager */ + +class CurveSystemManager { +public: + + int primitive; + int line_method; + int interpolation; + int triangle_method; + int resolution; + int segments; + + float normalmix; + float encasing_ratio; + + bool use_curves; + bool use_smooth; + bool use_cache; + bool use_parents; + bool use_encasing; + bool use_backfacing; + bool use_tangent_normal; + bool use_tangent_normal_correction; + bool use_tangent_normal_geometry; + bool use_joined; + + bool need_update; + bool need_mesh_update; + + CurveSystemManager(); + ~CurveSystemManager(); + + void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); + void device_free(Device *device, DeviceScene *dscene); + bool modified(const CurveSystemManager& CurveSystemManager); + bool modified_mesh(const CurveSystemManager& CurveSystemManager); + + void tag_update(Scene *scene); + void tag_update_mesh(); +}; + +CCL_NAMESPACE_END + +#endif /* __CURVES_H__ */ + diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 4173da453fd..66e528c7230 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -142,6 +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; foreach(Object *object, scene->objects) { Mesh *mesh = object->mesh; @@ -169,10 +170,18 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen if(shader->sample_as_light && shader->has_surface_emission) num_triangles++; } + + /* disabled for strands*/ + /*for(size_t i = 0; i < mesh->curve_segs.size(); i++) { + * Shader *shader = scene->shaders[mesh->curve_segs[i].curveshader]; + * + * if(shader->sample_as_light && shader->has_surface_emission) + * num_curve_segs++; + }*/ } } - size_t num_distribution = num_triangles; + size_t num_distribution = num_triangles + num_curve_segs; num_distribution += num_lights; /* emission area */ @@ -234,6 +243,32 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen totarea += triangle_area(p1, p2, p3); } } + + /*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]; + * + * if(shader->sample_as_light && shader->has_surface_emission) { + * distribution[offset].x = totarea; + * distribution[offset].y = __int_as_float(i + mesh->curveseg_offset); + * distribution[offset].z = 0.0f; + * distribution[offset].w = __int_as_float(object_id); + * offset++; + * + * Mesh::CurveSeg s = mesh->curve_segs[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; + * float r2 = mesh->curve_keys[s.v[1]].radius; + * + * if(!transform_applied) { + * p1 = transform_point(&tfm, p1); + * p2 = transform_point(&tfm, p2); + * } + * + * totarea += M_PI_F * (r1 + r2) * len(p1 - p2); + * } + }*/ } if(progress.get_cancel()) return; diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index bc782a78c60..a2d545d51c0 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -51,6 +51,9 @@ Mesh::Mesh() tri_offset = 0; vert_offset = 0; + curveseg_offset = 0; + curvekey_offset = 0; + attributes.mesh = this; } @@ -66,6 +69,7 @@ void Mesh::reserve(int numverts, int numtris) 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); } @@ -77,6 +81,11 @@ void Mesh::clear() shader.clear(); smooth.clear(); + curve_keys.clear(); + curve_keysCD.clear(); + curve_segs.clear(); + curve_attrib.clear(); + attributes.clear(); used_shaders.clear(); @@ -96,14 +105,48 @@ 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) +{ + CurveKey ck; + ck.loc = loc; + ck.radius = radius; + ck.time = time; + + curve_keys.push_back(ck); +} + +void Mesh::add_curve(int v0, int v1, int shader, int curveid) +{ + CurveSeg s; + s.v[0] = v0; + s.v[1] = v1; + s.curveshader = 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); +} + void Mesh::compute_bounds() { BoundBox bnds = BoundBox::empty; size_t verts_size = verts.size(); + size_t curve_keys_size = curve_keys.size(); for(size_t i = 0; i < verts_size; i++) bnds.grow(verts[i]); + for(size_t i = 0; i < curve_keys_size; i++) + bnds.grow(curve_keys[i].loc, curve_keys[i].radius); + /* happens mostly on empty meshes */ if(!bnds.valid()) bnds.grow(make_float3(0.0f, 0.0f, 0.0f)); @@ -243,6 +286,45 @@ void Mesh::pack_verts(float4 *tri_verts, float4 *tri_vindex, size_t vert_offset) } } +void Mesh::pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_seg_keys, size_t curvekey_offset) +{ + size_t curve_keys_size = curve_keys.size(); + CurveKey *keys_ptr = NULL; + + 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); + } + } + + size_t curve_seg_num = curve_segs.size(); + + if(curve_seg_num) { + CurveSeg *curve_ptr = &curve_segs[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); + + float3 p1 = keys_ptr[s.v[0]].loc; + float3 p2 = keys_ptr[s.v[1]].loc; + float length = len(p2 - p1); + + curve_seg_keys[i] = make_float4( + __int_as_float(s.v[0] + curvekey_offset), + __int_as_float(s.v[1] + curvekey_offset), + __int_as_float(shader_id), + length); + } + } +} + void Mesh::compute_bvh(SceneParams *params, Progress *progress, int n, int total) { if(progress->get_cancel()) @@ -573,39 +655,62 @@ 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_seg_keys = 0; + foreach(Mesh *mesh, scene->meshes) { mesh->vert_offset = vert_size; mesh->tri_offset = tri_size; + mesh->curvekey_offset = CurveKey_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(); } - if(tri_size == 0) - return; + if(tri_size != 0) { + /* normals */ + progress.set_status("Updating Mesh", "Computing normals"); - /* normals */ - progress.set_status("Updating Mesh", "Computing normals"); + float4 *normal = dscene->tri_normal.resize(tri_size); + float4 *vnormal = dscene->tri_vnormal.resize(vert_size); + float4 *tri_verts = dscene->tri_verts.resize(vert_size); + float4 *tri_vindex = dscene->tri_vindex.resize(tri_size); - float4 *normal = dscene->tri_normal.resize(tri_size); - float4 *vnormal = dscene->tri_vnormal.resize(vert_size); - float4 *tri_verts = dscene->tri_verts.resize(vert_size); - float4 *tri_vindex = dscene->tri_vindex.resize(tri_size); + foreach(Mesh *mesh, scene->meshes) { + mesh->pack_normals(scene, &normal[mesh->tri_offset], &vnormal[mesh->vert_offset]); + mesh->pack_verts(&tri_verts[mesh->vert_offset], &tri_vindex[mesh->tri_offset], mesh->vert_offset); - foreach(Mesh *mesh, scene->meshes) { - mesh->pack_normals(scene, &normal[mesh->tri_offset], &vnormal[mesh->vert_offset]); - mesh->pack_verts(&tri_verts[mesh->vert_offset], &tri_vindex[mesh->tri_offset], mesh->vert_offset); + if(progress.get_cancel()) return; + } - if(progress.get_cancel()) return; + /* vertex coordinates */ + progress.set_status("Updating Mesh", "Copying Mesh to device"); + + device->tex_alloc("__tri_normal", dscene->tri_normal); + device->tex_alloc("__tri_vnormal", dscene->tri_vnormal); + device->tex_alloc("__tri_verts", dscene->tri_verts); + device->tex_alloc("__tri_vindex", dscene->tri_vindex); } - /* vertex coordinates */ - progress.set_status("Updating Mesh", "Copying Mesh to device"); + 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); - device->tex_alloc("__tri_normal", dscene->tri_normal); - device->tex_alloc("__tri_vnormal", dscene->tri_vnormal); - device->tex_alloc("__tri_verts", dscene->tri_verts); - device->tex_alloc("__tri_vindex", dscene->tri_vindex); + foreach(Mesh *mesh, scene->meshes) { + mesh->pack_curves(scene, &cur_keys[mesh->curvekey_offset], &cur_segs[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); + } } void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) @@ -642,6 +747,10 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene * dscene->tri_woop.reference(&pack.tri_woop[0], pack.tri_woop.size()); device->tex_alloc("__tri_woop", dscene->tri_woop); } + if(pack.prim_type.size()) { + dscene->prim_type.reference((uint*)&pack.prim_type[0], pack.prim_type.size()); + device->tex_alloc("__prim_type", dscene->prim_type); + } if(pack.prim_visibility.size()) { dscene->prim_visibility.reference((uint*)&pack.prim_visibility[0], pack.prim_visibility.size()); device->tex_alloc("__prim_visibility", dscene->prim_visibility); @@ -751,6 +860,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene) device->tex_free(dscene->bvh_nodes); device->tex_free(dscene->object_node); device->tex_free(dscene->tri_woop); + device->tex_free(dscene->prim_type); device->tex_free(dscene->prim_visibility); device->tex_free(dscene->prim_index); device->tex_free(dscene->prim_object); @@ -758,6 +868,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->attributes_map); device->tex_free(dscene->attributes_float); device->tex_free(dscene->attributes_float3); @@ -765,6 +877,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene) dscene->bvh_nodes.clear(); dscene->object_node.clear(); dscene->tri_woop.clear(); + dscene->prim_type.clear(); dscene->prim_visibility.clear(); dscene->prim_index.clear(); dscene->prim_object.clear(); @@ -772,6 +885,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->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 637143f5adf..24d3f02e082 100644 --- a/intern/cycles/render/mesh.h +++ b/intern/cycles/render/mesh.h @@ -50,6 +50,28 @@ public: int v[3]; }; + /* Mesh Strand Data*/ + struct CurveSeg { + int v[2]; + uint curveshader; + int curve; + }; + + struct Curve_Attribute { + float uv[2]; + }; + + struct CurveKey { + float3 loc; + float radius; + float time; + }; + + /*curve data for hair - currently only contains key tangent instead*/ + struct CurveData { + float3 tg; + }; + /* Displacement */ enum DisplacementMethod { DISPLACE_BUMP, @@ -65,6 +87,11 @@ public: vector<uint> shader; vector<bool> smooth; + vector<CurveKey> curve_keys; + vector<CurveData> curve_keysCD; + vector<CurveSeg> curve_segs; + vector<Curve_Attribute> curve_attrib; + vector<uint> used_shaders; AttributeSet attributes; @@ -82,6 +109,9 @@ public: size_t tri_offset; size_t vert_offset; + size_t curveseg_offset; + size_t curvekey_offset; + /* Functions */ Mesh(); ~Mesh(); @@ -89,6 +119,9 @@ public: void reserve(int numverts, int numfaces); 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 compute_bounds(); void add_face_normals(); @@ -96,6 +129,7 @@ public: void pack_normals(Scene *scene, float4 *normal, float4 *vnormal); void pack_verts(float4 *tri_verts, float4 *tri_vindex, size_t vert_offset); + void pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_seg_keys, size_t curvekey_offset); void compute_bvh(SceneParams *params, Progress *progress, int n, int total); bool need_attribute(Scene *scene, AttributeStandard std); diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index aef28449e44..23d6432616c 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -2240,6 +2240,52 @@ void ParticleInfoNode::compile(OSLCompiler& compiler) compiler.add(this, "node_particle_info"); } +/* Hair Info */ + +HairInfoNode::HairInfoNode() +: ShaderNode("hair_info") +{ + add_output("Is Strand", SHADER_SOCKET_FLOAT); + add_output("Intercept", SHADER_SOCKET_FLOAT); + add_output("Thickness", SHADER_SOCKET_FLOAT); + add_output("Tangent Normal", SHADER_SOCKET_NORMAL); +} + +void HairInfoNode::compile(SVMCompiler& compiler) +{ + ShaderOutput *out; + + out = output("Is Strand"); + if(!out->links.empty()) { + compiler.stack_assign(out); + compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_IS_STRAND, out->stack_offset); + } + + out = output("Intercept"); + if(!out->links.empty()) { + compiler.stack_assign(out); + compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_INTERCEPT, out->stack_offset); + } + + out = output("Thickness"); + if(!out->links.empty()) { + compiler.stack_assign(out); + compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_THICKNESS, out->stack_offset); + } + + out = output("Tangent Normal"); + if(!out->links.empty()) { + compiler.stack_assign(out); + compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_TANGENT_NORMAL, out->stack_offset); + } + +} + +void HairInfoNode::compile(OSLCompiler& compiler) +{ + compiler.add(this, "NODE_HAIR_INFO"); +} + /* Value */ ValueNode::ValueNode() diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 8012a99ff05..ee7afccb0e1 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -331,6 +331,11 @@ public: void attributes(AttributeRequestSet *attributes); }; +class HairInfoNode : public ShaderNode { +public: + SHADER_NODE_CLASS(HairInfoNode) +}; + class ValueNode : public ShaderNode { public: SHADER_NODE_CLASS(ValueNode) diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 5df8e8c1368..588b4d50e1b 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -19,6 +19,7 @@ #include "device.h" #include "light.h" #include "mesh.h" +#include "curves.h" #include "object.h" #include "scene.h" @@ -45,6 +46,7 @@ Object::Object() motion.post = transform_identity(); use_motion = false; use_holdout = false; + curverender = false; } Object::~Object() @@ -86,6 +88,13 @@ void Object::apply_transform() for(size_t i = 0; i < mesh->verts.size(); i++) 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); + + Attribute *attr_fN = mesh->attributes.find(ATTR_STD_FACE_NORMAL); Attribute *attr_vN = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL); @@ -133,6 +142,7 @@ void Object::tag_update(Scene *scene) } } + scene->curve_system_manager->need_update = true; scene->mesh_manager->need_update = true; scene->object_manager->need_update = true; } @@ -189,6 +199,16 @@ 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; + float r1 = mesh->curve_keys[t.v[0]].radius; + float3 p2 = mesh->curve_keys[t.v[1]].loc; + float r2 = mesh->curve_keys[t.v[1]].radius; + + /* currently ignores segment overlaps*/ + surface_area += M_PI_F *(r1 + r2) * len(p1 - p2); + } + surface_area_map[mesh] = surface_area; } else @@ -204,6 +224,16 @@ 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; + float r1 = mesh->curve_keys[t.v[0]].radius; + float3 p2 = mesh->curve_keys[t.v[1]].loc; + float r2 = mesh->curve_keys[t.v[1]].radius; + + /* currently ignores segment overlaps*/ + surface_area += M_PI_F *(r1 + r2) * len(p1 - p2); + } } /* pack in texture */ @@ -355,6 +385,7 @@ void ObjectManager::apply_static_transforms(Scene *scene, uint *object_flag, Pro void ObjectManager::tag_update(Scene *scene) { need_update = true; + scene->curve_system_manager->need_update = true; scene->mesh_manager->need_update = true; scene->light_manager->need_update = true; } diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h index 9c9b11bc29c..9ba500ca4d6 100644 --- a/intern/cycles/render/object.h +++ b/intern/cycles/render/object.h @@ -48,6 +48,7 @@ public: MotionTransform motion; bool use_motion; bool use_holdout; + bool curverender; float3 dupli_generated; float2 dupli_uv; diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index 8085cfdd3e6..093bfecf88e 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -29,6 +29,7 @@ #include "mesh.h" #include "object.h" #include "particles.h" +#include "curves.h" #include "scene.h" #include "svm.h" #include "osl.h" @@ -54,6 +55,7 @@ Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_) integrator = new Integrator(); image_manager = new ImageManager(); particle_system_manager = new ParticleSystemManager(); + curve_system_manager = new CurveSystemManager(); /* OSL only works on the CPU */ if(device_info_.type == DEVICE_CPU) @@ -96,6 +98,7 @@ void Scene::free_memory(bool final) light_manager->device_free(device, &dscene); particle_system_manager->device_free(device, &dscene); + curve_system_manager->device_free(device, &dscene); if(!params.persistent_images || final) image_manager->device_free(device, &dscene); @@ -112,6 +115,7 @@ void Scene::free_memory(bool final) delete shader_manager; delete light_manager; delete particle_system_manager; + delete curve_system_manager; delete image_manager; } else { @@ -165,6 +169,11 @@ void Scene::device_update(Device *device_, Progress& progress) if(progress.get_cancel()) return; + progress.set_status("Updating Hair Systems"); + curve_system_manager->device_update(device, &dscene, this, progress); + + if(progress.get_cancel()) return; + progress.set_status("Updating Meshes"); mesh_manager->device_update(device, &dscene, this, progress); @@ -242,7 +251,8 @@ bool Scene::need_reset() || filter->need_update || integrator->need_update || shader_manager->need_update - || particle_system_manager->need_update); + || particle_system_manager->need_update + || curve_system_manager->need_update); } void Scene::reset() diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index ebe932e40e7..8b121d3b2fb 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -50,6 +50,7 @@ class Object; class ObjectManager; class ParticleSystemManager; class ParticleSystem; +class CurveSystemManager; class Shader; class ShaderManager; class Progress; @@ -62,6 +63,7 @@ public: device_vector<float4> bvh_nodes; device_vector<uint> object_node; device_vector<float4> tri_woop; + device_vector<uint> prim_type; device_vector<uint> prim_visibility; device_vector<uint> prim_index; device_vector<uint> prim_object; @@ -72,6 +74,9 @@ public: device_vector<float4> tri_vindex; device_vector<float4> tri_verts; + device_vector<float4> cur_segs; + device_vector<float4> cur_keys; + /* objects */ device_vector<float4> objects; device_vector<float4> objects_vector; @@ -170,6 +175,7 @@ public: MeshManager *mesh_manager; ObjectManager *object_manager; ParticleSystemManager *particle_system_manager; + CurveSystemManager *curve_system_manager; /* default shaders */ int default_surface; |