static void attr_create_subd_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool subdivide_uvs) { if (b_mesh.uv_layers.length() != 0) { BL::Mesh::uv_layers_iterator l; int i = 0; for (b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l, ++i) { bool active_render = l->active_render(); AttributeStandard uv_std = (active_render) ? ATTR_STD_UV : ATTR_STD_NONE; ustring uv_name = ustring(l->name().c_str()); AttributeStandard tangent_std = (active_render) ? ATTR_STD_UV_TANGENT : ATTR_STD_NONE; ustring tangent_name = ustring((string(l->name().c_str()) + ".tangent").c_str()); /* Denotes whether UV map was requested directly. */ const bool need_uv = mesh->need_attribute(scene, uv_name) || mesh->need_attribute(scene, uv_std); /* Denotes whether tangent was requested directly. */ const bool need_tangent = mesh->need_attribute(scene, tangent_name) || (active_render && mesh->need_attribute(scene, tangent_std)); Attribute *uv_attr = NULL; /* UV map */ if (need_uv || need_tangent) { if (active_render) uv_attr = mesh->subd_attributes.add(uv_std, uv_name); else uv_attr = mesh->subd_attributes.add(uv_name, TypeFloat2, ATTR_ELEMENT_CORNER); if (subdivide_uvs) { uv_attr->flags |= ATTR_SUBDIVIDED; } BL::Mesh::polygons_iterator p; float2 *fdata = uv_attr->data_float2(); for (b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) { int n = p->loop_total(); for (int j = 0; j < n; j++) { *(fdata++) = get_float2(l->data[p->loop_start() + j].uv()); } } } /* UV tangent */ if (need_tangent) { AttributeStandard sign_std = (active_render) ? ATTR_STD_UV_TANGENT_SIGN : ATTR_STD_NONE; ustring sign_name = ustring((string(l->name().c_str()) + ".tangent_sign").c_str()); bool need_sign = (mesh->need_attribute(scene, sign_name) || mesh->need_attribute(scene, sign_std)); mikk_compute_tangents(b_mesh, l->name().c_str(), mesh, need_sign, active_render); } /* Remove temporarily created UV attribute. */ if (!need_uv && uv_attr != NULL) { mesh->subd_attributes.remove(uv_attr); } } } else if (mesh->need_attribute(scene, ATTR_STD_UV_TANGENT)) { bool need_sign = mesh->need_attribute(scene, ATTR_STD_UV_TANGENT_SIGN); mikk_compute_tangents(b_mesh, NULL, mesh, need_sign, true); if (!mesh->need_attribute(scene, ATTR_STD_GENERATED)) { mesh->subd_attributes.remove(ATTR_STD_GENERATED); } } }
void BlenderSync::sync_curves( Mesh *mesh, BL::Mesh &b_mesh, BL::Object &b_ob, bool motion, int motion_step) { if (!motion) { /* Clear stored curve data */ mesh->curve_keys.clear(); mesh->curve_radius.clear(); mesh->curve_first_key.clear(); mesh->curve_shader.clear(); mesh->curve_attributes.clear(); } /* obtain general settings */ const bool use_curves = scene->curve_system_manager->use_curves; if (!(use_curves && b_ob.mode() != b_ob.mode_PARTICLE_EDIT && b_ob.mode() != b_ob.mode_EDIT)) { if (!motion) mesh->compute_bounds(); return; } const int primitive = scene->curve_system_manager->primitive; const int triangle_method = scene->curve_system_manager->triangle_method; const int resolution = scene->curve_system_manager->resolution; const size_t vert_num = mesh->verts.size(); const size_t tri_num = mesh->num_triangles(); int used_res = 1; /* extract particle hair data - should be combined with connecting to mesh later*/ ParticleCurveData CData; ObtainCacheParticleData(mesh, &b_mesh, &b_ob, &CData, !preview); /* add hair geometry to mesh */ if (primitive == CURVE_TRIANGLES) { if (triangle_method == CURVE_CAMERA_TRIANGLES) { /* obtain camera parameters */ float3 RotCam; Camera *camera = scene->camera; Transform &ctfm = camera->matrix; if (camera->type == CAMERA_ORTHOGRAPHIC) { RotCam = -make_float3(ctfm.x.z, ctfm.y.z, ctfm.z.z); } else { Transform tfm = get_transform(b_ob.matrix_world()); Transform itfm = transform_quick_inverse(tfm); RotCam = transform_point(&itfm, make_float3(ctfm.x.w, ctfm.y.w, ctfm.z.w)); } bool is_ortho = camera->type == CAMERA_ORTHOGRAPHIC; ExportCurveTrianglePlanes(mesh, &CData, RotCam, is_ortho); } else { ExportCurveTriangleGeometry(mesh, &CData, resolution); used_res = resolution; } } else { if (motion) ExportCurveSegmentsMotion(mesh, &CData, motion_step); else ExportCurveSegments(scene, mesh, &CData); } /* generated coordinates from first key. we should ideally get this from * blender to handle deforming objects */ if (!motion) { if (mesh->need_attribute(scene, ATTR_STD_GENERATED)) { float3 loc, size; mesh_texture_space(b_mesh, loc, size); if (primitive == CURVE_TRIANGLES) { Attribute *attr_generated = mesh->attributes.add(ATTR_STD_GENERATED); float3 *generated = attr_generated->data_float3(); for (size_t i = vert_num; i < mesh->verts.size(); i++) generated[i] = mesh->verts[i] * size - loc; } else { Attribute *attr_generated = mesh->curve_attributes.add(ATTR_STD_GENERATED); float3 *generated = attr_generated->data_float3(); for (size_t i = 0; i < mesh->num_curves(); i++) { float3 co = mesh->curve_keys[mesh->get_curve(i).first_key]; generated[i] = co * size - loc; } } } } /* create vertex color attributes */ if (!motion) { BL::Mesh::vertex_colors_iterator l; int vcol_num = 0; for (b_mesh.vertex_colors.begin(l); l != b_mesh.vertex_colors.end(); ++l, vcol_num++) { if (!mesh->need_attribute(scene, ustring(l->name().c_str()))) continue; ObtainCacheParticleVcol(mesh, &b_mesh, &b_ob, &CData, !preview, vcol_num); if (primitive == CURVE_TRIANGLES) { Attribute *attr_vcol = mesh->attributes.add( ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE); uchar4 *cdata = attr_vcol->data_uchar4(); ExportCurveTriangleVcol(&CData, tri_num * 3, used_res, cdata); } else { Attribute *attr_vcol = mesh->curve_attributes.add( ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CURVE); float3 *fdata = attr_vcol->data_float3(); if (fdata) { size_t i = 0; /* Encode vertex color using the sRGB curve. */ for (size_t curve = 0; curve < CData.curve_vcol.size(); curve++) { fdata[i++] = color_srgb_to_linear_v3(CData.curve_vcol[curve]); } } } } } /* create UV attributes */ if (!motion) { BL::Mesh::uv_layers_iterator l; int uv_num = 0; for (b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l, uv_num++) { bool active_render = l->active_render(); AttributeStandard std = (active_render) ? ATTR_STD_UV : ATTR_STD_NONE; ustring name = ustring(l->name().c_str()); /* UV map */ if (mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) { Attribute *attr_uv; ObtainCacheParticleUV(mesh, &b_mesh, &b_ob, &CData, !preview, uv_num); if (primitive == CURVE_TRIANGLES) { if (active_render) attr_uv = mesh->attributes.add(std, name); else attr_uv = mesh->attributes.add(name, TypeFloat2, ATTR_ELEMENT_CORNER); float2 *uv = attr_uv->data_float2(); ExportCurveTriangleUV(&CData, tri_num * 3, used_res, uv); } else { if (active_render) attr_uv = mesh->curve_attributes.add(std, name); else attr_uv = mesh->curve_attributes.add(name, TypeFloat2, ATTR_ELEMENT_CURVE); float2 *uv = attr_uv->data_float2(); if (uv) { size_t i = 0; for (size_t curve = 0; curve < CData.curve_uv.size(); curve++) { uv[i++] = CData.curve_uv[curve]; } } } } } } mesh->compute_bounds(); }
/* Create uv map attributes. */ static void attr_create_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh) { if (b_mesh.uv_layers.length() != 0) { BL::Mesh::uv_layers_iterator l; for (b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l) { const bool active_render = l->active_render(); AttributeStandard uv_std = (active_render) ? ATTR_STD_UV : ATTR_STD_NONE; ustring uv_name = ustring(l->name().c_str()); AttributeStandard tangent_std = (active_render) ? ATTR_STD_UV_TANGENT : ATTR_STD_NONE; ustring tangent_name = ustring((string(l->name().c_str()) + ".tangent").c_str()); /* Denotes whether UV map was requested directly. */ const bool need_uv = mesh->need_attribute(scene, uv_name) || mesh->need_attribute(scene, uv_std); /* Denotes whether tangent was requested directly. */ const bool need_tangent = mesh->need_attribute(scene, tangent_name) || (active_render && mesh->need_attribute(scene, tangent_std)); /* UV map */ /* NOTE: We create temporary UV layer if its needed for tangent but * wasn't requested by other nodes in shaders. */ Attribute *uv_attr = NULL; if (need_uv || need_tangent) { if (active_render) { uv_attr = mesh->attributes.add(uv_std, uv_name); } else { uv_attr = mesh->attributes.add(uv_name, TypeFloat2, ATTR_ELEMENT_CORNER); } BL::Mesh::loop_triangles_iterator t; float2 *fdata = uv_attr->data_float2(); for (b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) { int3 li = get_int3(t->loops()); fdata[0] = get_float2(l->data[li[0]].uv()); fdata[1] = get_float2(l->data[li[1]].uv()); fdata[2] = get_float2(l->data[li[2]].uv()); fdata += 3; } } /* UV tangent */ if (need_tangent) { AttributeStandard sign_std = (active_render) ? ATTR_STD_UV_TANGENT_SIGN : ATTR_STD_NONE; ustring sign_name = ustring((string(l->name().c_str()) + ".tangent_sign").c_str()); bool need_sign = (mesh->need_attribute(scene, sign_name) || mesh->need_attribute(scene, sign_std)); mikk_compute_tangents(b_mesh, l->name().c_str(), mesh, need_sign, active_render); } /* Remove temporarily created UV attribute. */ if (!need_uv && uv_attr != NULL) { mesh->attributes.remove(uv_attr); } } } else if (mesh->need_attribute(scene, ATTR_STD_UV_TANGENT)) { bool need_sign = mesh->need_attribute(scene, ATTR_STD_UV_TANGENT_SIGN); mikk_compute_tangents(b_mesh, NULL, mesh, need_sign, true); if (!mesh->need_attribute(scene, ATTR_STD_GENERATED)) { mesh->attributes.remove(ATTR_STD_GENERATED); } } }
/* Create uv map attributes. */ static void attr_create_uv_map(Scene *scene, Mesh *mesh, BL::Mesh& b_mesh, const vector<int>& nverts, const vector<int>& face_flags, bool subdivision, bool subdivide_uvs) { if(subdivision) { BL::Mesh::uv_layers_iterator l; int i = 0; for(b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l, ++i) { bool active_render = b_mesh.uv_textures[i].active_render(); AttributeStandard std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE; ustring name = ustring(l->name().c_str()); /* UV map */ if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) { Attribute *attr; if(active_render) attr = mesh->subd_attributes.add(std, name); else attr = mesh->subd_attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER); if(subdivide_uvs) { attr->flags |= ATTR_SUBDIVIDED; } BL::Mesh::polygons_iterator p; float3 *fdata = attr->data_float3(); for(b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) { int n = p->loop_total(); for(int j = 0; j < n; j++) { *(fdata++) = get_float3(l->data[p->loop_start() + j].uv()); } } } } } else if(b_mesh.tessface_uv_textures.length() != 0) { BL::Mesh::tessface_uv_textures_iterator l; for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) { bool active_render = l->active_render(); AttributeStandard std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE; ustring name = ustring(l->name().c_str()); /* UV map */ if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) { Attribute *attr; if(active_render) attr = mesh->attributes.add(std, name); else attr = mesh->attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER); BL::MeshTextureFaceLayer::data_iterator t; float3 *fdata = attr->data_float3(); size_t i = 0; for(l->data.begin(t); t != l->data.end(); ++t, ++i) { int tri_a[3], tri_b[3]; face_split_tri_indices(nverts[i], face_flags[i], tri_a, tri_b); float3 uvs[4]; uvs[0] = get_float3(t->uv1()); uvs[1] = get_float3(t->uv2()); uvs[2] = get_float3(t->uv3()); if(nverts[i] == 4) { uvs[3] = get_float3(t->uv4()); } fdata[0] = uvs[tri_a[0]]; fdata[1] = uvs[tri_a[1]]; fdata[2] = uvs[tri_a[2]]; fdata += 3; if(nverts[i] == 4) { fdata[0] = uvs[tri_b[0]]; fdata[1] = uvs[tri_b[1]]; fdata[2] = uvs[tri_b[2]]; fdata += 3; } } } /* UV tangent */ std = (active_render)? ATTR_STD_UV_TANGENT: ATTR_STD_NONE; name = ustring((string(l->name().c_str()) + ".tangent").c_str()); if(mesh->need_attribute(scene, name) || (active_render && mesh->need_attribute(scene, std))) { std = (active_render)? ATTR_STD_UV_TANGENT_SIGN: ATTR_STD_NONE; name = ustring((string(l->name().c_str()) + ".tangent_sign").c_str()); bool need_sign = (mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)); mikk_compute_tangents(b_mesh, &(*l), mesh, nverts, face_flags, need_sign, active_render); } } } else if(mesh->need_attribute(scene, ATTR_STD_UV_TANGENT)) { bool need_sign = mesh->need_attribute(scene, ATTR_STD_UV_TANGENT_SIGN); mikk_compute_tangents(b_mesh, NULL, mesh, nverts, face_flags, need_sign, true); } }