Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/blender/blender_mesh.cpp
| Show First 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | inline void face_split_tri_indices(const int face_flag, | ||||
| } | } | ||||
| } | } | ||||
| /* Tangent Space */ | /* Tangent Space */ | ||||
| struct MikkUserData { | struct MikkUserData { | ||||
| MikkUserData(const BL::Mesh& b_mesh, | MikkUserData(const BL::Mesh& b_mesh, | ||||
| BL::MeshTextureFaceLayer *layer, | BL::MeshTextureFaceLayer *layer, | ||||
| int num_faces) | const Mesh *mesh, | ||||
| : b_mesh(b_mesh), | float3 *tangent, | ||||
| layer(layer), | float *tangent_sign) | ||||
| num_faces(num_faces) | : mesh(mesh), | ||||
| { | texface(NULL), | ||||
| tangent.resize(num_faces*4); | orco(NULL), | ||||
| tangent(tangent), | |||||
| tangent_sign(tangent_sign) | |||||
| { | |||||
| Attribute *attr_vN = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL); | |||||
| vertex_normal = attr_vN->data_float3(); | |||||
| if(layer == NULL) { | |||||
| Attribute *attr_orco = mesh->attributes.find(ATTR_STD_GENERATED); | |||||
| orco = attr_orco->data_float3(); | |||||
| mesh_texture_space(*(BL::Mesh*)&b_mesh, orco_loc, orco_size); | |||||
| } | |||||
| else { | |||||
| Attribute *attr_uv = mesh->attributes.find(ustring(layer->name())); | |||||
| if(attr_uv != NULL) { | |||||
| texface = attr_uv->data_float3(); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| BL::Mesh b_mesh; | const Mesh *mesh; | ||||
| BL::MeshTextureFaceLayer *layer; | |||||
| int num_faces; | int num_faces; | ||||
| vector<float4> tangent; | |||||
| float3 *vertex_normal; | |||||
| float3 *texface; | |||||
| float3 *orco; | |||||
| float3 orco_loc, orco_size; | |||||
| float3 *tangent; | |||||
| float *tangent_sign; | |||||
| }; | }; | ||||
| static int mikk_get_num_faces(const SMikkTSpaceContext *context) | static int mikk_get_num_faces(const SMikkTSpaceContext *context) | ||||
| { | { | ||||
| MikkUserData *userdata = (MikkUserData*)context->m_pUserData; | const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData; | ||||
| return userdata->num_faces; | return userdata->mesh->num_triangles(); | ||||
| } | } | ||||
| static int mikk_get_num_verts_of_face(const SMikkTSpaceContext *context, const int face_num) | static int mikk_get_num_verts_of_face(const SMikkTSpaceContext * /*context*/, | ||||
| const int /*face_num*/) | |||||
| { | { | ||||
| MikkUserData *userdata = (MikkUserData*)context->m_pUserData; | return 3; | ||||
| BL::MeshTessFace f = userdata->b_mesh.tessfaces[face_num]; | |||||
| int4 vi = get_int4(f.vertices_raw()); | |||||
| return (vi[3] == 0)? 3: 4; | |||||
| } | } | ||||
| static void mikk_get_position(const SMikkTSpaceContext *context, float P[3], const int face_num, const int vert_num) | static void mikk_get_position(const SMikkTSpaceContext *context, | ||||
| float P[3], | |||||
| const int face_num, const int vert_num) | |||||
| { | { | ||||
| MikkUserData *userdata = (MikkUserData*)context->m_pUserData; | const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData; | ||||
| BL::MeshTessFace f = userdata->b_mesh.tessfaces[face_num]; | const Mesh *mesh = userdata->mesh; | ||||
| int4 vi = get_int4(f.vertices_raw()); | const int vert_index = mesh->triangles[face_num * 3 + vert_num]; | ||||
| BL::MeshVertex v = userdata->b_mesh.vertices[vi[vert_num]]; | const float3 vP = mesh->verts[vert_index]; | ||||
| float3 vP = get_float3(v.co()); | |||||
| P[0] = vP.x; | P[0] = vP.x; | ||||
| P[1] = vP.y; | P[1] = vP.y; | ||||
| P[2] = vP.z; | P[2] = vP.z; | ||||
| } | } | ||||
| static void mikk_get_texture_coordinate(const SMikkTSpaceContext *context, float uv[2], const int face_num, const int vert_num) | static void mikk_get_texture_coordinate(const SMikkTSpaceContext *context, | ||||
| { | float uv[2], | ||||
| MikkUserData *userdata = (MikkUserData*)context->m_pUserData; | const int face_num, const int vert_num) | ||||
| if(userdata->layer != NULL) { | { | ||||
| BL::MeshTextureFace tf = userdata->layer->data[face_num]; | const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData; | ||||
| float3 tfuv; | if(userdata->texface != NULL) { | ||||
| const size_t corner_index = face_num * 3 + vert_num; | |||||
| switch(vert_num) { | float3 tfuv = userdata->texface[corner_index]; | ||||
| case 0: | |||||
| tfuv = get_float3(tf.uv1()); | |||||
| break; | |||||
| case 1: | |||||
| tfuv = get_float3(tf.uv2()); | |||||
| break; | |||||
| case 2: | |||||
| tfuv = get_float3(tf.uv3()); | |||||
| break; | |||||
| default: | |||||
| tfuv = get_float3(tf.uv4()); | |||||
| break; | |||||
| } | |||||
| uv[0] = tfuv.x; | uv[0] = tfuv.x; | ||||
| uv[1] = tfuv.y; | uv[1] = tfuv.y; | ||||
| } | } | ||||
| else { | else if(userdata->orco != NULL) { | ||||
| int vert_idx = userdata->b_mesh.tessfaces[face_num].vertices()[vert_num]; | const Mesh *mesh = userdata->mesh; | ||||
| float3 orco = | const size_t vertex_index = mesh->triangles[face_num * 3 + vert_num]; | ||||
| get_float3(userdata->b_mesh.vertices[vert_idx].undeformed_co()); | const float3 orco_loc = userdata->orco_loc; | ||||
| float2 tmp = map_to_sphere(make_float3(orco[0], orco[1], orco[2])); | const float3 orco_size = userdata->orco_size; | ||||
| const float3 orco = (userdata->orco[vertex_index] + orco_loc) / orco_size; | |||||
| const float2 tmp = map_to_sphere(orco); | |||||
| uv[0] = tmp.x; | uv[0] = tmp.x; | ||||
| uv[1] = tmp.y; | uv[1] = tmp.y; | ||||
| } | } | ||||
| else { | |||||
| uv[0] = 0.0f; | |||||
| uv[1] = 0.0f; | |||||
| } | |||||
| } | } | ||||
| static void mikk_get_normal(const SMikkTSpaceContext *context, float N[3], const int face_num, const int vert_num) | static void mikk_get_normal(const SMikkTSpaceContext *context, float N[3], | ||||
| const int face_num, const int vert_num) | |||||
| { | { | ||||
| MikkUserData *userdata = (MikkUserData*)context->m_pUserData; | const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData; | ||||
| BL::MeshTessFace f = userdata->b_mesh.tessfaces[face_num]; | const Mesh *mesh = userdata->mesh; | ||||
| float3 vN; | float3 vN; | ||||
| if(mesh->smooth[face_num]) { | |||||
| if(f.use_smooth()) { | const size_t vert_index = mesh->triangles[face_num * 3 + vert_num]; | ||||
| int4 vi = get_int4(f.vertices_raw()); | vN = userdata->vertex_normal[vert_index]; | ||||
| BL::MeshVertex v = userdata->b_mesh.vertices[vi[vert_num]]; | |||||
| vN = get_float3(v.normal()); | |||||
| } | } | ||||
| else { | else { | ||||
| vN = get_float3(f.normal()); | const Mesh::Triangle tri = mesh->get_triangle(face_num); | ||||
| vN = tri.compute_normal(&mesh->verts[0]); | |||||
| } | } | ||||
| N[0] = vN.x; | N[0] = vN.x; | ||||
| N[1] = vN.y; | N[1] = vN.y; | ||||
| N[2] = vN.z; | N[2] = vN.z; | ||||
| } | } | ||||
| static void mikk_set_tangent_space(const SMikkTSpaceContext *context, const float T[], const float sign, const int face, const int vert) | static void mikk_set_tangent_space(const SMikkTSpaceContext *context, | ||||
| const float T[], | |||||
| const float sign, | |||||
| const int face_num, const int vert_num) | |||||
| { | { | ||||
| MikkUserData *userdata = (MikkUserData*)context->m_pUserData; | MikkUserData *userdata = (MikkUserData *)context->m_pUserData; | ||||
| const size_t corner_index = face_num * 3 + vert_num; | |||||
| userdata->tangent[face*4 + vert] = make_float4(T[0], T[1], T[2], sign); | userdata->tangent[corner_index] = make_float3(T[0], T[1], T[2]); | ||||
| if(userdata->tangent_sign != NULL) { | |||||
| userdata->tangent_sign[corner_index] = sign; | |||||
| } | |||||
| } | } | ||||
| static void mikk_compute_tangents(BL::Mesh& b_mesh, | static void mikk_compute_tangents(const BL::Mesh& b_mesh, | ||||
| BL::MeshTextureFaceLayer *b_layer, | BL::MeshTextureFaceLayer *b_layer, | ||||
| Mesh *mesh, | Mesh *mesh, | ||||
| const vector<int>& nverts, | |||||
| const vector<int>& face_flags, | |||||
| bool need_sign, | bool need_sign, | ||||
| bool active_render) | bool active_render) | ||||
| { | { | ||||
| /* setup userdata */ | /* Create tangent attributes. */ | ||||
| MikkUserData userdata(b_mesh, b_layer, nverts.size()); | |||||
| /* setup interface */ | |||||
| SMikkTSpaceInterface sm_interface; | |||||
| memset(&sm_interface, 0, sizeof(sm_interface)); | |||||
| sm_interface.m_getNumFaces = mikk_get_num_faces; | |||||
| sm_interface.m_getNumVerticesOfFace = mikk_get_num_verts_of_face; | |||||
| sm_interface.m_getPosition = mikk_get_position; | |||||
| sm_interface.m_getTexCoord = mikk_get_texture_coordinate; | |||||
| sm_interface.m_getNormal = mikk_get_normal; | |||||
| sm_interface.m_setTSpaceBasic = mikk_set_tangent_space; | |||||
| /* setup context */ | |||||
| SMikkTSpaceContext context; | |||||
| memset(&context, 0, sizeof(context)); | |||||
| context.m_pUserData = &userdata; | |||||
| context.m_pInterface = &sm_interface; | |||||
| /* compute tangents */ | |||||
| genTangSpaceDefault(&context); | |||||
| /* create tangent attributes */ | |||||
| Attribute *attr; | Attribute *attr; | ||||
| ustring name; | ustring name; | ||||
| if(b_layer != NULL) | if(b_layer != NULL) { | ||||
| name = ustring((string(b_layer->name().c_str()) + ".tangent").c_str()); | name = ustring((string(b_layer->name().c_str()) + ".tangent").c_str()); | ||||
| else | } | ||||
| else { | |||||
| name = ustring("orco.tangent"); | name = ustring("orco.tangent"); | ||||
| } | |||||
| if(active_render) | if(active_render) { | ||||
| attr = mesh->attributes.add(ATTR_STD_UV_TANGENT, name); | attr = mesh->attributes.add(ATTR_STD_UV_TANGENT, name); | ||||
| else | } | ||||
| attr = mesh->attributes.add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER); | else { | ||||
| attr = mesh->attributes.add(name, | |||||
| TypeDesc::TypeVector, | |||||
| ATTR_ELEMENT_CORNER); | |||||
| } | |||||
| float3 *tangent = attr->data_float3(); | float3 *tangent = attr->data_float3(); | ||||
| /* Create bitangent sign attribute. */ | |||||
| /* create bitangent sign attribute */ | |||||
| float *tangent_sign = NULL; | float *tangent_sign = NULL; | ||||
| if(need_sign) { | if(need_sign) { | ||||
| Attribute *attr_sign; | Attribute *attr_sign; | ||||
| ustring name_sign; | ustring name_sign; | ||||
| if(b_layer != NULL) | if(b_layer != NULL) { | ||||
| name_sign = ustring((string(b_layer->name().c_str()) + ".tangent_sign").c_str()); | name_sign = ustring((string(b_layer->name().c_str()) + | ||||
| else | ".tangent_sign").c_str()); | ||||
| name_sign = ustring("orco.tangent_sign"); | |||||
| 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, ATTR_ELEMENT_CORNER); | |||||
| tangent_sign = attr_sign->data_float(); | |||||
| } | } | ||||
| else { | |||||
| for(int i = 0; i < nverts.size(); i++) { | name_sign = ustring("orco.tangent_sign"); | ||||
| int tri_a[3], tri_b[3]; | |||||
| face_split_tri_indices(face_flags[i], tri_a, tri_b); | |||||
| tangent[0] = float4_to_float3(userdata.tangent[i*4 + tri_a[0]]); | |||||
| tangent[1] = float4_to_float3(userdata.tangent[i*4 + tri_a[1]]); | |||||
| tangent[2] = float4_to_float3(userdata.tangent[i*4 + tri_a[2]]); | |||||
| tangent += 3; | |||||
| if(tangent_sign) { | |||||
| tangent_sign[0] = userdata.tangent[i*4 + tri_a[0]].w; | |||||
| tangent_sign[1] = userdata.tangent[i*4 + tri_a[1]].w; | |||||
| tangent_sign[2] = userdata.tangent[i*4 + tri_a[2]].w; | |||||
| tangent_sign += 3; | |||||
| } | } | ||||
| if(nverts[i] == 4) { | if(active_render) { | ||||
| tangent[0] = float4_to_float3(userdata.tangent[i*4 + tri_b[0]]); | attr_sign = mesh->attributes.add(ATTR_STD_UV_TANGENT_SIGN, | ||||
| tangent[1] = float4_to_float3(userdata.tangent[i*4 + tri_b[1]]); | name_sign); | ||||
| tangent[2] = float4_to_float3(userdata.tangent[i*4 + tri_b[2]]); | |||||
| tangent += 3; | |||||
| if(tangent_sign) { | |||||
| tangent_sign[0] = userdata.tangent[i*4 + tri_b[0]].w; | |||||
| tangent_sign[1] = userdata.tangent[i*4 + tri_b[1]].w; | |||||
| tangent_sign[2] = userdata.tangent[i*4 + tri_b[2]].w; | |||||
| tangent_sign += 3; | |||||
| } | } | ||||
| else { | |||||
| attr_sign = mesh->attributes.add(name_sign, | |||||
| TypeDesc::TypeFloat, | |||||
| ATTR_ELEMENT_CORNER); | |||||
| } | } | ||||
| tangent_sign = attr_sign->data_float(); | |||||
| } | } | ||||
| /* Setup userdata. */ | |||||
| MikkUserData userdata(b_mesh, b_layer, mesh, tangent, tangent_sign); | |||||
| /* Setup interface. */ | |||||
| SMikkTSpaceInterface sm_interface; | |||||
| memset(&sm_interface, 0, sizeof(sm_interface)); | |||||
| sm_interface.m_getNumFaces = mikk_get_num_faces; | |||||
| sm_interface.m_getNumVerticesOfFace = mikk_get_num_verts_of_face; | |||||
| sm_interface.m_getPosition = mikk_get_position; | |||||
| sm_interface.m_getTexCoord = mikk_get_texture_coordinate; | |||||
| sm_interface.m_getNormal = mikk_get_normal; | |||||
| sm_interface.m_setTSpaceBasic = mikk_set_tangent_space; | |||||
| /* Setup context. */ | |||||
| SMikkTSpaceContext context; | |||||
| memset(&context, 0, sizeof(context)); | |||||
| context.m_pUserData = &userdata; | |||||
| context.m_pInterface = &sm_interface; | |||||
| /* Compute tangents. */ | |||||
| genTangSpaceDefault(&context); | |||||
| } | } | ||||
| /* Create Volume Attribute */ | /* Create Volume Attribute */ | ||||
| static void create_mesh_volume_attribute(BL::Object& b_ob, | static void create_mesh_volume_attribute(BL::Object& b_ob, | ||||
| Mesh *mesh, | Mesh *mesh, | ||||
| ImageManager *image_manager, | ImageManager *image_manager, | ||||
| AttributeStandard std, | AttributeStandard std, | ||||
| ▲ Show 20 Lines • Show All 156 Lines • ▼ Show 20 Lines | for(b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l, ++i) { | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else if(b_mesh.tessface_uv_textures.length() != 0) { | else if(b_mesh.tessface_uv_textures.length() != 0) { | ||||
| BL::Mesh::tessface_uv_textures_iterator l; | BL::Mesh::tessface_uv_textures_iterator l; | ||||
| for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) { | for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) { | ||||
| bool active_render = l->active_render(); | const bool active_render = l->active_render(); | ||||
| AttributeStandard std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE; | AttributeStandard uv_std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE; | ||||
| ustring name = ustring(l->name().c_str()); | 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 */ | /* UV map */ | ||||
| if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) { | /* NOTE: We create temporary UV layer if its needed for tangent but | ||||
| Attribute *attr; | * wasn't requested by other nodes in shaders. | ||||
| */ | |||||
| if(active_render) | Attribute *uv_attr = NULL; | ||||
| attr = mesh->attributes.add(std, name); | if(need_uv || need_tangent) { | ||||
| else | if(active_render) { | ||||
| attr = mesh->attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER); | uv_attr = mesh->attributes.add(uv_std, uv_name); | ||||
| } | |||||
| else { | |||||
| uv_attr = mesh->attributes.add(uv_name, | |||||
| TypeDesc::TypePoint, | |||||
| ATTR_ELEMENT_CORNER); | |||||
| } | |||||
| BL::MeshTextureFaceLayer::data_iterator t; | BL::MeshTextureFaceLayer::data_iterator t; | ||||
| float3 *fdata = attr->data_float3(); | float3 *fdata = uv_attr->data_float3(); | ||||
| size_t i = 0; | size_t i = 0; | ||||
| for(l->data.begin(t); t != l->data.end(); ++t, ++i) { | for(l->data.begin(t); t != l->data.end(); ++t, ++i) { | ||||
| int tri_a[3], tri_b[3]; | int tri_a[3], tri_b[3]; | ||||
| face_split_tri_indices(face_flags[i], tri_a, tri_b); | face_split_tri_indices(face_flags[i], tri_a, tri_b); | ||||
| float3 uvs[4]; | float3 uvs[4]; | ||||
| uvs[0] = get_float3(t->uv1()); | uvs[0] = get_float3(t->uv1()); | ||||
| Show All 13 Lines | for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) { | ||||
| fdata[1] = uvs[tri_b[1]]; | fdata[1] = uvs[tri_b[1]]; | ||||
| fdata[2] = uvs[tri_b[2]]; | fdata[2] = uvs[tri_b[2]]; | ||||
| fdata += 3; | fdata += 3; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* UV tangent */ | /* UV tangent */ | ||||
| std = (active_render)? ATTR_STD_UV_TANGENT: ATTR_STD_NONE; | if(need_tangent) { | ||||
| name = ustring((string(l->name().c_str()) + ".tangent").c_str()); | AttributeStandard sign_std = | ||||
| (active_render)? ATTR_STD_UV_TANGENT_SIGN | |||||
| if(mesh->need_attribute(scene, name) || (active_render && mesh->need_attribute(scene, std))) { | : ATTR_STD_NONE; | ||||
| std = (active_render)? ATTR_STD_UV_TANGENT_SIGN: ATTR_STD_NONE; | ustring sign_name = ustring( | ||||
| name = ustring((string(l->name().c_str()) + ".tangent_sign").c_str()); | (string(l->name().c_str()) + ".tangent_sign").c_str()); | ||||
| bool need_sign = (mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)); | bool need_sign = (mesh->need_attribute(scene, sign_name) || | ||||
| mesh->need_attribute(scene, sign_std)); | |||||
| mikk_compute_tangents(b_mesh, | mikk_compute_tangents(b_mesh, | ||||
| &(*l), | &(*l), | ||||
| mesh, | mesh, | ||||
| nverts, | |||||
| face_flags, | |||||
| need_sign, | need_sign, | ||||
| active_render); | 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)) { | else if(mesh->need_attribute(scene, ATTR_STD_UV_TANGENT)) { | ||||
| bool need_sign = mesh->need_attribute(scene, ATTR_STD_UV_TANGENT_SIGN); | bool need_sign = mesh->need_attribute(scene, ATTR_STD_UV_TANGENT_SIGN); | ||||
| mikk_compute_tangents(b_mesh, | mikk_compute_tangents(b_mesh, NULL, mesh, need_sign, true); | ||||
| NULL, | if(!mesh->need_attribute(scene, ATTR_STD_GENERATED)) { | ||||
| mesh, | mesh->attributes.remove(ATTR_STD_GENERATED); | ||||
| nverts, | } | ||||
| face_flags, | |||||
| need_sign, | |||||
| true); | |||||
| } | } | ||||
| } | } | ||||
| /* Create vertex pointiness attributes. */ | /* Create vertex pointiness attributes. */ | ||||
| /* Compare vertices by sum of their coordinates. */ | /* Compare vertices by sum of their coordinates. */ | ||||
| class VertexAverageComparator { | class VertexAverageComparator { | ||||
| public: | public: | ||||
| ▲ Show 20 Lines • Show All 221 Lines • ▼ Show 20 Lines | static void create_mesh(Scene *scene, | ||||
| Attribute *attr_N = attributes.add(ATTR_STD_VERTEX_NORMAL); | Attribute *attr_N = attributes.add(ATTR_STD_VERTEX_NORMAL); | ||||
| float3 *N = attr_N->data_float3(); | float3 *N = attr_N->data_float3(); | ||||
| for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++N) | for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++N) | ||||
| *N = get_float3(v->normal()); | *N = get_float3(v->normal()); | ||||
| N = attr_N->data_float3(); | N = attr_N->data_float3(); | ||||
| /* create generated coordinates from undeformed coordinates */ | /* create generated coordinates from undeformed coordinates */ | ||||
| if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) { | const bool need_default_tangent = | ||||
| (subdivision == false) && | |||||
| (b_mesh.tessface_uv_textures.length() == 0) && | |||||
| (mesh->need_attribute(scene, ATTR_STD_UV_TANGENT)); | |||||
| if(mesh->need_attribute(scene, ATTR_STD_GENERATED) || | |||||
| need_default_tangent) | |||||
| { | |||||
| Attribute *attr = attributes.add(ATTR_STD_GENERATED); | Attribute *attr = attributes.add(ATTR_STD_GENERATED); | ||||
| attr->flags |= ATTR_SUBDIVIDED; | attr->flags |= ATTR_SUBDIVIDED; | ||||
| float3 loc, size; | float3 loc, size; | ||||
| mesh_texture_space(b_mesh, loc, size); | mesh_texture_space(b_mesh, loc, size); | ||||
| float3 *generated = attr->data_float3(); | float3 *generated = attr->data_float3(); | ||||
| size_t i = 0; | size_t i = 0; | ||||
| for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v) | for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v) { | ||||
| generated[i++] = get_float3(v->undeformed_co())*size - loc; | generated[i++] = get_float3(v->undeformed_co())*size - loc; | ||||
| } | } | ||||
| } | |||||
| /* create faces */ | /* create faces */ | ||||
| vector<int> nverts(numfaces); | vector<int> nverts(numfaces); | ||||
| vector<int> face_flags(numfaces, FACE_FLAG_NONE); | vector<int> face_flags(numfaces, FACE_FLAG_NONE); | ||||
| int fi = 0; | int fi = 0; | ||||
| if(!subdivision) { | if(!subdivision) { | ||||
| for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f, ++fi) { | for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f, ++fi) { | ||||
| ▲ Show 20 Lines • Show All 529 Lines • Show Last 20 Lines | |||||