void OBJ_GenerateLightingInfo(obj_t* obj) { vec3_t v1,v2 ; int i; vec2_t st1,st2; float coef; vec3_t currentTangent; vec3_t currentNormal; vec3_t* tangents; vec3_t* normals; tangents = (vec3_t*)calloc(obj->num_vertices, sizeof(vec3_t)); normals = (vec3_t*)calloc(obj->num_vertices, sizeof(vec3_t)); //Accumulate tangents & normals for(i=0;i<obj->num_indices/3;i++) { vectorSubtract(obj->vertices[obj->indices[i*3+2]].position , obj->vertices[obj->indices[i*3]].position, v1); vectorSubtract(obj->vertices[obj->indices[i*3+1]].position , obj->vertices[obj->indices[i*3]].position, v2); vector2Subtract(obj->vertices[obj->indices[i*3+2]].textCoo,obj->vertices[obj->indices[i*3]].textCoo,st1); vector2Subtract(obj->vertices[obj->indices[i*3+1]].textCoo,obj->vertices[obj->indices[i*3]].textCoo,st2); //Normal part vectorCrossProduct(v2, v1, currentNormal); vectorAdd(normals[obj->indices[i*3+0]],currentNormal,normals[obj->indices[i*3+0]]); vectorAdd(normals[obj->indices[i*3+1]],currentNormal,normals[obj->indices[i*3+1]]); vectorAdd(normals[obj->indices[i*3+2]],currentNormal,normals[obj->indices[i*3+2]]); //Tangent part coef = 1/ (st1[0] * st2[1] - st2[0] * st1[1]); currentTangent[0] = coef * (v1[0] * st2[1] + v2[0] * -st1[1]); currentTangent[1] = coef * (v1[1] * st2[1] + v2[1] * -st1[1]); currentTangent[2] = coef * (v1[2] * st2[1] + v2[2] * -st1[1]); vectorAdd(tangents[obj->indices[i*3+0]],currentTangent,tangents[obj->indices[i*3+0]]); vectorAdd(tangents[obj->indices[i*3+1]],currentTangent,tangents[obj->indices[i*3+1]]); vectorAdd(tangents[obj->indices[i*3+2]],currentTangent,tangents[obj->indices[i*3+2]]); } //Vector Normalize + Normalize for(i=0;i<obj->num_vertices;i++) { normalize(tangents[i]); vectorScale(tangents[i],DE_SHRT_MAX,obj->vertices[i].tangent); normalize(normals[i]); vectorScale(normals[i],DE_SHRT_MAX,obj->vertices[i].normal); } free(tangents); free(normals); }
void MD5_GenerateLightingInfo (md5_mesh_t* mesh) { int verticesCounter; int weightCounter; //User for tangent space generation vec3_t v1,v2,normal; vec3_t* normalAccumulator; vec3_t* normalWeightAccumulator; vec3_t tangent; float coef; vec3_t jointSpaceTangent; vec2_t st1,st2; vec3_t* tangentAccumulator; vec3_t* tangentWeightAccumulator; vertex_t* currentVertex = NULL; md5_vertex_t* md5Vertex; int facesCounter; md5_weight_t* weight; md5_bone_t* bone; md5_triangle_t* currentFace; vec3_t jointSpaceNormal; normalAccumulator = calloc(mesh->numVertices, sizeof(vec3_t)); normalWeightAccumulator = calloc(mesh->numWeights, sizeof(vec3_t)); tangentAccumulator = calloc(mesh->numVertices, sizeof(vec3_t)); tangentWeightAccumulator= calloc(mesh->numWeights, sizeof(vec3_t)); //printf("\nGenerating normal and tangents.\n"); //Generate the normal and tangent per face currentFace = mesh->triangles; for(facesCounter = 0; facesCounter < mesh->numTriangles ; facesCounter++,currentFace++) { // Normal part vectorSubtract(mesh->vertexArray[currentFace->index[2]].pos , mesh->vertexArray[currentFace->index[0]].pos, v1); vectorSubtract(mesh->vertexArray[currentFace->index[1]].pos , mesh->vertexArray[currentFace->index[0]].pos, v2); vectorCrossProduct(v2,v1,normal); normalize(normal); vectorAdd(normalAccumulator[currentFace->index[0]],normal,normalAccumulator[currentFace->index[0]]); vectorAdd(normalAccumulator[currentFace->index[1]],normal,normalAccumulator[currentFace->index[1]]); vectorAdd(normalAccumulator[currentFace->index[2]],normal,normalAccumulator[currentFace->index[2]]); // The following part is from "Mathematic for 3D programming" by Eric Lengyel // Tangent part vector2Subtract(mesh->vertexArray[currentFace->index[2]].text,mesh->vertexArray[currentFace->index[0]].text,st1); vector2Subtract(mesh->vertexArray[currentFace->index[1]].text,mesh->vertexArray[currentFace->index[0]].text,st2); vector2Scale(st1,1/(float)32767,st1); vector2Scale(st2,1/(float)32767,st2); if (st1[0] == 0.0f && st2[0] == 0.0f) { st1[0] = 0.1f ; st2[0] = 0.1f; } if (st1[1] == 0.0f && st2[1] == 0.0f) { st1[1] = 0.1f ; st2[1] = 0.1f; } coef = 1/ (st1[0] * st2[1] - st2[0] * st1[1]); tangent[0] = coef * (v1[0] * st2[1] + v2[0] * -st1[1]); tangent[1] = coef * (v1[1] * st2[1] + v2[1] * -st1[1]); tangent[2] = coef * (v1[2] * st2[1] + v2[2] * -st1[1]); normalize(tangent); vectorAdd(tangentAccumulator[currentFace->index[0]],tangent,tangentAccumulator[currentFace->index[0]]); vectorAdd(tangentAccumulator[currentFace->index[1]],tangent,tangentAccumulator[currentFace->index[1]]); vectorAdd(tangentAccumulator[currentFace->index[2]],tangent,tangentAccumulator[currentFace->index[2]]); } //Normalize accumulated normal and tangent for(verticesCounter=0 ; verticesCounter < mesh->numVertices ; verticesCounter++,currentVertex++) { normalize(normalAccumulator[verticesCounter]); // printf("normalized accumulated normal [%d][%.2f,%.2f,%.2f]\n",verticesCounter,normalAccumulator[verticesCounter][0],normalAccumulator[verticesCounter][1],normalAccumulator[verticesCounter][2]); normalize(tangentAccumulator[verticesCounter]); // printf("normalized accumulated tangent [%d][%.2f,%.2f,%.2f]\n",verticesCounter,tangentAccumulator[verticesCounter][0],tangentAccumulator[verticesCounter][1],tangentAccumulator[verticesCounter][2]); } //Now we have all the normal for this model, but need to transform them in bone space for re-usage // Translating the normal orientation from object to joint space and Store normals inside weights, md5Vertex = mesh->vertices; currentVertex = mesh->vertexArray; for(verticesCounter=0 ; verticesCounter < mesh->numVertices ; verticesCounter++,md5Vertex++) { for (weightCounter = 0; weightCounter < md5Vertex->count; weightCounter++) { weight = &mesh->weights[md5Vertex->start + weightCounter]; bone = &mesh->bones[weight->boneId]; multiplyByInvertQuaternion(normalAccumulator[verticesCounter],bone->orientation,jointSpaceNormal); vectorAdd(normalWeightAccumulator[md5Vertex->start + weightCounter],jointSpaceNormal,normalWeightAccumulator[md5Vertex->start + weightCounter]); multiplyByInvertQuaternion(tangentAccumulator[verticesCounter],bone->orientation,jointSpaceTangent); vectorAdd(tangentWeightAccumulator[md5Vertex->start + weightCounter],jointSpaceTangent,tangentWeightAccumulator[md5Vertex->start + weightCounter]); } } weight = mesh->weights; for (weightCounter = 0; weightCounter < mesh->numWeights; weightCounter++,weight++) { normalize(normalWeightAccumulator[weightCounter]); vectorScale(normalWeightAccumulator[weightCounter],32767,weight->boneSpaceNormal); normalize(tangentWeightAccumulator[weightCounter]); vectorScale(tangentWeightAccumulator[weightCounter],32767,weight->boneSpaceTangent); } free(normalAccumulator); free(normalWeightAccumulator); free(tangentAccumulator); free(tangentWeightAccumulator); }
void GenerateLightingInfo (const md5_mesh_t *mesh, md5_joint_t *skeleton) { int verticesCounter; int weightCounter; //User for tangent space generation vec3_t v1,v2,normal; vec3_t* normalAccumulator; vec3_t* normalWeightAccumulator; #ifdef TANGENT_ENABLED vec3_t tangent; float coef; vec3_t jointSpaceTangent; vec2_t st1,st2; vec3_t* tangentAccumulator; vec3_t* tangentWeightAccumulator; #endif vertex_t* currentVertex = NULL; md5_vertex_t* md5Vertex; int facesCounter; md5_weight_t* weight; md5_joint_t* joint; md5_triangle_t* currentFace; vec3_t jointSpaceNormal; normalAccumulator = calloc(mesh->num_verts, sizeof(vec3_t)); normalWeightAccumulator = calloc(mesh->num_weights, sizeof(vec3_t)); #ifdef TANGENT_ENABLED tangentAccumulator = calloc(mesh->num_verts, sizeof(vec3_t)); tangentWeightAccumulator = calloc(mesh->num_weights, sizeof(vec3_t)); #endif //Set all textures coordinate once for all. currentVertex = mesh->vertexArray; for(verticesCounter=0 ; verticesCounter < mesh->num_verts ; verticesCounter++,currentVertex++) { currentVertex->text[0] = mesh->vertices[verticesCounter].st[0]; currentVertex->text[1] = mesh->vertices[verticesCounter].st[1]; } currentFace = mesh->triangles; for(facesCounter = 0; facesCounter < mesh->num_tris ; facesCounter++,currentFace++) { // Normal part vectorSubtract(mesh->vertexArray[currentFace->index[2]].pos , mesh->vertexArray[currentFace->index[0]].pos, v1); vectorSubtract(mesh->vertexArray[currentFace->index[1]].pos , mesh->vertexArray[currentFace->index[0]].pos, v2); vectorCrossProduct(v2,v1,normal); vectorAdd(normalAccumulator[currentFace->index[0]],normal,normalAccumulator[currentFace->index[0]]); vectorAdd(normalAccumulator[currentFace->index[1]],normal,normalAccumulator[currentFace->index[1]]); vectorAdd(normalAccumulator[currentFace->index[2]],normal,normalAccumulator[currentFace->index[2]]); // The following part is from "Mathematic for 3D programming" by Eric Lengyel // Tangent part #ifdef TANGENT_ENABLED vector2Subtract(mesh->vertexArray[currentFace->index[2]].text,mesh->vertexArray[currentFace->index[0]].text,st1); vector2Subtract(mesh->vertexArray[currentFace->index[1]].text,mesh->vertexArray[currentFace->index[0]].text,st2); coef = 1/ (st1[0] * st2[1] - st2[0] * st1[1]); tangent[0] = coef * (v1[0] * st2[1] + v2[0] * -st1[1]); tangent[1] = coef * (v1[1] * st2[1] + v2[1] * -st1[1]); tangent[2] = coef * (v1[2] * st2[1] + v2[2] * -st1[1]); vectorAdd(tangentAccumulator[currentFace->index[0]],tangent,tangentAccumulator[currentFace->index[0]]); vectorAdd(tangentAccumulator[currentFace->index[1]],tangent,tangentAccumulator[currentFace->index[1]]); vectorAdd(tangentAccumulator[currentFace->index[2]],tangent,tangentAccumulator[currentFace->index[2]]); #endif } for(verticesCounter=0 ; verticesCounter < mesh->num_verts ; verticesCounter++,currentVertex++) { normalize(normalAccumulator[verticesCounter]); #ifdef TANGENT_ENABLED normalize(tangentAccumulator[verticesCounter]); #endif } //Now we have all the normal for this model, but need to transform them in bone space for re-usage // Translating the normal orientation from object to joint space and Store normals inside weights, md5Vertex = mesh->vertices; currentVertex = mesh->vertexArray; for(verticesCounter=0 ; verticesCounter < mesh->num_verts ; verticesCounter++,md5Vertex++) { for (weightCounter = 0; weightCounter < md5Vertex->count; weightCounter++) { weight = &mesh->weights[md5Vertex->start + weightCounter]; joint = &skeleton[weight->joint]; multiplyByInvertQuaternion(normalAccumulator[verticesCounter],joint->orient,jointSpaceNormal); vectorAdd(normalWeightAccumulator[md5Vertex->start + weightCounter],jointSpaceNormal,normalWeightAccumulator[md5Vertex->start + weightCounter]); #ifdef TANGENT_ENABLED multiplyByInvertQuaternion(tangentAccumulator[verticesCounter],joint->orient,jointSpaceTangent); vectorAdd(tangentWeightAccumulator[md5Vertex->start + weightCounter],jointSpaceTangent,tangentWeightAccumulator[md5Vertex->start + weightCounter]); #endif } } weight = mesh->weights; for (weightCounter = 0; weightCounter < mesh->num_weights; weightCounter++,weight++) { normalize(normalWeightAccumulator[weightCounter]); vectorScale(normalWeightAccumulator[weightCounter],32767,weight->normal); #ifdef TANGENT_ENABLED normalize(tangentWeightAccumulator[weightCounter]); vectorScale(tangentWeightAccumulator[weightCounter],32767,weight->tangent); #endif } free(normalAccumulator); free(normalWeightAccumulator); #ifdef TANGENT_ENABLED free(tangentAccumulator); free(tangentWeightAccumulator); #endif }