diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp index 68b5d18a093..61628aae535 100644 --- a/intern/cycles/blender/blender_curves.cpp +++ b/intern/cycles/blender/blender_curves.cpp @@ -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(); - } diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index a01b2e9ee38..86f996320cb 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -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(); diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp index 102414e4a3d..0b43704b7b8 100644 --- a/intern/cycles/bvh/bvh.cpp +++ b/intern/cycles/bvh/bvh.cpp @@ -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 */ diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp index cdd94324f53..665c783b2d8 100644 --- a/intern/cycles/bvh/bvh_build.cpp +++ b/intern/cycles/bvh/bvh_build.cpp @@ -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(); } } diff --git a/intern/cycles/bvh/bvh_split.cpp b/intern/cycles/bvh/bvh_split.cpp index 860e2c8d7df..67fdfd77657 100644 --- a/intern/cycles/bvh/bvh_split.cpp +++ b/intern/cycles/bvh/bvh_split.cpp @@ -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]; diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index fde881c0a06..6d5b9a063a0 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -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 diff --git a/intern/cycles/kernel/kernel_attribute.h b/intern/cycles/kernel/kernel_attribute.h deleted file mode 100644 index b7ad731c883..00000000000 --- a/intern/cycles/kernel/kernel_attribute.h +++ /dev/null @@ -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__ */ diff --git a/intern/cycles/kernel/kernel_bvh.h b/intern/cycles/kernel/kernel_bvh.h index 15af35a05f8..d32287f91e8 100644 --- a/intern/cycles/kernel/kernel_bvh.h +++ b/intern/cycles/kernel/kernel_bvh.h @@ -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; diff --git a/intern/cycles/kernel/kernel_curve.h b/intern/cycles/kernel/kernel_curve.h new file mode 100644 index 00000000000..fef1a48644d --- /dev/null +++ b/intern/cycles/kernel/kernel_curve.h @@ -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 + diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index 0f74ab75dd4..09ee1f68e12 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -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; diff --git a/intern/cycles/kernel/kernel_object.h b/intern/cycles/kernel/kernel_object.h index 2260094aa70..40aa4753daa 100644 --- a/intern/cycles/kernel/kernel_object.h +++ b/intern/cycles/kernel/kernel_object.h @@ -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 diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h index 7f8b611ba14..727639386ed 100644 --- a/intern/cycles/kernel/kernel_passes.h +++ b/intern/cycles/kernel/kernel_passes.h @@ -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); } diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 8da21751cbe..20feaf50a2e 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -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 diff --git a/intern/cycles/kernel/kernel_primitive.h b/intern/cycles/kernel/kernel_primitive.h new file mode 100644 index 00000000000..2296017c686 --- /dev/null +++ b/intern/cycles/kernel/kernel_primitive.h @@ -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__ */ diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index 652efa18b93..49bbc5a74ab 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -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 diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h index 0b6107b398e..072df21a188 100644 --- a/intern/cycles/kernel/kernel_textures.h +++ b/intern/cycles/kernel/kernel_textures.h @@ -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) diff --git a/intern/cycles/kernel/kernel_triangle.h b/intern/cycles/kernel/kernel_triangle.h index 1f2618d3507..d346137760f 100644 --- a/intern/cycles/kernel/kernel_triangle.h +++ b/intern/cycles/kernel/kernel_triangle.h @@ -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 diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index d051006f165..e80772bd4e2 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -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 diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index 64c4d109452..afa5211216b 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -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 { diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h index 9b7c9a423ff..50c50b9952c 100644 --- a/intern/cycles/kernel/osl/osl_services.h +++ b/intern/cycles/kernel/osl/osl_services.h @@ -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; diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index 3ff032374fc..18486eba114 100644 --- a/intern/cycles/kernel/osl/osl_shader.cpp +++ b/intern/cycles/kernel/osl/osl_shader.cpp @@ -26,9 +26,10 @@ #include "osl_services.h" #include "osl_shader.h" -#include "util_attribute.h" #include "util_foreach.h" +#include "attribute.h" + #include 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; } diff --git a/intern/cycles/kernel/osl/osl_shader.h b/intern/cycles/kernel/osl/osl_shader.h index 2e46a2de42c..2062c651162 100644 --- a/intern/cycles/kernel/osl/osl_shader.h +++ b/intern/cycles/kernel/osl/osl_shader.h @@ -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 diff --git a/intern/cycles/kernel/shaders/node_hair_info.osl b/intern/cycles/kernel/shaders/node_hair_info.osl index a44fc67f4bc..cbb3b98383f 100644 --- a/intern/cycles/kernel/shaders/node_hair_info.osl +++ b/intern/cycles/kernel/shaders/node_hair_info.osl @@ -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); } diff --git a/intern/cycles/kernel/svm/svm_attribute.h b/intern/cycles/kernel/svm/svm_attribute.h index 4f9dc4af007..f11b69138d1 100644 --- a/intern/cycles/kernel/svm/svm_attribute.h +++ b/intern/cycles/kernel/svm/svm_attribute.h @@ -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 diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h index e1b898e9b14..db8bbabe0ec 100644 --- a/intern/cycles/kernel/svm/svm_geometry.h +++ b/intern/cycles/kernel/svm/svm_geometry.h @@ -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; } diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h index 5e7c92ba93c..7a1af43b625 100644 --- a/intern/cycles/kernel/svm/svm_tex_coord.h +++ b/intern/cycles/kernel/svm/svm_tex_coord.h @@ -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)); diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index 95941c14b6c..758e4e5e820 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -26,7 +26,7 @@ CCL_NAMESPACE_BEGIN /* Attribute */ -void Attribute::set(ustring name_, TypeDesc type_, Element element_) +void Attribute::set(ustring name_, TypeDesc type_, AttributeElement element_) { name = name_; type = type_; @@ -39,12 +39,30 @@ void Attribute::set(ustring name_, TypeDesc type_, Element element_) type == TypeDesc::TypeNormal); } -void Attribute::reserve(int numverts, int numtris) +void Attribute::reserve(int numverts, int numtris, int numcurves, int numkeys) { - buffer.resize(buffer_size(numverts, numtris), 0); + buffer.resize(buffer_size(numverts, numtris, numcurves, numkeys), 0); } -size_t Attribute::data_sizeof() +void Attribute::add(const float& f) +{ + char *data = (char*)&f; + size_t size = sizeof(f); + + for(size_t i = 0; i < size; i++) + buffer.push_back(data[i]); +} + +void Attribute::add(const float3& f) +{ + char *data = (char*)&f; + size_t size = sizeof(f); + + for(size_t i = 0; i < size; i++) + buffer.push_back(data[i]); +} + +size_t Attribute::data_sizeof() const { if(type == TypeDesc::TypeFloat) return sizeof(float); @@ -52,19 +70,27 @@ size_t Attribute::data_sizeof() return sizeof(float3); } -size_t Attribute::element_size(int numverts, int numtris) +size_t Attribute::element_size(int numverts, int numtris, int numcurves, int numkeys) const { - if(element == VERTEX) + if(element == ATTR_ELEMENT_VALUE) + return 1; + if(element == ATTR_ELEMENT_VERTEX) return numverts; - else if(element == FACE) + else if(element == ATTR_ELEMENT_FACE) return numtris; - else + else if(element == ATTR_ELEMENT_CORNER) return numtris*3; + else if(element == ATTR_ELEMENT_CURVE_SEGMENT) + return numcurves; + else if(element == ATTR_ELEMENT_CURVE_KEY) + return numkeys; + + return 0; } -size_t Attribute::buffer_size(int numverts, int numtris) +size_t Attribute::buffer_size(int numverts, int numtris, int numcurves, int numkeys) const { - return element_size(numverts, numtris)*data_sizeof(); + return element_size(numverts, numtris, numcurves, numkeys)*data_sizeof(); } bool Attribute::same_storage(TypeDesc a, TypeDesc b) @@ -84,18 +110,51 @@ bool Attribute::same_storage(TypeDesc a, TypeDesc b) return false; } +const char *Attribute::standard_name(AttributeStandard std) +{ + if(std == ATTR_STD_VERTEX_NORMAL) + return "N"; + else if(std == ATTR_STD_FACE_NORMAL) + return "Ng"; + else if(std == ATTR_STD_UV) + return "uv"; + else if(std == ATTR_STD_GENERATED) + return "generated"; + else if(std == ATTR_STD_UV_TANGENT) + return "tangent"; + else if(std == ATTR_STD_UV_TANGENT_SIGN) + return "tangent_sign"; + else if(std == ATTR_STD_POSITION_UNDEFORMED) + return "undeformed"; + else if(std == ATTR_STD_POSITION_UNDISPLACED) + return "undisplaced"; + else if(std == ATTR_STD_MOTION_PRE) + return "motion_pre"; + else if(std == ATTR_STD_MOTION_POST) + return "motion_post"; + else if(std == ATTR_STD_PARTICLE) + return "particle"; + else if(std == ATTR_STD_CURVE_TANGENT) + return "curve_tangent"; + else if(std == ATTR_STD_CURVE_INTERCEPT) + return "curve_intercept"; + + return ""; +} + /* Attribute Set */ AttributeSet::AttributeSet() { - mesh = NULL; + triangle_mesh = NULL; + curve_mesh = NULL; } AttributeSet::~AttributeSet() { } -Attribute *AttributeSet::add(ustring name, TypeDesc type, Attribute::Element element) +Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement element) { Attribute *attr = find(name); @@ -111,24 +170,22 @@ Attribute *AttributeSet::add(ustring name, TypeDesc type, Attribute::Element ele attributes.push_back(Attribute()); attr = &attributes.back(); - if(element == Attribute::VERTEX) - attr->set(name, type, element); - else if(element == Attribute::FACE) - attr->set(name, type, element); - else if(element == Attribute::CORNER) - attr->set(name, type, element); + attr->set(name, type, element); - if(mesh) - attr->reserve(mesh->verts.size(), mesh->triangles.size()); + /* this is weak .. */ + if(triangle_mesh) + attr->reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), 0, 0); + if(curve_mesh) + attr->reserve(0, 0, curve_mesh->curve_segments.size(), curve_mesh->curve_keys.size()); return attr; } -Attribute *AttributeSet::find(ustring name) +Attribute *AttributeSet::find(ustring name) const { - foreach(Attribute& attr, attributes) + foreach(const Attribute& attr, attributes) if(attr.name == name) - return &attr; + return (Attribute*)&attr; return NULL; } @@ -154,41 +211,59 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name) Attribute *attr = NULL; if(name == ustring()) - name = attribute_standard_name(std); + 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 */ diff --git a/intern/cycles/render/attribute.h b/intern/cycles/render/attribute.h index d05952edfd7..6c0c06d0425 100644 --- a/intern/cycles/render/attribute.h +++ b/intern/cycles/render/attribute.h @@ -21,7 +21,6 @@ #include "kernel_types.h" -#include "util_attribute.h" #include "util_list.h" #include "util_param.h" #include "util_types.h" @@ -42,36 +41,34 @@ class Mesh; class Attribute { public: - enum Element { - VERTEX, - FACE, - CORNER - }; - ustring name; AttributeStandard std; TypeDesc type; vector 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 attributes; AttributeSet(); ~AttributeSet(); - Attribute *add(ustring name, TypeDesc type, Attribute::Element element); - Attribute *find(ustring name); + Attribute *add(ustring name, TypeDesc type, AttributeElement element); + Attribute *find(ustring name) const; void remove(ustring name); Attribute *add(AttributeStandard std, ustring name = ustring()); - Attribute *find(AttributeStandard std); + Attribute *find(AttributeStandard std) const; void remove(AttributeStandard std); Attribute *find(AttributeRequest& req); - void reserve(int numverts, int numfaces); + void reserve(); void clear(); }; @@ -104,7 +102,7 @@ public: * * Request from a shader to use a certain attribute, so we can figure out * which ones we need to export from the host app end store for the kernel. - * The attribute is found either by name or by standard. */ + * The attribute is found either by name or by standard attribute type. */ class AttributeRequest { public: @@ -112,9 +110,9 @@ public: AttributeStandard std; /* temporary variables used by MeshManager */ - TypeDesc type; - AttributeElement element; - int offset; + TypeDesc triangle_type, curve_type; + AttributeElement triangle_element, curve_element; + int triangle_offset, curve_offset; AttributeRequest(ustring name_); AttributeRequest(AttributeStandard std); diff --git a/intern/cycles/render/curves.h b/intern/cycles/render/curves.h index 581b3010d77..85a549082f2 100644 --- a/intern/cycles/render/curves.h +++ b/intern/cycles/render/curves.h @@ -80,8 +80,7 @@ public: vector curve_firstkey; vector curve_keynum; vector curve_length; - vector curve_u; - vector curve_v; + vector curve_uv; vector curvekey_co; vector curvekey_time; diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 66e528c7230..cab6008dd7c 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -142,7 +142,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen /* count */ size_t num_lights = scene->lights.size(); size_t num_triangles = 0; - size_t num_curve_segs = 0; + size_t num_curve_segments = 0; foreach(Object *object, scene->objects) { Mesh *mesh = object->mesh; @@ -172,16 +172,16 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen } /* disabled for strands*/ - /*for(size_t i = 0; i < mesh->curve_segs.size(); i++) { - * Shader *shader = scene->shaders[mesh->curve_segs[i].curveshader]; + /*for(size_t i = 0; i < mesh->curve_segments.size(); i++) { + * Shader *shader = scene->shaders[mesh->curve_segments[i].shader]; * * if(shader->sample_as_light && shader->has_surface_emission) - * num_curve_segs++; + * num_curve_segments++; }*/ } } - size_t num_distribution = num_triangles + num_curve_segs; + size_t num_distribution = num_triangles + num_curve_segments; num_distribution += num_lights; /* emission area */ @@ -245,8 +245,8 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen } /*sample as light disabled for strands*/ - /*for(size_t i = 0; i < mesh->curve_segs.size(); i++) { - * Shader *shader = scene->shaders[mesh->curve_segs[i].curveshader]; + /*for(size_t i = 0; i < mesh->curve_segments.size(); i++) { + * Shader *shader = scene->shaders[mesh->curve_segments[i].shader]; * * if(shader->sample_as_light && shader->has_surface_emission) { * distribution[offset].x = totarea; @@ -255,7 +255,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen * distribution[offset].w = __int_as_float(object_id); * offset++; * - * Mesh::CurveSeg s = mesh->curve_segs[i]; + * Mesh::CurveSeg s = mesh->curve_segments[i]; * float3 p1 = mesh->curve_keys[s.v[0]].loc; * float r1 = mesh->curve_keys[s.v[0]].radius; * float3 p2 = mesh->curve_keys[s.v[1]].loc; diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index b20e5cebdc5..53cae53ef69 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -54,7 +54,8 @@ Mesh::Mesh() curveseg_offset = 0; curvekey_offset = 0; - attributes.mesh = this; + attributes.triangle_mesh = this; + curve_attributes.curve_mesh = this; } Mesh::~Mesh() @@ -62,15 +63,18 @@ Mesh::~Mesh() delete bvh; } -void Mesh::reserve(int numverts, int numtris) +void Mesh::reserve(int numverts, int numtris, int numcurves, int numcurvekeys) { /* reserve space to add verts and triangles later */ verts.resize(numverts); triangles.resize(numtris); shader.resize(numtris); smooth.resize(numtris); - /*currently no need in hair segment resize and curve data needs including*/ - attributes.reserve(numverts, numtris); + curve_keys.resize(numcurvekeys); + curve_segments.resize(numcurves); + + attributes.reserve(); + curve_attributes.reserve(); } void Mesh::clear() @@ -82,11 +86,10 @@ void Mesh::clear() smooth.clear(); curve_keys.clear(); - curve_keysCD.clear(); - curve_segs.clear(); - curve_attrib.clear(); + curve_segments.clear(); attributes.clear(); + curve_attributes.clear(); used_shaders.clear(); transform_applied = false; @@ -105,34 +108,24 @@ void Mesh::add_triangle(int v0, int v1, int v2, int shader_, bool smooth_) smooth.push_back(smooth_); } -void Mesh::add_curvekey(float3 loc, float radius, float time) +void Mesh::add_curve_key(float3 co, float radius) { CurveKey ck; - ck.loc = loc; + ck.co = co; ck.radius = radius; - ck.time = time; curve_keys.push_back(ck); } -void Mesh::add_curve(int v0, int v1, int shader, int curveid) +void Mesh::add_curve_segment(int v0, int v1, int shader, int curveid) { - CurveSeg s; + CurveSegment s; s.v[0] = v0; s.v[1] = v1; - s.curveshader = shader; + s.shader = shader; s.curve = curveid; - curve_segs.push_back(s); -} - -void Mesh::add_curveattrib(float u, float v) -{ - Curve_Attribute s; - s.uv[0] = u; - s.uv[1] = v; - - curve_attrib.push_back(s); + curve_segments.push_back(s); } void Mesh::compute_bounds() @@ -145,7 +138,7 @@ void Mesh::compute_bounds() bnds.grow(verts[i]); for(size_t i = 0; i < curve_keys_size; i++) - bnds.grow(curve_keys[i].loc, curve_keys[i].radius); + bnds.grow(curve_keys[i].co, curve_keys[i].radius); /* happens mostly on empty meshes */ if(!bnds.valid()) @@ -296,29 +289,31 @@ void Mesh::pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_seg_key size_t curve_keys_size = curve_keys.size(); CurveKey *keys_ptr = NULL; + /* pack curve keys */ if(curve_keys_size) { - keys_ptr = &curve_keys[0]; for(size_t i = 0; i < curve_keys_size; i++) { - float3 p = keys_ptr[i].loc; - curve_key_co[i] = make_float4(p.x, p.y, p.z, keys_ptr[i].radius); + float3 p = keys_ptr[i].co; + float radius = keys_ptr[i].radius; + + curve_key_co[i] = make_float4(p.x, p.y, p.z, radius); } } - size_t curve_seg_num = curve_segs.size(); + /* pack curve segments */ + size_t curve_seg_num = curve_segments.size(); if(curve_seg_num) { - CurveSeg *curve_ptr = &curve_segs[0]; - + CurveSegment *curve_ptr = &curve_segments[0]; int shader_id = 0; for(size_t i = 0; i < curve_seg_num; i++) { - CurveSeg s = curve_ptr[i]; - shader_id = scene->shader_manager->get_shader_id(s.curveshader, this, false); + CurveSegment s = curve_ptr[i]; + shader_id = scene->shader_manager->get_shader_id(s.shader, this, false); - float3 p1 = keys_ptr[s.v[0]].loc; - float3 p2 = keys_ptr[s.v[1]].loc; + float3 p1 = keys_ptr[s.v[0]].co; + float3 p2 = keys_ptr[s.v[1]].co; float length = len(p2 - p1); curve_seg_keys[i] = make_float4( @@ -414,7 +409,7 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vectorattribute_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, vectorattribute_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, vectorattribute_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& attr_float, vector& 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(); diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h index 24d3f02e082..ca8c755671f 100644 --- a/intern/cycles/render/mesh.h +++ b/intern/cycles/render/mesh.h @@ -50,26 +50,16 @@ public: int v[3]; }; - /* Mesh Strand Data*/ - struct CurveSeg { + /* Mesh Curve */ + struct CurveSegment { int v[2]; - uint curveshader; + uint shader; int curve; }; - struct Curve_Attribute { - float uv[2]; - }; - struct CurveKey { - float3 loc; + float3 co; float radius; - float time; - }; - - /*curve data for hair - currently only contains key tangent instead*/ - struct CurveData { - float3 tg; }; /* Displacement */ @@ -88,12 +78,11 @@ public: vector smooth; vector curve_keys; - vector curve_keysCD; - vector curve_segs; - vector curve_attrib; + vector curve_segments; vector used_shaders; AttributeSet attributes; + AttributeSet curve_attributes; BoundBox bounds; bool transform_applied; @@ -116,12 +105,11 @@ public: Mesh(); ~Mesh(); - void reserve(int numverts, int numfaces); + void reserve(int numverts, int numfaces, int numcurves, int numcurvekeys); void clear(); void add_triangle(int v0, int v1, int v2, int shader, bool smooth); - void add_curvekey(float3 loc, float radius, float time); - void add_curve(int v0, int v1, int shader, int curveid); - void add_curveattrib(float u, float v); + void add_curve_key(float3 loc, float radius); + void add_curve_segment(int v0, int v1, int shader, int curveid); void compute_bounds(); void add_face_normals(); diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 13e9ae81cf0..14ef3c68ad3 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -2251,6 +2251,16 @@ HairInfoNode::HairInfoNode() add_output("Tangent Normal", SHADER_SOCKET_NORMAL); } +void HairInfoNode::attributes(AttributeRequestSet *attributes) +{ + ShaderOutput *intercept_out = output("Intercept"); + + if(!intercept_out->links.empty()) + attributes->add(ATTR_STD_CURVE_INTERCEPT); + + ShaderNode::attributes(attributes); +} + void HairInfoNode::compile(SVMCompiler& compiler) { ShaderOutput *out; @@ -2263,8 +2273,9 @@ void HairInfoNode::compile(SVMCompiler& compiler) out = output("Intercept"); if(!out->links.empty()) { + int attr = compiler.attribute(ATTR_STD_CURVE_INTERCEPT); compiler.stack_assign(out); - compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_INTERCEPT, out->stack_offset); + compiler.add_node(NODE_ATTR, attr, out->stack_offset, NODE_ATTR_FLOAT); } out = output("Thickness"); diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index ee7afccb0e1..564ceee5a5b 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -334,6 +334,8 @@ public: class HairInfoNode : public ShaderNode { public: SHADER_NODE_CLASS(HairInfoNode) + + void attributes(AttributeRequestSet *attributes); }; class ValueNode : public ShaderNode { diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 588b4d50e1b..4862b47c342 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -89,12 +89,9 @@ void Object::apply_transform() mesh->verts[i] = transform_point(&tfm, mesh->verts[i]); for(size_t i = 0; i < mesh->curve_keys.size(); i++) - mesh->curve_keys[i].loc = transform_point(&tfm, mesh->curve_keys[i].loc); - - for(size_t i = 0; i < mesh->curve_keysCD.size(); i++) - mesh->curve_keysCD[i].tg = transform_direction(&tfm, mesh->curve_keysCD[i].tg); - + mesh->curve_keys[i].co = transform_point(&tfm, mesh->curve_keys[i].co); + Attribute *attr_tangent = mesh->curve_attributes.find(ATTR_STD_CURVE_TANGENT); Attribute *attr_fN = mesh->attributes.find(ATTR_STD_FACE_NORMAL); Attribute *attr_vN = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL); @@ -119,6 +116,13 @@ void Object::apply_transform() vN[i] = transform_direction(&ntfm, vN[i]); } + if(attr_tangent) { + float3 *tangent = attr_tangent->data_float3(); + + for(size_t i = 0; i < mesh->curve_keys.size(); i++) + tangent[i] = transform_direction(&tfm, tangent[i]); + } + if(bounds.valid()) { mesh->compute_bounds(); compute_bounds(false, 0.0f); @@ -199,10 +203,10 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene surface_area += triangle_area(p1, p2, p3); } - foreach(Mesh::CurveSeg& t, mesh->curve_segs) { - float3 p1 = mesh->curve_keys[t.v[0]].loc; + foreach(Mesh::CurveSegment& t, mesh->curve_segments) { + float3 p1 = mesh->curve_keys[t.v[0]].co; float r1 = mesh->curve_keys[t.v[0]].radius; - float3 p2 = mesh->curve_keys[t.v[1]].loc; + float3 p2 = mesh->curve_keys[t.v[1]].co; float r2 = mesh->curve_keys[t.v[1]].radius; /* currently ignores segment overlaps*/ @@ -225,10 +229,10 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene surface_area += triangle_area(p1, p2, p3); } - foreach(Mesh::CurveSeg& t, mesh->curve_segs) { - float3 p1 = mesh->curve_keys[t.v[0]].loc; + foreach(Mesh::CurveSegment& t, mesh->curve_segments) { + float3 p1 = mesh->curve_keys[t.v[0]].co; float r1 = mesh->curve_keys[t.v[0]].radius; - float3 p2 = mesh->curve_keys[t.v[1]].loc; + float3 p2 = mesh->curve_keys[t.v[1]].co; float r2 = mesh->curve_keys[t.v[1]].radius; /* currently ignores segment overlaps*/ diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index 8b121d3b2fb..9490fd96be0 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -25,7 +25,6 @@ #include "kernel_types.h" -#include "util_attribute.h" #include "util_param.h" #include "util_string.h" #include "util_thread.h" @@ -74,8 +73,8 @@ public: device_vector tri_vindex; device_vector tri_verts; - device_vector cur_segs; - device_vector cur_keys; + device_vector curve_segments; + device_vector curve_keys; /* objects */ device_vector objects; diff --git a/intern/cycles/subd/subd_dice.cpp b/intern/cycles/subd/subd_dice.cpp index 6920df9954c..48e6808bc38 100644 --- a/intern/cycles/subd/subd_dice.cpp +++ b/intern/cycles/subd/subd_dice.cpp @@ -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); diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt index dce417704cc..bcaaa9a71b9 100644 --- a/intern/cycles/util/CMakeLists.txt +++ b/intern/cycles/util/CMakeLists.txt @@ -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 diff --git a/intern/cycles/util/util_attribute.cpp b/intern/cycles/util/util_attribute.cpp deleted file mode 100644 index 057fb6213e9..00000000000 --- a/intern/cycles/util/util_attribute.cpp +++ /dev/null @@ -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 diff --git a/intern/cycles/util/util_attribute.h b/intern/cycles/util/util_attribute.h deleted file mode 100644 index 334864c7f44..00000000000 --- a/intern/cycles/util/util_attribute.h +++ /dev/null @@ -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__ */ - diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h index 00b6cf5c56e..bb6de1197e7 100644 --- a/intern/cycles/util/util_types.h +++ b/intern/cycles/util/util_types.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__ */