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.
This commit is contained in:
Brecht Van Lommel 2013-01-03 12:08:54 +00:00
parent 8ca977b16e
commit 57cf48e7c6
41 changed files with 1052 additions and 945 deletions

@ -67,8 +67,7 @@ ParticleCurveData::~ParticleCurveData()
curve_firstkey.clear();
curve_keynum.clear();
curve_length.clear();
curve_u.clear();
curve_v.clear();
curve_uv.clear();
curvekey_co.clear();
curvekey_time.clear();
@ -78,13 +77,13 @@ void interp_weights(float t, float data[4], int type)
{
float t2, t3, fc;
if (type == CURVE_LINEAR) {
if(type == CURVE_LINEAR) {
data[0] = 0.0f;
data[1] = -t + 1.0f;
data[2] = t;
data[3] = 0.0f;
}
else if (type == CURVE_CARDINAL) {
else if(type == CURVE_CARDINAL) {
t2 = t * t;
t3 = t2 * t;
fc = 0.71f;
@ -94,7 +93,7 @@ void interp_weights(float t, float data[4], int type)
data[2] = (fc - 2.0f) * t3 + (3.0f - 2.0f * fc) * t2 + fc * t;
data[3] = fc * t3 - fc * t2;
}
else if (type == CURVE_BSPLINE) {
else if(type == CURVE_BSPLINE) {
t2 = t * t;
t3 = t2 * t;
@ -115,8 +114,8 @@ void curveinterp_v3_v3v3v3v3(float3 *p, float3 *v1, float3 *v2, float3 *v3, floa
float shaperadius(float shape, float root, float tip, float time)
{
float radius = 1.0f - time;
if (shape != 0.0f) {
if (shape < 0.0f)
if(shape != 0.0f) {
if(shape < 0.0f)
radius = (float)pow(1.0f - time, 1.f + shape);
else
radius = (float)pow(1.0f - time, 1.f / (1.f - shape));
@ -133,10 +132,10 @@ void InterpolateKeySegments(int seg, int segno, int key, int curve, float3 *keyl
float3 ckey_loc3 = CData->curvekey_co[key+1];
float3 ckey_loc4 = ckey_loc3;
if (key > CData->curve_firstkey[curve])
if(key > CData->curve_firstkey[curve])
ckey_loc1 = CData->curvekey_co[key - 1];
if (key < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2)
if(key < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2)
ckey_loc4 = CData->curvekey_co[key + 2];
@ -167,7 +166,7 @@ bool ObtainParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Particle
BL::Object::modifiers_iterator b_mod;
for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (b_mod->show_viewport()) && (b_mod->show_render())) {
if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (b_mod->show_viewport()) && (b_mod->show_render())) {
BL::ParticleSystemModifier psmd(b_mod->ptr);
@ -213,7 +212,7 @@ bool ObtainParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Particle
float nco[3];
b_cKey->co_object( *b_ob, psmd, *b_pa, nco);
float3 cKey = make_float3(nco[0],nco[1],nco[2]);
if (step_no > 0)
if(step_no > 0)
curve_length += len(cKey - pcKey);
CData->curvekey_co.push_back(cKey);
CData->curvekey_time.push_back(curve_length);
@ -227,11 +226,10 @@ bool ObtainParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Particle
BL::Mesh::tessface_uv_textures_iterator l;
b_mesh->tessface_uv_textures.begin(l);
float uvs[3] = {0,0};
float3 uv = make_float3(0.0f, 0.0f, 0.0f);
if(b_mesh->tessface_uv_textures.length())
b_pa->uv_on_emitter(psmd,uvs);
CData->curve_u.push_back(uvs[0]);
CData->curve_v.push_back(uvs[1]);
b_pa->uv_on_emitter(psmd,&uv.x);
CData->curve_uv.push_back(uv);
curvenum++;
@ -258,7 +256,7 @@ bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par
BL::Object::modifiers_iterator b_mod;
for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (b_mod->show_viewport()) && (b_mod->show_render())) {
if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (b_mod->show_viewport()) && (b_mod->show_render())) {
BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
@ -277,10 +275,10 @@ bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par
int totchild = b_psys.child_particles.length() * b_psys.settings().draw_percentage() / 100;
int totcurves = totchild;
if (use_parents || b_psys.settings().child_type() == 0)
if(use_parents || b_psys.settings().child_type() == 0)
totcurves += totparts;
if (totcurves == 0)
if(totcurves == 0)
continue;
PointerRNA cpsys = RNA_pointer_get(&b_part.ptr, "cycles");
@ -314,7 +312,7 @@ bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par
b_psys.co_hair(*b_ob, psmd, pa_no, step_no, nco);
float3 cKey = make_float3(nco[0],nco[1],nco[2]);
cKey = transform_point(&itfm, cKey);
if (step_no > 0)
if(step_no > 0)
curve_length += len(cKey - pcKey);
CData->curvekey_co.push_back(cKey);
CData->curvekey_time.push_back(curve_length);
@ -327,17 +325,14 @@ bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par
BL::Mesh::tessface_uv_textures_iterator l;
b_mesh->tessface_uv_textures.begin(l);
float uvs[2] = {0,0};
float3 uv = make_float3(0.0f, 0.0f, 0.0f);
if(b_mesh->tessface_uv_textures.length())
b_psys.uv_on_emitter(psmd, *b_pa, pa_no, uvs);
b_psys.uv_on_emitter(psmd, *b_pa, pa_no, &uv.x);
CData->curve_uv.push_back(uv);
if(pa_no < totparts && b_pa != b_psys.particles.end())
++b_pa;
CData->curve_u.push_back(uvs[0]);
CData->curve_v.push_back(uvs[1]);
curvenum++;
}
@ -365,11 +360,11 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, int interpo
float3 v1;
if (curvekey == CData->curve_firstkey[curve]) {
if(curvekey == CData->curve_firstkey[curve]) {
subv = 0;
v1 = CData->curvekey_co[curvekey+2] - CData->curvekey_co[curvekey];
}
else if (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2)
else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2)
v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey - 2];
else
v1 = CData->curvekey_co[curvekey + 1] - CData->curvekey_co[curvekey - 1];
@ -387,10 +382,10 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, int interpo
float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
if (CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
if ((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (subv == segments))
if((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (subv == segments))
radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.95f);
xbasis = normalize(cross(v1,RotCam - ickey_loc));
@ -408,7 +403,7 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, int interpo
}
}
mesh->reserve(mesh->verts.size(), mesh->triangles.size());
mesh->reserve(mesh->verts.size(), mesh->triangles.size(), 0, 0);
mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
mesh->add_face_normals();
@ -439,11 +434,11 @@ void ExportCurveTriangleRibbons(Mesh *mesh, ParticleCurveData *CData, int interp
float3 v1;
float3 v2;
if (curvekey == CData->curve_firstkey[curve]) {
if(curvekey == CData->curve_firstkey[curve]) {
v1 = CData->curvekey_co[curvekey+2] - CData->curvekey_co[curvekey+1];
v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
}
else if (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) {
else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) {
v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[curvekey-2];
}
@ -467,12 +462,12 @@ void ExportCurveTriangleRibbons(Mesh *mesh, ParticleCurveData *CData, int interp
float3 v2;
float3 xbasis;
if (curvekey == CData->curve_firstkey[curve]) {
if(curvekey == CData->curve_firstkey[curve]) {
subv = 0;
v1 = CData->curvekey_co[curvekey+2] - CData->curvekey_co[curvekey+1];
v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
}
else if (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) {
else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) {
v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[curvekey-2];
}
@ -502,10 +497,10 @@ void ExportCurveTriangleRibbons(Mesh *mesh, ParticleCurveData *CData, int interp
float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
if (CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
if ((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (subv == segments))
if((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (subv == segments))
radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.95f);
float3 ickey_loc_shfl = ickey_loc - radius * xbasis;
@ -522,7 +517,7 @@ void ExportCurveTriangleRibbons(Mesh *mesh, ParticleCurveData *CData, int interp
}
}
mesh->reserve(mesh->verts.size(), mesh->triangles.size());
mesh->reserve(mesh->verts.size(), mesh->triangles.size(), 0, 0);
mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
mesh->add_face_normals();
@ -553,11 +548,11 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int inter
float3 v1;
float3 v2;
if (curvekey == CData->curve_firstkey[curve]) {
if(curvekey == CData->curve_firstkey[curve]) {
v1 = CData->curvekey_co[curvekey+2] - CData->curvekey_co[curvekey+1];
v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
}
else if (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) {
else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) {
v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[curvekey-2];
}
@ -582,12 +577,12 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int inter
float3 v1;
float3 v2;
if (curvekey == CData->curve_firstkey[curve]) {
if(curvekey == CData->curve_firstkey[curve]) {
subv = 0;
v1 = CData->curvekey_co[curvekey+2] - CData->curvekey_co[curvekey+1];
v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
}
else if (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) {
else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) {
v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[curvekey-2];
}
@ -619,10 +614,10 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int inter
float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
if (CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
if ((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (subv == segments))
if((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (subv == segments))
radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.95f);
float angle = 2 * M_PI_F / (float)resolution;
@ -645,7 +640,7 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int inter
}
}
mesh->reserve(mesh->verts.size(), mesh->triangles.size());
mesh->reserve(mesh->verts.size(), mesh->triangles.size(), 0, 0);
mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
mesh->add_face_normals();
@ -661,9 +656,12 @@ void ExportCurveSegments(Mesh *mesh, ParticleCurveData *CData, int interpolation
int curs = 0;
int segs = 0;
if(!(mesh->curve_segs.empty() && mesh->curve_keys.empty() && mesh->curve_attrib.empty()))
if(!(mesh->curve_segments.empty() && mesh->curve_keys.empty()))
return;
Attribute *attr_uv = mesh->curve_attributes.add(ATTR_STD_UV);
Attribute *attr_intercept = mesh->curve_attributes.add(ATTR_STD_CURVE_INTERCEPT);
for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
if(CData->psys_curvenum[sys] == 0)
@ -677,7 +675,7 @@ void ExportCurveSegments(Mesh *mesh, ParticleCurveData *CData, int interpolation
for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
int subv = 1;
if (curvekey == CData->curve_firstkey[curve])
if(curvekey == CData->curve_firstkey[curve])
subv = 0;
for (; subv <= segments; subv++) {
@ -685,20 +683,22 @@ void ExportCurveSegments(Mesh *mesh, ParticleCurveData *CData, int interpolation
float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
float time = 0.0f;
if ((interpolation == CURVE_BSPLINE) && (curvekey == CData->curve_firstkey[curve]) && (subv == 0))
if((interpolation == CURVE_BSPLINE) && (curvekey == CData->curve_firstkey[curve]) && (subv == 0))
ickey_loc = CData->curvekey_co[curvekey];
else
InterpolateKeySegments(subv, segments, curvekey, curve, &ickey_loc, &time, CData , interpolation);
float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
if (CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
radius =0.0f;
mesh->add_curvekey(ickey_loc, radius, time);
mesh->add_curve_key(ickey_loc, radius);
attr_intercept->add(time);
if(subv != 0) {
mesh->add_curve(cks - 1, cks, CData->psys_shader[sys], curs);
attr_uv->add(CData->curve_uv[curve]);
mesh->add_curve_segment(cks - 1, cks, CData->psys_shader[sys], curs);
segs++;
}
@ -706,18 +706,17 @@ void ExportCurveSegments(Mesh *mesh, ParticleCurveData *CData, int interpolation
}
}
mesh->add_curveattrib(CData->curve_u[curve], CData->curve_v[curve]);
curs++;
}
}
/* check allocation*/
if((mesh->curve_keys.size() != cks) || (mesh->curve_segs.size() != segs) || (mesh->curve_attrib.size() != curs)) {
if((mesh->curve_keys.size() != cks) || (mesh->curve_segments.size() != segs)) {
/* allocation failed -> clear data */
mesh->curve_keys.clear();
mesh->curve_segs.clear();
mesh->curve_attrib.clear();
mesh->curve_segments.clear();
mesh->curve_attributes.clear();
}
}
@ -734,7 +733,7 @@ void BlenderSync::sync_curve_settings()
curve_system_manager->use_curves = get_boolean(csscene, "use_curves");
if (preset == CURVE_CUSTOM) {
if(preset == CURVE_CUSTOM) {
/*custom properties*/
curve_system_manager->primitive = get_enum(csscene, "primitive");
curve_system_manager->line_method = get_enum(csscene, "line_method");
@ -824,15 +823,18 @@ void BlenderSync::sync_curve_settings()
void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool object_updated)
{
/* Clear stored curve data */
mesh->curve_attrib.clear();
mesh->curve_keys.clear();
mesh->curve_keysCD.clear();
mesh->curve_segs.clear();
mesh->curve_segments.clear();
mesh->curve_attributes.clear();
/* obtain general settings */
bool use_curves = scene->curve_system_manager->use_curves;
if(use_curves && b_ob.mode() == b_ob.mode_OBJECT) {
if(!(use_curves && b_ob.mode() == b_ob.mode_OBJECT)) {
mesh->compute_bounds();
return;
}
int primitive = scene->curve_system_manager->primitive;
int interpolation = scene->curve_system_manager->interpolation;
int triangle_method = scene->curve_system_manager->triangle_method;
@ -845,12 +847,12 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool
/* extract particle hair data - should be combined with connecting to mesh later*/
ParticleCurveData *CData = new ParticleCurveData();
ParticleCurveData CData;
if (use_cache)
ObtainCacheParticleData(mesh, &b_mesh, &b_ob, CData, use_parents);
if(use_cache)
ObtainCacheParticleData(mesh, &b_mesh, &b_ob, &CData, use_parents);
else
ObtainParticleData(mesh, &b_mesh, &b_ob, CData);
ObtainParticleData(mesh, &b_mesh, &b_ob, &CData);
/* attach strands to mesh */
BL::Object b_CamOb = b_scene.camera();
@ -862,37 +864,33 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool
RotCam = transform_point(&itfm, make_float3(ctfm.x.w, ctfm.y.w, ctfm.z.w));
}
if (primitive == CURVE_TRIANGLES){
if (triangle_method == CURVE_CAMERA)
ExportCurveTrianglePlanes(mesh, CData, interpolation, use_smooth, segments, RotCam);
else if (triangle_method == CURVE_RIBBONS)
ExportCurveTriangleRibbons(mesh, CData, interpolation, use_smooth, segments);
if(primitive == CURVE_TRIANGLES){
if(triangle_method == CURVE_CAMERA)
ExportCurveTrianglePlanes(mesh, &CData, interpolation, use_smooth, segments, RotCam);
else if(triangle_method == CURVE_RIBBONS)
ExportCurveTriangleRibbons(mesh, &CData, interpolation, use_smooth, segments);
else
ExportCurveTriangleGeometry(mesh, CData, interpolation, use_smooth, resolution, segments);
ExportCurveTriangleGeometry(mesh, &CData, interpolation, use_smooth, resolution, segments);
}
else {
ExportCurveSegments(mesh, CData, interpolation, segments);
ExportCurveSegments(mesh, &CData, interpolation, segments);
int ckey_num = mesh->curve_keys.size();
/*export tangents or curve data? - not functional yet*/
if (export_tgs && ckey_num > 1) {
if(export_tgs && ckey_num > 1) {
Attribute *attr_tangent = mesh->curve_attributes.add(ATTR_STD_CURVE_TANGENT);
float3 *data_tangent = attr_tangent->data_float3();
for(int ck = 0; ck < ckey_num; ck++) {
Mesh::CurveData SCD;
SCD.tg = normalize(normalize(mesh->curve_keys[min(ck + 1, ckey_num - 1)].loc - mesh->curve_keys[ck].loc) -
normalize(mesh->curve_keys[max(ck - 1, 0)].loc - mesh->curve_keys[ck].loc));
mesh->curve_keysCD.push_back(SCD);
float3 tg = normalize(normalize(mesh->curve_keys[min(ck + 1, ckey_num - 1)].co - mesh->curve_keys[ck].co) -
normalize(mesh->curve_keys[max(ck - 1, 0)].co - mesh->curve_keys[ck].co));
data_tangent[ck] = tg;
}
}
}
delete CData;
}
mesh->compute_bounds();
}

@ -147,7 +147,7 @@ static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_la
if(active_render)
attr = mesh->attributes.add(ATTR_STD_UV_TANGENT, name);
else
attr = mesh->attributes.add(name, TypeDesc::TypeVector, Attribute::CORNER);
attr = mesh->attributes.add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER);
float3 *tangent = attr->data_float3();
@ -161,7 +161,7 @@ static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_la
if(active_render)
attr_sign = mesh->attributes.add(ATTR_STD_UV_TANGENT_SIGN, name_sign);
else
attr_sign = mesh->attributes.add(name_sign, TypeDesc::TypeFloat, Attribute::CORNER);
attr_sign = mesh->attributes.add(name_sign, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER);
tangent_sign = attr_sign->data_float();
}
@ -249,7 +249,7 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
continue;
Attribute *attr = mesh->attributes.add(
ustring(l->name().c_str()), TypeDesc::TypeColor, Attribute::CORNER);
ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER);
BL::MeshColorLayer::data_iterator c;
float3 *fdata = attr->data_float3();
@ -288,7 +288,7 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
if(active_render)
attr = mesh->attributes.add(std, name);
else
attr = mesh->attributes.add(name, TypeDesc::TypePoint, Attribute::CORNER);
attr = mesh->attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);
BL::MeshTextureFaceLayer::data_iterator t;
float3 *fdata = attr->data_float3();

@ -76,9 +76,7 @@ bool BVH::cache_read(CacheData& key)
key.add(ob->mesh->verts);
key.add(ob->mesh->triangles);
key.add(ob->mesh->curve_keys);
key.add(ob->mesh->curve_keysCD);
key.add(ob->mesh->curve_segs);
key.add(ob->mesh->curve_attrib);
key.add(ob->mesh->curve_segments);
key.add(&ob->bounds, sizeof(ob->bounds));
key.add(&ob->visibility, sizeof(ob->visibility));
key.add(&ob->mesh->transform_applied, sizeof(bool));
@ -278,34 +276,33 @@ void BVH::pack_curve_seg(int idx, float4 woop[3])
int tob = pack.prim_object[idx];
const Mesh *mesh = objects[tob]->mesh;
int tidx = pack.prim_index[idx];
float3 v0 = mesh->curve_keys[mesh->curve_segs[tidx].v[0]].loc;
float3 v1 = mesh->curve_keys[mesh->curve_segs[tidx].v[1]].loc;
float t0 = mesh->curve_keys[mesh->curve_segs[tidx].v[0]].time;
float t1 = mesh->curve_keys[mesh->curve_segs[tidx].v[1]].time;
float3 v0 = mesh->curve_keys[mesh->curve_segments[tidx].v[0]].co;
float3 v1 = mesh->curve_keys[mesh->curve_segments[tidx].v[1]].co;
float3 d0 = v1 - v0;
float l = len(d0);
float u = mesh->curve_attrib[mesh->curve_segs[tidx].curve].uv[0];
float v = mesh->curve_attrib[mesh->curve_segs[tidx].curve].uv[1];
/*Plan
*Transform tfm = make_transform(
* location <3> , l,
* extra curve data <3> , StrID,
* nextkey, flags/tip?, r, t);
* nextkey, flags/tip?, 0, 0);
*/
float3 tg1 = make_float3(1.0f,0.0f,0.0f);
float3 tg2 = make_float3(1.0f,0.0f,0.0f);
if(mesh->curve_keysCD.size()) {
tg1 = mesh->curve_keysCD[mesh->curve_segs[tidx].v[0]].tg;
tg2 = mesh->curve_keysCD[mesh->curve_segs[tidx].v[1]].tg;
Attribute *attr_tangent = mesh->curve_attributes.find(ATTR_STD_CURVE_TANGENT);
float3 tg1 = make_float3(1.0f, 0.0f, 0.0f);
float3 tg2 = make_float3(1.0f, 0.0f, 0.0f);
if(attr_tangent) {
const float3 *data_tangent = attr_tangent->data_float3();
tg1 = data_tangent[mesh->curve_segments[tidx].v[0]];
tg2 = data_tangent[mesh->curve_segments[tidx].v[1]];
}
Transform tfm = make_transform(
tg1.x, tg1.y, tg1.z, l,
tg2.x, tg2.y, tg2.z, 0,
t0, t1, u, v,
0, 0, 0, 0,
0, 0, 0, 1);
woop[0] = tfm.x;
@ -628,10 +625,10 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility
if(pack.prim_type[prim]) {
/* strands */
int str_offset = (params.top_level)? mesh->curveseg_offset: 0;
const int *hidx = mesh->curve_segs[pidx - str_offset].v;
const int *hidx = mesh->curve_segments[pidx - str_offset].v;
bbox.grow(mesh->curve_keys[hidx[0]].loc, mesh->curve_keys[hidx[0]].radius);
bbox.grow(mesh->curve_keys[hidx[1]].loc, mesh->curve_keys[hidx[1]].radius);
bbox.grow(mesh->curve_keys[hidx[0]].co, mesh->curve_keys[hidx[0]].radius);
bbox.grow(mesh->curve_keys[hidx[1]].co, mesh->curve_keys[hidx[1]].radius);
}
else {
/* triangles */

@ -85,12 +85,12 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh,
}
}
for(uint j = 0; j < mesh->curve_segs.size(); j++) {
Mesh::CurveSeg s = mesh->curve_segs[j];
for(uint j = 0; j < mesh->curve_segments.size(); j++) {
Mesh::CurveSegment s = mesh->curve_segments[j];
BoundBox bounds = BoundBox::empty;
for(int k = 0; k < 2; k++) {
float3 pt = mesh->curve_keys[s.v[k]].loc;
float3 pt = mesh->curve_keys[s.v[k]].co;
bounds.grow(pt, mesh->curve_keys[s.v[k]].radius);
}
@ -118,14 +118,14 @@ void BVHBuild::add_references(BVHRange& root)
if(params.top_level) {
if(ob->mesh->transform_applied) {
num_alloc_references += ob->mesh->triangles.size();
num_alloc_references += ob->mesh->curve_segs.size();
num_alloc_references += ob->mesh->curve_segments.size();
}
else
num_alloc_references++;
}
else {
num_alloc_references += ob->mesh->triangles.size();
num_alloc_references += ob->mesh->curve_segs.size();
num_alloc_references += ob->mesh->curve_segments.size();
}
}

@ -283,9 +283,9 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH
else {
/* Strand split: NOTE - Currently ignores strand width and needs to be fixed.*/
const int *inds = mesh->curve_segs[ref.prim_index()].v;
const float3* v0 = &mesh->curve_keys[inds[0]].loc;
const float3* v1 = &mesh->curve_keys[inds[1]].loc;
const int *inds = mesh->curve_segments[ref.prim_index()].v;
const float3* v0 = &mesh->curve_keys[inds[0]].co;
const float3* v1 = &mesh->curve_keys[inds[1]].co;
float v0p = (*v0)[dim];
float v1p = (*v1)[dim];

@ -20,12 +20,12 @@ set(SRC
set(SRC_HEADERS
kernel.h
kernel_accumulate.h
kernel_attribute.h
kernel_bvh.h
kernel_camera.h
kernel_compat_cpu.h
kernel_compat_cuda.h
kernel_compat_opencl.h
kernel_curve.h
kernel_differential.h
kernel_displace.h
kernel_emission.h
@ -37,6 +37,7 @@ set(SRC_HEADERS
kernel_object.h
kernel_passes.h
kernel_path.h
kernel_primitive.h
kernel_projection.h
kernel_random.h
kernel_shader.h

@ -1,50 +0,0 @@
/*
* 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 __KERNEL_ATTRIBUTE_CL__
#define __KERNEL_ATTRIBUTE_CL__
CCL_NAMESPACE_BEGIN
/* note: declared in kernel.h, have to add it here because kernel.h is not available */
bool kernel_osl_use(KernelGlobals *kg);
__device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id)
{
#ifdef __OSL__
if (kg->osl) {
return OSLShader::find_attribute(kg, sd, id);
}
else
#endif
{
/* for SVM, find attribute by unique id */
uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
while(attr_map.x != id)
attr_map = kernel_tex_fetch(__attributes_map, ++attr_offset);
/* return result */
return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z;
}
}
CCL_NAMESPACE_END
#endif /* __KERNEL_ATTRIBUTE_CL__ */

@ -214,13 +214,13 @@ __device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect,
int flags = kernel_data.curve_kernel_data.curveflags;
int prim = kernel_tex_fetch(__prim_index, triAddr);
float4 v00 = kernel_tex_fetch(__cur_segs, prim);
float4 v00 = kernel_tex_fetch(__curve_segments, prim);
int v1 = __float_as_int(v00.x);
int v2 = __float_as_int(v00.y);
float4 P1 = kernel_tex_fetch(__cur_keys, v1);
float4 P2 = kernel_tex_fetch(__cur_keys, v2);
float4 P1 = kernel_tex_fetch(__curve_keys, v1);
float4 P2 = kernel_tex_fetch(__curve_keys, v2);
float l = v00.w;
float r1 = P1.w;
@ -720,13 +720,13 @@ __device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, const
}
int prim = kernel_tex_fetch(__prim_index, isect->prim);
float4 v00 = kernel_tex_fetch(__cur_segs, prim);
float4 v00 = kernel_tex_fetch(__curve_segments, prim);
int v1 = __float_as_int(v00.x);
int v2 = __float_as_int(v00.y);
float4 P1 = kernel_tex_fetch(__cur_keys, v1);
float4 P2 = kernel_tex_fetch(__cur_keys, v2);
float4 P1 = kernel_tex_fetch(__curve_keys, v1);
float4 P2 = kernel_tex_fetch(__curve_keys, v2);
float l = v00.w;
float r1 = P1.w;
float r2 = P2.w;

@ -0,0 +1,140 @@
/*
* 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.
*/
CCL_NAMESPACE_BEGIN
#ifdef __HAIR__
/* curve attributes */
__device float curve_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
{
if(elem == ATTR_ELEMENT_CURVE_SEGMENT) {
#ifdef __RAY_DIFFERENTIALS__
if(dx) *dx = 0.0f;
if(dy) *dy = 0.0f;
#endif
return kernel_tex_fetch(__attributes_float, offset + sd->curve_seg);
}
else if(elem == ATTR_ELEMENT_CURVE_KEY) {
float4 segment = kernel_tex_fetch(__curve_segments, sd->curve_seg);
float f0 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(segment.x));
float f1 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(segment.y));
#ifdef __RAY_DIFFERENTIALS__
if(dx) *dx = sd->du.dx*(f1 - f0);
if(dy) *dy = 0.0f;
#endif
return (1.0f - sd->u)*f0 + sd->u*f1;
}
else {
#ifdef __RAY_DIFFERENTIALS__
if(dx) *dx = 0.0f;
if(dy) *dy = 0.0f;
#endif
return 0.0f;
}
}
__device float3 curve_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
{
if(elem == ATTR_ELEMENT_CURVE_SEGMENT) {
/* idea: we can't derive any useful differentials here, but for tiled
* mipmap image caching it would be useful to avoid reading the highest
* detail level always. maybe a derivative based on the hair density
* could be computed somehow? */
#ifdef __RAY_DIFFERENTIALS__
if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
#endif
return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + sd->curve_seg));
}
else if(elem == ATTR_ELEMENT_CURVE_KEY) {
float4 segment = kernel_tex_fetch(__curve_segments, sd->curve_seg);
float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(segment.x)));
float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(segment.y)));
#ifdef __RAY_DIFFERENTIALS__
if(dx) *dx = sd->du.dx*(f1 - f0);
if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
#endif
return (1.0f - sd->u)*f0 + sd->u*f1;
}
else {
#ifdef __RAY_DIFFERENTIALS__
if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
#endif
return make_float3(0.0f, 0.0f, 0.0f);
}
}
/* hair info node functions */
__device float curve_thickness(KernelGlobals *kg, ShaderData *sd)
{
int prim = sd->curve_seg;
float u = sd->u;
float r = 0.0f;
if(prim != -1) {
float4 v00 = kernel_tex_fetch(__curve_segments, prim);
int v1 = __float_as_int(v00.x);
int v2 = __float_as_int(v00.y);
float4 P1 = kernel_tex_fetch(__curve_keys, v1);
float4 P2 = kernel_tex_fetch(__curve_keys, v2);
r = (P2.w - P1.w) * u + P1.w;
}
return r*2.0f;
}
__device float3 curve_tangent_normal(KernelGlobals *kg, ShaderData *sd)
{
float3 tgN = make_float3(0.0f,0.0f,0.0f);
if(sd->curve_seg != ~0) {
float normalmix = kernel_data.curve_kernel_data.normalmix;
tgN = -(-sd->I - sd->dPdu * (dot(sd->dPdu,-sd->I) * normalmix / len_squared(sd->dPdu)));
tgN = normalize(tgN);
/* need to find suitable scaled gd for corrected normal */
#if 0
if (kernel_data.curve_kernel_data.use_tangent_normal_correction)
tgN = normalize(tgN - gd * sd->dPdu);
#endif
}
return tgN;
}
#endif
CCL_NAMESPACE_END

@ -333,14 +333,14 @@ __device void curve_seg_light_sample(KernelGlobals *kg, int prim, int object,
float randu, float randv, float time, LightSample *ls)
{
/* this strand code needs completion */
float4 v00 = kernel_tex_fetch(__cur_segs, prim);
float4 v00 = kernel_tex_fetch(__curve_segments, prim);
int v1 = __float_as_int(v00.x);
int v2 = __float_as_int(v00.y);
float l = v00.w;
float4 P1 = kernel_tex_fetch(__cur_keys, v1);
float4 P2 = kernel_tex_fetch(__cur_keys, v2);
float4 P1 = kernel_tex_fetch(__curve_keys, v1);
float4 P2 = kernel_tex_fetch(__curve_keys, v2);
float r1 = P1.w;
float r2 = P2.w;
float3 tg = float4_to_float3(P2 - P1) / l;

@ -288,55 +288,5 @@ __device float3 particle_angular_velocity(KernelGlobals *kg, int particle)
return make_float3(f3.z, f3.w, f4.x);
}
#ifdef __HAIR__
/* Hair Info Node fns */
__device float hair_radius(KernelGlobals *kg, int prim, float u)
{
float r = 0.0f;
if (prim != -1) {
float4 v00 = kernel_tex_fetch(__cur_segs, prim);
int v1 = __float_as_int(v00.x);
int v2 = __float_as_int(v00.y);
float4 P1 = kernel_tex_fetch(__cur_keys, v1);
float4 P2 = kernel_tex_fetch(__cur_keys, v2);
r = (P2.w - P1.w) * u + P1.w;
}
return r;
}
__device float3 hair_tangent_normal(KernelGlobals *kg, ShaderData *sd)
{
float3 tgN = make_float3(0.0f,0.0f,0.0f);
if (sd->curve_seg != ~0) {
tgN = -(-sd->I - sd->dPdu * (dot(sd->dPdu,-sd->I) * kernel_data.curve_kernel_data.normalmix / len_squared(sd->dPdu)));
tgN = normalize(tgN);
/*if (kernel_data.curve_kernel_data.use_tangent_normal_correction) need to find suitable scaled gd for corrected normal
{
tgN = normalize(tgN - gd * sd->dPdu);
}*/
}
return tgN;
}
__device float intercept(KernelGlobals *kg, int prim, int triAddr, float u)
{
float t = 0.0f;
if (prim != -1) {
float4 sd2 = kernel_tex_fetch(__tri_woop, triAddr*3+2);
t = (sd2.y - sd2.x) * u + sd2.x;
}
return t;
}
#endif
CCL_NAMESPACE_END

@ -70,11 +70,11 @@ __device_inline void kernel_write_data_passes(KernelGlobals *kg, __global float
kernel_write_pass_float3(buffer + kernel_data.film.pass_normal, sample, normal);
}
if(flag & PASS_UV) {
float3 uv = triangle_uv(kg, sd);
float3 uv = primitive_uv(kg, sd);
kernel_write_pass_float3(buffer + kernel_data.film.pass_uv, sample, uv);
}
if(flag & PASS_MOTION) {
float4 speed = triangle_motion_vector(kg, sd);
float4 speed = primitive_motion_vector(kg, sd);
kernel_write_pass_float4(buffer + kernel_data.film.pass_motion, sample, speed);
kernel_write_pass_float(buffer + kernel_data.film.pass_motion_weight, sample, 1.0f);
}

@ -24,9 +24,10 @@
#include "kernel_montecarlo.h"
#include "kernel_projection.h"
#include "kernel_object.h"
#include "kernel_attribute.h"
#include "kernel_projection.h"
#include "kernel_triangle.h"
#include "kernel_curve.h"
#include "kernel_primitive.h"
#include "kernel_projection.h"
#ifdef __QBVH__
#include "kernel_qbvh.h"
#else

@ -0,0 +1,183 @@
/*
* 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 __KERNEL_ATTRIBUTE_CL__
#define __KERNEL_ATTRIBUTE_CL__
CCL_NAMESPACE_BEGIN
/* attribute lookup */
__device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id, AttributeElement *elem)
{
if(sd->object == ~0)
return (int)ATTR_STD_NOT_FOUND;
#ifdef __OSL__
if (kg->osl) {
return OSLShader::find_attribute(kg, sd, id, elem);
}
else
#endif
{
/* for SVM, find attribute by unique id */
uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
attr_offset = (sd->curve_seg == ~0)? attr_offset: attr_offset + ATTR_PRIM_CURVE;
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
while(attr_map.x != id) {
attr_offset += ATTR_PRIM_TYPES;
attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
}
*elem = (AttributeElement)attr_map.y;
/* return result */
return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z;
}
}
__device float primitive_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
{
#ifdef __HAIR__
if(sd->curve_seg == ~0)
#endif
return triangle_attribute_float(kg, sd, elem, offset, dx, dy);
#ifdef __HAIR__
else
return curve_attribute_float(kg, sd, elem, offset, dx, dy);
#endif
}
__device float3 primitive_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
{
#ifdef __HAIR__
if(sd->curve_seg == ~0)
#endif
return triangle_attribute_float3(kg, sd, elem, offset, dx, dy);
#ifdef __HAIR__
else
return curve_attribute_float3(kg, sd, elem, offset, dx, dy);
#endif
}
__device float3 primitive_uv(KernelGlobals *kg, ShaderData *sd)
{
AttributeElement elem_uv;
int offset_uv = find_attribute(kg, sd, ATTR_STD_UV, &elem_uv);
if(offset_uv == ATTR_STD_NOT_FOUND)
return make_float3(0.0f, 0.0f, 0.0f);
float3 uv = primitive_attribute_float3(kg, sd, elem_uv, offset_uv, NULL, NULL);
uv.z = 1.0f;
return uv;
}
__device float3 primitive_tangent(KernelGlobals *kg, ShaderData *sd)
{
#ifdef __HAIR__
if(sd->curve_seg != ~0)
return normalize(sd->dPdu);
#endif
/* try to create spherical tangent from generated coordinates */
AttributeElement attr_elem;
int attr_offset = find_attribute(kg, sd, ATTR_STD_GENERATED, &attr_elem);
if(attr_offset != ATTR_STD_NOT_FOUND) {
float3 data = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL);
data = make_float3(-(data.y - 0.5f), (data.x - 0.5f), 0.0f);
object_normal_transform(kg, sd, &data);
return cross(sd->N, normalize(cross(data, sd->N)));;
}
else {
/* otherwise use surface derivatives */
return normalize(sd->dPdu);
}
}
/* motion */
__device float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *sd)
{
float3 motion_pre = sd->P, motion_post = sd->P;
/* deformation motion */
AttributeElement elem_pre, elem_post;
int offset_pre = find_attribute(kg, sd, ATTR_STD_MOTION_PRE, &elem_pre);
int offset_post = find_attribute(kg, sd, ATTR_STD_MOTION_POST, &elem_post);
if(offset_pre != ATTR_STD_NOT_FOUND)
motion_pre = primitive_attribute_float3(kg, sd, elem_pre, offset_pre, NULL, NULL);
if(offset_post != ATTR_STD_NOT_FOUND)
motion_post = primitive_attribute_float3(kg, sd, elem_post, offset_post, NULL, NULL);
/* object motion. note that depending on the mesh having motion vectors, this
* transformation was set match the world/object space of motion_pre/post */
Transform tfm;
tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_PRE);
motion_pre = transform_point(&tfm, motion_pre);
tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_POST);
motion_post = transform_point(&tfm, motion_post);
float3 P;
/* camera motion, for perspective/orthographic motion.pre/post will be a
* world-to-raster matrix, for panorama it's world-to-camera */
if (kernel_data.cam.type != CAMERA_PANORAMA) {
tfm = kernel_data.cam.worldtoraster;
P = transform_perspective(&tfm, sd->P);
tfm = kernel_data.cam.motion.pre;
motion_pre = transform_perspective(&tfm, motion_pre);
tfm = kernel_data.cam.motion.post;
motion_post = transform_perspective(&tfm, motion_post);
}
else {
tfm = kernel_data.cam.worldtocamera;
P = normalize(transform_point(&tfm, sd->P));
P = float2_to_float3(direction_to_panorama(kg, P));
P.x *= kernel_data.cam.width;
P.y *= kernel_data.cam.height;
tfm = kernel_data.cam.motion.pre;
motion_pre = normalize(transform_point(&tfm, motion_pre));
motion_pre = float2_to_float3(direction_to_panorama(kg, motion_pre));
motion_pre.x *= kernel_data.cam.width;
motion_pre.y *= kernel_data.cam.height;
tfm = kernel_data.cam.motion.post;
motion_post = normalize(transform_point(&tfm, motion_post));
motion_post = float2_to_float3(direction_to_panorama(kg, motion_post));
motion_post.x *= kernel_data.cam.width;
motion_post.y *= kernel_data.cam.height;
}
motion_pre = motion_pre - P;
motion_post = P - motion_post;
return make_float4(motion_pre.x, motion_pre.y, motion_post.x, motion_post.y);
}
CCL_NAMESPACE_END
#endif /* __KERNEL_ATTRIBUTE_CL__ */

@ -77,7 +77,7 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
#ifdef __HAIR__
if(kernel_tex_fetch(__prim_type, isect->prim)) {
/* Strand Shader setting*/
float4 CurSeg = kernel_tex_fetch(__cur_segs, sd->prim);
float4 CurSeg = kernel_tex_fetch(__curve_segments, sd->prim);
sd->shader = __float_as_int(CurSeg.z);
sd->curve_seg = sd->prim;
@ -788,7 +788,7 @@ __device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect)
#ifdef __HAIR__
}
else {
float4 str = kernel_tex_fetch(__cur_segs, prim);
float4 str = kernel_tex_fetch(__curve_segments, prim);
shader = __float_as_int(str.z);
}
#endif

@ -44,8 +44,8 @@ KERNEL_TEX(float4, texture_float4, __tri_vindex)
KERNEL_TEX(float4, texture_float4, __tri_verts)
/* curves */
KERNEL_TEX(float4, texture_float4, __cur_segs)
KERNEL_TEX(float4, texture_float4, __cur_keys)
KERNEL_TEX(float4, texture_float4, __curve_segments)
KERNEL_TEX(float4, texture_float4, __curve_keys)
/* attributes */
KERNEL_TEX(uint4, texture_uint4, __attributes_map)

@ -106,195 +106,88 @@ __device_inline void triangle_dPdudv(KernelGlobals *kg, float3 *dPdu, float3 *dP
__device float triangle_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
{
#ifdef __HAIR__
if(sd->curve_seg == ~0) {
if(elem == ATTR_ELEMENT_FACE) {
if(dx) *dx = 0.0f;
if(dy) *dy = 0.0f;
return kernel_tex_fetch(__attributes_float, offset + sd->prim);
}
else if(elem == ATTR_ELEMENT_VERTEX) {
float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim));
float f0 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.x));
float f1 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.y));
float f2 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.z));
#ifdef __RAY_DIFFERENTIALS__
if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
#endif
if(elem == ATTR_ELEMENT_FACE) {
if(dx) *dx = 0.0f;
if(dy) *dy = 0.0f;
return kernel_tex_fetch(__attributes_float, offset + sd->prim);
}
else if(elem == ATTR_ELEMENT_VERTEX) {
float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim));
return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
}
else if(elem == ATTR_ELEMENT_CORNER) {
int tri = offset + sd->prim*3;
float f0 = kernel_tex_fetch(__attributes_float, tri + 0);
float f1 = kernel_tex_fetch(__attributes_float, tri + 1);
float f2 = kernel_tex_fetch(__attributes_float, tri + 2);
float f0 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.x));
float f1 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.y));
float f2 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.z));
#ifdef __RAY_DIFFERENTIALS__
if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
#endif
#ifdef __RAY_DIFFERENTIALS__
if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
#endif
return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
}
else if(elem == ATTR_ELEMENT_CORNER) {
int tri = offset + sd->prim*3;
float f0 = kernel_tex_fetch(__attributes_float, tri + 0);
float f1 = kernel_tex_fetch(__attributes_float, tri + 1);
float f2 = kernel_tex_fetch(__attributes_float, tri + 2);
#ifdef __RAY_DIFFERENTIALS__
if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
#endif
return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
}
else {
if(dx) *dx = 0.0f;
if(dy) *dy = 0.0f;
return 0.0f;
}
#ifdef __HAIR__
return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
}
else {
if(dx) *dx = 0.0f;
if(dy) *dy = 0.0f;
return 0.0f;
}
#endif
}
__device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
{
#ifdef __HAIR__
if(sd->curve_seg == ~0) {
#endif
if(elem == ATTR_ELEMENT_FACE) {
if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
if(elem == ATTR_ELEMENT_FACE) {
if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + sd->prim));
}
else if(elem == ATTR_ELEMENT_VERTEX) {
float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim));
float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.x)));
float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.y)));
float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.z)));
#ifdef __RAY_DIFFERENTIALS__
if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
#endif
return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
}
else if(elem == ATTR_ELEMENT_CORNER) {
int tri = offset + sd->prim*3;
float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0));
float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1));
float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2));
#ifdef __RAY_DIFFERENTIALS__
if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
#endif
return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
}
else {
if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
return make_float3(0.0f, 0.0f, 0.0f);
}
#ifdef __HAIR__
return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + sd->prim));
}
else
{
return make_float3(0.0f, 0.0f, 0.0f);
else if(elem == ATTR_ELEMENT_VERTEX) {
float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim));
float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.x)));
float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.y)));
float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.z)));
#ifdef __RAY_DIFFERENTIALS__
if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
#endif
return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
}
#endif
}
else if(elem == ATTR_ELEMENT_CORNER) {
int tri = offset + sd->prim*3;
float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0));
float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1));
float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2));
/* motion */
__device float4 triangle_motion_vector(KernelGlobals *kg, ShaderData *sd)
{
float3 motion_pre = sd->P, motion_post = sd->P;
/* deformation motion */
int offset_pre = find_attribute(kg, sd, ATTR_STD_MOTION_PRE);
int offset_post = find_attribute(kg, sd, ATTR_STD_MOTION_POST);
#ifdef __HAIR__
if(sd->curve_seg == ~0) {
#endif
if(offset_pre != ATTR_STD_NOT_FOUND)
motion_pre = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, offset_pre, NULL, NULL);
if(offset_post != ATTR_STD_NOT_FOUND)
motion_post = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, offset_post, NULL, NULL);
#ifdef __HAIR__
}
#ifdef __RAY_DIFFERENTIALS__
if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
#endif
/* object motion. note that depending on the mesh having motion vectors, this
* transformation was set match the world/object space of motion_pre/post */
Transform tfm;
tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_PRE);
motion_pre = transform_point(&tfm, motion_pre);
tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_POST);
motion_post = transform_point(&tfm, motion_post);
float3 P;
/* camera motion, for perspective/orthographic motion.pre/post will be a
* world-to-raster matrix, for panorama it's world-to-camera */
if (kernel_data.cam.type != CAMERA_PANORAMA) {
tfm = kernel_data.cam.worldtoraster;
P = transform_perspective(&tfm, sd->P);
tfm = kernel_data.cam.motion.pre;
motion_pre = transform_perspective(&tfm, motion_pre);
tfm = kernel_data.cam.motion.post;
motion_post = transform_perspective(&tfm, motion_post);
return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
}
else {
tfm = kernel_data.cam.worldtocamera;
P = normalize(transform_point(&tfm, sd->P));
P = float2_to_float3(direction_to_panorama(kg, P));
P.x *= kernel_data.cam.width;
P.y *= kernel_data.cam.height;
if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
tfm = kernel_data.cam.motion.pre;
motion_pre = normalize(transform_point(&tfm, motion_pre));
motion_pre = float2_to_float3(direction_to_panorama(kg, motion_pre));
motion_pre.x *= kernel_data.cam.width;
motion_pre.y *= kernel_data.cam.height;
tfm = kernel_data.cam.motion.post;
motion_post = normalize(transform_point(&tfm, motion_post));
motion_post = float2_to_float3(direction_to_panorama(kg, motion_post));
motion_post.x *= kernel_data.cam.width;
motion_post.y *= kernel_data.cam.height;
return make_float3(0.0f, 0.0f, 0.0f);
}
motion_pre = motion_pre - P;
motion_post = P - motion_post;
return make_float4(motion_pre.x, motion_pre.y, motion_post.x, motion_post.y);
}
__device float3 triangle_uv(KernelGlobals *kg, ShaderData *sd)
{
int offset_uv = find_attribute(kg, sd, ATTR_STD_UV);
#ifdef __HAIR__
if(offset_uv == ATTR_STD_NOT_FOUND || sd->curve_seg != ~0)
return make_float3(0.0f, 0.0f, 0.0f);
#else
if(offset_uv == ATTR_STD_NOT_FOUND)
return make_float3(0.0f, 0.0f, 0.0f);
#endif
float3 uv = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, offset_uv, NULL, NULL);
uv.z = 1.0f;
return uv;
}
CCL_NAMESPACE_END

@ -348,14 +348,39 @@ typedef struct Intersection {
/* Attributes */
#define ATTR_PRIM_TYPES 2
#define ATTR_PRIM_CURVE 1
typedef enum AttributeElement {
ATTR_ELEMENT_NONE,
ATTR_ELEMENT_VALUE,
ATTR_ELEMENT_FACE,
ATTR_ELEMENT_VERTEX,
ATTR_ELEMENT_CORNER,
ATTR_ELEMENT_VALUE,
ATTR_ELEMENT_NONE
ATTR_ELEMENT_CURVE_SEGMENT,
ATTR_ELEMENT_CURVE_KEY
} AttributeElement;
typedef enum AttributeStandard {
ATTR_STD_NONE = 0,
ATTR_STD_VERTEX_NORMAL,
ATTR_STD_FACE_NORMAL,
ATTR_STD_UV,
ATTR_STD_UV_TANGENT,
ATTR_STD_UV_TANGENT_SIGN,
ATTR_STD_GENERATED,
ATTR_STD_POSITION_UNDEFORMED,
ATTR_STD_POSITION_UNDISPLACED,
ATTR_STD_MOTION_PRE,
ATTR_STD_MOTION_POST,
ATTR_STD_PARTICLE,
ATTR_STD_CURVE_TANGENT,
ATTR_STD_CURVE_INTERCEPT,
ATTR_STD_NUM,
ATTR_STD_NOT_FOUND = ~0
} AttributeStandard;
/* Closure data */
#define MAX_CLOSURE 8

@ -37,9 +37,10 @@
#include "kernel_differential.h"
#include "kernel_object.h"
#include "kernel_bvh.h"
#include "kernel_attribute.h"
#include "kernel_projection.h"
#include "kernel_triangle.h"
#include "kernel_curve.h"
#include "kernel_primitive.h"
#include "kernel_projection.h"
#include "kernel_accumulate.h"
#include "kernel_shader.h"
@ -75,10 +76,9 @@ ustring OSLRenderServices::u_geom_trianglevertices("geom:trianglevertices");
ustring OSLRenderServices::u_geom_polyvertices("geom:polyvertices");
ustring OSLRenderServices::u_geom_name("geom:name");
#ifdef __HAIR__
ustring OSLRenderServices::u_curve_is_strand("curve:is_strand");
ustring OSLRenderServices::u_curve_intercept("curve:intercept");
ustring OSLRenderServices::u_curve_thickness("curve:thickness");
ustring OSLRenderServices::u_curve_tangent_normal("curve:tangent_normal");
ustring OSLRenderServices::u_is_curve("geom:is_curve");
ustring OSLRenderServices::u_curve_thickness("geom:curve_thickness");
ustring OSLRenderServices::u_curve_tangent_normal("geom:curve_tangent_normal");
#endif
ustring OSLRenderServices::u_path_ray_length("path:ray_length");
ustring OSLRenderServices::u_trace("trace");
@ -501,14 +501,14 @@ static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd, const OS
attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor)
{
float3 fval[3];
fval[0] = triangle_attribute_float3(kg, sd, attr.elem, attr.offset,
(derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
fval[0] = primitive_attribute_float3(kg, sd, attr.elem, attr.offset,
(derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
return set_attribute_float3(fval, type, derivatives, val);
}
else if (attr.type == TypeDesc::TypeFloat) {
float fval[3];
fval[0] = triangle_attribute_float(kg, sd, attr.elem, attr.offset,
(derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
fval[0] = primitive_attribute_float(kg, sd, attr.elem, attr.offset,
(derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
return set_attribute_float(fval, type, derivatives, val);
}
else {
@ -604,7 +604,8 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD
else if (name == u_geom_numpolyvertices) {
return set_attribute_int(3, type, derivatives, val);
}
else if (name == u_geom_trianglevertices || name == u_geom_polyvertices) {
else if ((name == u_geom_trianglevertices || name == u_geom_polyvertices)
&& sd->curve_seg == ~0) {
float3 P[3];
triangle_vertices(kg, sd->prim, P);
@ -623,20 +624,16 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD
#ifdef __HAIR__
/* Hair Attributes */
else if (name == u_curve_is_strand) {
else if (name == u_is_curve) {
float f = !(sd->curve_seg == ~0);
return set_attribute_float(f, type, derivatives, val);
}
else if (name == u_curve_intercept) {
float f = intercept(kg, sd->curve_seg, sd->prim, sd->u);
return set_attribute_float(f, type, derivatives, val);
}
else if (name == u_curve_thickness) {
float f = 2 * hair_radius(kg, sd->curve_seg, sd->u);
float f = curve_thickness(kg, sd);
return set_attribute_float(f, type, derivatives, val);
}
else if (name == u_curve_tangent_normal) {
float3 f = hair_tangent_normal(kg, sd);
float3 f = curve_tangent_normal(kg, sd);
return set_attribute_float3(f, type, derivatives, val);
}
#endif
@ -662,7 +659,7 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri
{
KernelGlobals *kg = kernel_globals;
ShaderData *sd = (ShaderData *)renderstate;
int object, tri;
int object, prim, curve_seg;
/* lookup of attribute on another object */
if (object_name != u_empty || sd == NULL) {
@ -672,17 +669,20 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri
return false;
object = it->second;
tri = ~0;
prim = ~0;
curve_seg = ~0;
}
else {
object = sd->object;
tri = sd->prim;
prim = sd->prim;
curve_seg = sd->curve_seg;
if (object == ~0)
return get_background_attribute(kg, sd, name, type, derivatives, val);
}
/* find attribute on object */
object = object*ATTR_PRIM_TYPES + (curve_seg != ~0);
OSLGlobals::AttributeMap& attribute_map = kg->osl->attribute_map[object];
OSLGlobals::AttributeMap::iterator it = attribute_map.find(name);
@ -691,7 +691,7 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri
if (attr.elem != ATTR_ELEMENT_VALUE) {
/* triangle and vertex attributes */
if (tri != ~0)
if (prim != ~0)
return get_mesh_attribute(kg, sd, attr, type, derivatives, val);
}
else {

@ -130,8 +130,7 @@ public:
static ustring u_geom_trianglevertices;
static ustring u_geom_polyvertices;
static ustring u_geom_name;
static ustring u_curve_is_strand;
static ustring u_curve_intercept;
static ustring u_is_curve;
static ustring u_curve_thickness;
static ustring u_curve_tangent_normal;
static ustring u_path_ray_length;

@ -26,9 +26,10 @@
#include "osl_services.h"
#include "osl_shader.h"
#include "util_attribute.h"
#include "util_foreach.h"
#include "attribute.h"
#include <OSL/oslexec.h>
CCL_NAMESPACE_BEGIN
@ -453,15 +454,17 @@ float3 OSLShader::volume_eval_phase(const ShaderClosure *sc, const float3 omega_
/* Attributes */
int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id)
int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem)
{
/* for OSL, a hash map is used to lookup the attribute by name. */
OSLGlobals::AttributeMap &attr_map = kg->osl->attribute_map[sd->object];
ustring stdname(std::string("std::") + std::string(attribute_standard_name((AttributeStandard)id)));
int object = sd->object*ATTR_PRIM_TYPES + (sd->curve_seg != ~0);
OSLGlobals::AttributeMap &attr_map = kg->osl->attribute_map[object];
ustring stdname(std::string("geom:") + std::string(Attribute::standard_name((AttributeStandard)id)));
OSLGlobals::AttributeMap::const_iterator it = attr_map.find(stdname);
if (it != attr_map.end()) {
const OSLGlobals::Attribute &osl_attr = it->second;
*elem = osl_attr.elem;
/* return result */
return (osl_attr.elem == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : osl_attr.offset;
}

@ -74,7 +74,7 @@ public:
const float3 omega_in, const float3 omega_out);
/* attributes */
static int find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id);
static int find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem);
};
CCL_NAMESPACE_END

@ -24,9 +24,9 @@ shader node_hair_info(
output float Thickness = 0.0,
output normal TangentNormal = N)
{
getattribute("curve:is_strand", IsStrand);
getattribute("curve:intercept", Intercept);
getattribute("curve:thickness", Thickness);
getattribute("curve:tangent_normal", TangentNormal);
getattribute("geom:is_curve", IsStrand);
getattribute("geom:curve_intercept", Intercept);
getattribute("geom:curve_thickness", Thickness);
getattribute("geom:curve_tangent_normal", TangentNormal);
}

@ -28,10 +28,13 @@ __device void svm_node_attr_init(KernelGlobals *kg, ShaderData *sd,
/* find attribute by unique id */
uint id = node.y;
uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
attr_offset = (sd->curve_seg == ~0)? attr_offset: attr_offset + ATTR_PRIM_CURVE;
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
while(attr_map.x != id)
attr_map = kernel_tex_fetch(__attributes_map, ++attr_offset);
while(attr_map.x != id) {
attr_offset += ATTR_PRIM_TYPES;
attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
}
/* return result */
*elem = (AttributeElement)attr_map.y;
@ -58,45 +61,27 @@ __device void svm_node_attr(KernelGlobals *kg, ShaderData *sd, float *stack, uin
svm_node_attr_init(kg, sd, node, &type, &mesh_type, &elem, &offset, &out_offset);
#ifdef __HAIR__
if (sd->curve_seg != ~0) {
/*currently strand attributes aren't enabled - only exports stored uvs*/
if(type == NODE_ATTR_FLOAT)
stack_store_float(stack, out_offset, 0.0f);
else {
float4 sd2 = kernel_tex_fetch(__tri_woop, sd->prim*3+2);
float3 uv = make_float3(sd2.z,sd2.w,0.0f);
stack_store_float3(stack, out_offset, uv);
}
}
else
{
#endif
/* fetch and store attribute */
if(type == NODE_ATTR_FLOAT) {
if(mesh_type == NODE_ATTR_FLOAT) {
float f = triangle_attribute_float(kg, sd, elem, offset, NULL, NULL);
stack_store_float(stack, out_offset, f);
}
else {
float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, NULL);
stack_store_float(stack, out_offset, average(f));
}
/* fetch and store attribute */
if(type == NODE_ATTR_FLOAT) {
if(mesh_type == NODE_ATTR_FLOAT) {
float f = primitive_attribute_float(kg, sd, elem, offset, NULL, NULL);
stack_store_float(stack, out_offset, f);
}
else {
if(mesh_type == NODE_ATTR_FLOAT3) {
float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, NULL);
stack_store_float3(stack, out_offset, f);
}
else {
float f = triangle_attribute_float(kg, sd, elem, offset, NULL, NULL);
stack_store_float3(stack, out_offset, make_float3(f, f, f));
}
float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, NULL);
stack_store_float(stack, out_offset, average(f));
}
}
else {
if(mesh_type == NODE_ATTR_FLOAT3) {
float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, NULL);
stack_store_float3(stack, out_offset, f);
}
else {
float f = primitive_attribute_float(kg, sd, elem, offset, NULL, NULL);
stack_store_float3(stack, out_offset, make_float3(f, f, f));
}
#ifdef __HAIR__
}
#endif
}
__device void svm_node_attr_bump_dx(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
@ -109,43 +94,30 @@ __device void svm_node_attr_bump_dx(KernelGlobals *kg, ShaderData *sd, float *st
svm_node_attr_init(kg, sd, node, &type, &mesh_type, &elem, &offset, &out_offset);
/* fetch and store attribute */
#ifdef __HAIR__
if (sd->curve_seg != ~0) {
/*currently strand attributes aren't enabled*/
if(type == NODE_ATTR_FLOAT)
stack_store_float(stack, out_offset, 0.0f);
else
stack_store_float3(stack, out_offset, make_float3(0.0f, 0.0f, 0.0f));
}
else {
#endif
if(type == NODE_ATTR_FLOAT) {
if(mesh_type == NODE_ATTR_FLOAT) {
float dx;
float f = triangle_attribute_float(kg, sd, elem, offset, &dx, NULL);
stack_store_float(stack, out_offset, f+dx);
}
else {
float3 dx;
float3 f = triangle_attribute_float3(kg, sd, elem, offset, &dx, NULL);
stack_store_float(stack, out_offset, average(f+dx));
}
if(type == NODE_ATTR_FLOAT) {
if(mesh_type == NODE_ATTR_FLOAT) {
float dx;
float f = primitive_attribute_float(kg, sd, elem, offset, &dx, NULL);
stack_store_float(stack, out_offset, f+dx);
}
else {
if(mesh_type == NODE_ATTR_FLOAT3) {
float3 dx;
float3 f = triangle_attribute_float3(kg, sd, elem, offset, &dx, NULL);
stack_store_float3(stack, out_offset, f+dx);
}
else {
float dx;
float f = triangle_attribute_float(kg, sd, elem, offset, &dx, NULL);
stack_store_float3(stack, out_offset, make_float3(f+dx, f+dx, f+dx));
}
float3 dx;
float3 f = primitive_attribute_float3(kg, sd, elem, offset, &dx, NULL);
stack_store_float(stack, out_offset, average(f+dx));
}
}
else {
if(mesh_type == NODE_ATTR_FLOAT3) {
float3 dx;
float3 f = primitive_attribute_float3(kg, sd, elem, offset, &dx, NULL);
stack_store_float3(stack, out_offset, f+dx);
}
else {
float dx;
float f = primitive_attribute_float(kg, sd, elem, offset, &dx, NULL);
stack_store_float3(stack, out_offset, make_float3(f+dx, f+dx, f+dx));
}
#ifdef __HAIR__
}
#endif
}
__device void svm_node_attr_bump_dy(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
@ -158,43 +130,30 @@ __device void svm_node_attr_bump_dy(KernelGlobals *kg, ShaderData *sd, float *st
svm_node_attr_init(kg, sd, node, &type, &mesh_type, &elem, &offset, &out_offset);
/* fetch and store attribute */
#ifdef __HAIR__
if (sd->curve_seg != ~0) {
/*currently strand attributes aren't enabled*/
if(type == NODE_ATTR_FLOAT)
stack_store_float(stack, out_offset, 0.0f);
else
stack_store_float3(stack, out_offset, make_float3(0.0f, 0.0f, 0.0f));
}
else {
#endif
if(type == NODE_ATTR_FLOAT) {
if(mesh_type == NODE_ATTR_FLOAT) {
float dy;
float f = triangle_attribute_float(kg, sd, elem, offset, NULL, &dy);
stack_store_float(stack, out_offset, f+dy);
}
else {
float3 dy;
float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, &dy);
stack_store_float(stack, out_offset, average(f+dy));
}
if(type == NODE_ATTR_FLOAT) {
if(mesh_type == NODE_ATTR_FLOAT) {
float dy;
float f = primitive_attribute_float(kg, sd, elem, offset, NULL, &dy);
stack_store_float(stack, out_offset, f+dy);
}
else {
if(mesh_type == NODE_ATTR_FLOAT3) {
float3 dy;
float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, &dy);
stack_store_float3(stack, out_offset, f+dy);
}
else {
float dy;
float f = triangle_attribute_float(kg, sd, elem, offset, NULL, &dy);
stack_store_float3(stack, out_offset, make_float3(f+dy, f+dy, f+dy));
}
float3 dy;
float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, &dy);
stack_store_float(stack, out_offset, average(f+dy));
}
}
else {
if(mesh_type == NODE_ATTR_FLOAT3) {
float3 dy;
float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, &dy);
stack_store_float3(stack, out_offset, f+dy);
}
else {
float dy;
float f = primitive_attribute_float(kg, sd, elem, offset, NULL, &dy);
stack_store_float3(stack, out_offset, make_float3(f+dy, f+dy, f+dy));
}
#ifdef __HAIR__
}
#endif
}
CCL_NAMESPACE_END

@ -28,26 +28,7 @@ __device void svm_node_geometry(KernelGlobals *kg, ShaderData *sd, float *stack,
case NODE_GEOM_P: data = sd->P; break;
case NODE_GEOM_N: data = sd->N; break;
#ifdef __DPDU__
case NODE_GEOM_T: {
/* try to create spherical tangent from generated coordinates */
int attr_offset = (sd->object != ~0)? find_attribute(kg, sd, ATTR_STD_GENERATED): ATTR_STD_NOT_FOUND;
#ifdef __HAIR__
if(attr_offset != ATTR_STD_NOT_FOUND && sd->curve_seg == ~0) {
#else
if(attr_offset != ATTR_STD_NOT_FOUND) {
#endif
data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL);
data = make_float3(-(data.y - 0.5f), (data.x - 0.5f), 0.0f);
object_normal_transform(kg, sd, &data);
data = cross(sd->N, normalize(cross(data, sd->N)));;
}
else {
/* otherwise use surface derivatives */
data = normalize(sd->dPdu);
}
break;
}
case NODE_GEOM_T: data = primitive_tangent(kg, sd); break;
#endif
case NODE_GEOM_I: data = sd->I; break;
case NODE_GEOM_Ng: data = sd->Ng; break;
@ -164,6 +145,7 @@ __device void svm_node_particle_info(KernelGlobals *kg, ShaderData *sd, float *s
}
#ifdef __HAIR__
/* Hair Info */
__device void svm_node_hair_info(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
@ -177,18 +159,15 @@ __device void svm_node_hair_info(KernelGlobals *kg, ShaderData *sd, float *stack
stack_store_float(stack, out_offset, data);
break;
}
case NODE_INFO_CURVE_INTERCEPT: {
data = intercept(kg, sd->curve_seg, sd->prim, sd->u);
stack_store_float(stack, out_offset, data);
break;
}
case NODE_INFO_CURVE_INTERCEPT:
break; /* handled as attribute */
case NODE_INFO_CURVE_THICKNESS: {
data = 2 * hair_radius(kg, sd->curve_seg, sd->u);
data = curve_thickness(kg, sd);
stack_store_float(stack, out_offset, data);
break;
}
case NODE_INFO_CURVE_TANGENT_NORMAL: {
data3 = hair_tangent_normal(kg, sd);
data3 = curve_tangent_normal(kg, sd);
stack_store_float3(stack, out_offset, data3);
break;
}

@ -242,18 +242,15 @@ __device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *stac
if(space == NODE_NORMAL_MAP_TANGENT) {
/* tangent space */
#ifdef __HAIR__
if(sd->object == ~0 || sd->curve_seg != ~0) {
#else
if(sd->object == ~0) {
#endif
if(sd->object == ~0) {
stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f));
return;
}
/* first try to get tangent attribute */
int attr_offset = find_attribute(kg, sd, node.z);
int attr_sign_offset = find_attribute(kg, sd, node.w);
AttributeElement attr_elem, attr_sign_elem;
int attr_offset = find_attribute(kg, sd, node.z, &attr_elem);
int attr_sign_offset = find_attribute(kg, sd, node.w, &attr_sign_elem);
if(attr_offset == ATTR_STD_NOT_FOUND || attr_sign_offset == ATTR_STD_NOT_FOUND) {
stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f));
@ -261,8 +258,8 @@ __device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *stac
}
/* ensure orthogonal and normalized (interpolation breaks it) */
float3 tangent = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, attr_offset, NULL, NULL);
float sign = triangle_attribute_float(kg, sd, ATTR_ELEMENT_CORNER, attr_sign_offset, NULL, NULL);
float3 tangent = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL);
float sign = primitive_attribute_float(kg, sd, attr_sign_elem, attr_sign_offset, NULL, NULL);
object_normal_transform(kg, sd, &tangent);
tangent = cross(sd->N, normalize(cross(tangent, sd->N)));;
@ -299,30 +296,24 @@ __device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack,
if(direction_type == NODE_TANGENT_UVMAP) {
/* UV map */
int attr_offset = find_attribute(kg, sd, node.z);
AttributeElement attr_elem;
int attr_offset = find_attribute(kg, sd, node.z, &attr_elem);
#ifdef __HAIR__
if(attr_offset == ATTR_STD_NOT_FOUND || sd->curve_seg != ~0)
#else
if(attr_offset == ATTR_STD_NOT_FOUND)
#endif
tangent = make_float3(0.0f, 0.0f, 0.0f);
else
tangent = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, attr_offset, NULL, NULL);
tangent = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL);
}
else {
/* radial */
int attr_offset = find_attribute(kg, sd, node.z);
AttributeElement attr_elem;
int attr_offset = find_attribute(kg, sd, node.z, &attr_elem);
float3 generated;
#ifdef __HAIR__
if(attr_offset == ATTR_STD_NOT_FOUND || sd->curve_seg != ~0)
#else
if(attr_offset == ATTR_STD_NOT_FOUND)
#endif
generated = sd->P;
else
generated = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL);
generated = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL);
if(axis == NODE_TANGENT_AXIS_X)
tangent = make_float3(0.0f, -(generated.z - 0.5f), (generated.y - 0.5f));

@ -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);
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);
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 */

@ -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);

@ -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;

@ -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;

@ -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.triangle_element != ATTR_ELEMENT_NONE) {
osl_attr.elem = req.triangle_element;
osl_attr.offset = req.triangle_offset;
if(req.type == TypeDesc::TypeFloat)
osl_attr.type = TypeDesc::TypeFloat;
else
osl_attr.type = TypeDesc::TypeColor;
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][stdname] = osl_attr;
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);
Attribute *triangle_mattr = mesh->attributes.find(req);
Attribute *curve_mattr = mesh->curve_attributes.find(req);
/* todo: get rid of this exception */
if(!mattr && req.std == ATTR_STD_GENERATED) {
mattr = mesh->attributes.add(ATTR_STD_GENERATED);
/* 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();

@ -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();

@ -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");

@ -334,6 +334,8 @@ public:
class HairInfoNode : public ShaderNode {
public:
SHADER_NODE_CLASS(HairInfoNode)
void attributes(AttributeRequestSet *attributes);
};
class ValueNode : public ShaderNode {

@ -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*/

@ -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;

@ -47,7 +47,7 @@ void EdgeDice::reserve(int num_verts, int num_tris)
vert_offset = mesh->verts.size();
tri_offset = mesh->triangles.size();
mesh->reserve(vert_offset + num_verts, tri_offset + num_tris);
mesh->reserve(vert_offset + num_verts, tri_offset + num_tris, 0, 0);
Attribute *attr_vN = mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);

@ -9,7 +9,6 @@ set(INC_SYS
)
set(SRC
util_attribute.cpp
util_cache.cpp
util_cuda.cpp
util_dynlib.cpp
@ -33,7 +32,6 @@ endif()
set(SRC_HEADERS
util_algorithm.h
util_args.h
util_attribute.h
util_boundbox.h
util_cache.h
util_cuda.h

@ -1,51 +0,0 @@
/*
* 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 "util_attribute.h"
CCL_NAMESPACE_BEGIN
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";
return "";
}
CCL_NAMESPACE_END

@ -1,31 +0,0 @@
/*
* 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 __UTIL_ATTRIBUTE_H__
#define __UTIL_ATTRIBUTE_H__
#include "util_types.h"
CCL_NAMESPACE_BEGIN
const char *attribute_standard_name(AttributeStandard std);
CCL_NAMESPACE_END
#endif /* __UTIL_ATTRIBUTE_H__ */

@ -448,24 +448,6 @@ __device_inline int4 make_int4(const float3& f)
#endif
typedef enum AttributeStandard {
ATTR_STD_NONE = 0,
ATTR_STD_VERTEX_NORMAL,
ATTR_STD_FACE_NORMAL,
ATTR_STD_UV,
ATTR_STD_UV_TANGENT,
ATTR_STD_UV_TANGENT_SIGN,
ATTR_STD_GENERATED,
ATTR_STD_POSITION_UNDEFORMED,
ATTR_STD_POSITION_UNDISPLACED,
ATTR_STD_MOTION_PRE,
ATTR_STD_MOTION_POST,
ATTR_STD_PARTICLE,
ATTR_STD_NUM,
ATTR_STD_NOT_FOUND = ~0
} AttributeStandard;
CCL_NAMESPACE_END
#endif /* __UTIL_TYPES_H__ */