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.
This commit is contained in:
@@ -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
|
||||
|
160
intern/cycles/render/curves.cpp
Normal file
160
intern/cycles/render/curves.cpp
Normal file
@@ -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
|
||||
|
134
intern/cycles/render/curves.h
Normal file
134
intern/cycles/render/curves.h
Normal file
@@ -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__ */
|
||||
|
@@ -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;
|
||||
|
@@ -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");
|
||||
|
||||
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);
|
||||
float4 *cur_keys = dscene->cur_keys.resize(CurveKey_size);
|
||||
float4 *cur_segs = dscene->cur_segs.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);
|
||||
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();
|
||||
|
@@ -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);
|
||||
|
@@ -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()
|
||||
|
@@ -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)
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -48,6 +48,7 @@ public:
|
||||
MotionTransform motion;
|
||||
bool use_motion;
|
||||
bool use_holdout;
|
||||
bool curverender;
|
||||
|
||||
float3 dupli_generated;
|
||||
float2 dupli_uv;
|
||||
|
@@ -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()
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user