// Calculate T&B void OGF::CalculateTB() { u32 v_count_reserve = 3*iFloor(float(vertices.size())*1.33f); u32 i_count_reserve = 3*faces.size(); // Declare inputs xr_vector<NVMeshMender::VertexAttribute> input; input.push_back (NVMeshMender::VertexAttribute()); // pos input.push_back (NVMeshMender::VertexAttribute()); // norm input.push_back (NVMeshMender::VertexAttribute()); // tex0 input.push_back (NVMeshMender::VertexAttribute()); // color input.push_back (NVMeshMender::VertexAttribute()); // *** faces input[0].Name_= "position"; xr_vector<float>& i_position = input[0].floatVector_; i_position.reserve (v_count_reserve); input[1].Name_= "normal"; xr_vector<float>& i_normal = input[1].floatVector_; i_normal.reserve (v_count_reserve); input[2].Name_= "tex0"; xr_vector<float>& i_tc = input[2].floatVector_; i_tc.reserve (v_count_reserve); input[3].Name_= "clr"; xr_vector<float>& i_color = input[3].floatVector_; i_normal.reserve (v_count_reserve); input[4].Name_= "indices"; xr_vector<int>& i_indices = input[4].intVector_; i_indices.reserve (i_count_reserve); // Declare outputs xr_vector<NVMeshMender::VertexAttribute> output; output.push_back(NVMeshMender::VertexAttribute()); // position, needed for mender output.push_back(NVMeshMender::VertexAttribute()); // normal output.push_back(NVMeshMender::VertexAttribute()); // tangent output.push_back(NVMeshMender::VertexAttribute()); // binormal output.push_back(NVMeshMender::VertexAttribute()); // tex0 output.push_back(NVMeshMender::VertexAttribute()); // color output.push_back(NVMeshMender::VertexAttribute()); // *** faces output[0].Name_= "position"; output[1].Name_= "normal"; output[2].Name_= "tangent"; output[3].Name_= "binormal"; output[4].Name_= "tex0"; output[5].Name_= "clr"; output[6].Name_= "indices"; // fill inputs (verts&indices) for (itOGF_V vert_it=vertices.begin(); vert_it!=vertices.end(); vert_it++){ OGF_Vertex &iV = *vert_it; i_position.push_back(iV.P.x); i_position.push_back(iV.P.y); i_position.push_back(iV.P.z); i_normal.push_back (iV.N.x); i_normal.push_back (iV.N.y); i_normal.push_back (iV.N.z); i_color.push_back (iV.Color._x); i_color.push_back (iV.Color._y); i_color.push_back (iV.Color._z); i_tc.push_back (iV.UV[0].x); i_tc.push_back (iV.UV[0].y); i_tc.push_back (0); } for (itOGF_F face_it=faces.begin(); face_it!=faces.end(); face_it++){ OGF_Face &iF = *face_it; i_indices.push_back (iF.v[0]); i_indices.push_back (iF.v[1]); i_indices.push_back (iF.v[2]); } // Perform munge NVMeshMender mender; if (!mender.Munge( input, // input attributes output, // outputs attributes deg2rad(75.f), // tangent space smooth angle 0, // no texture matrix applied to my texture coordinates NVMeshMender::FixTangents, // fix degenerate bases & texture mirroring NVMeshMender::DontFixCylindricalTexGen, // handle cylindrically mapped textures via vertex duplication NVMeshMender::DontWeightNormalsByFaceSize // weigh vertex normals by the triangle's size )) { Debug.fatal (DEBUG_INFO,"NVMeshMender failed (%s)",mender.GetLastError().c_str()); } // Bind declarators xr_vector<float>& o_position = output[0].floatVector_; R_ASSERT(output[0].Name_=="position"); xr_vector<float>& o_normal = output[1].floatVector_; R_ASSERT(output[1].Name_=="normal"); xr_vector<float>& o_tangent = output[2].floatVector_; R_ASSERT(output[2].Name_=="tangent"); xr_vector<float>& o_binormal = output[3].floatVector_; R_ASSERT(output[3].Name_=="binormal"); xr_vector<float>& o_tc = output[4].floatVector_; R_ASSERT(output[4].Name_=="tex0"); xr_vector<float>& o_color = output[5].floatVector_; R_ASSERT(output[5].Name_=="clr"); xr_vector<int>& o_indices = output[6].intVector_; R_ASSERT(output[6].Name_=="indices"); // verify R_ASSERT (3*faces.size() == o_indices.size()); u32 v_cnt = o_position.size(); R_ASSERT (0==v_cnt%3); R_ASSERT (v_cnt == o_normal.size()); R_ASSERT (v_cnt == o_tangent.size()); R_ASSERT (v_cnt == o_binormal.size()); R_ASSERT (v_cnt == o_tc.size()); R_ASSERT (v_cnt == o_color.size()); v_cnt /= 3; // retriving data u32 o_idx = 0; for (face_it=faces.begin(); face_it!=faces.end(); face_it++){ OGF_Face &iF = *face_it; iF.v[0] = o_indices[o_idx++]; iF.v[1] = o_indices[o_idx++]; iF.v[2] = o_indices[o_idx++]; } vertices.clear (); vertices.resize(v_cnt); for (u32 v_idx=0; v_idx!=v_cnt; v_idx++){ OGF_Vertex &iV = vertices[v_idx]; iV.P.set (o_position[v_idx*3+0], o_position[v_idx*3+1], o_position[v_idx*3+2]); iV.N.set (o_normal[v_idx*3+0], o_normal[v_idx*3+1], o_normal[v_idx*3+2]); iV.T.set (o_tangent[v_idx*3+0], o_tangent[v_idx*3+1], o_tangent[v_idx*3+2]); iV.B.set (o_binormal[v_idx*3+0], o_binormal[v_idx*3+1], o_binormal[v_idx*3+2]); iV.UV.resize(1); iV.UV[0].set(o_tc[v_idx*3+0], o_tc[v_idx*3+1]); iV.Color._set(o_color[v_idx*3+0], o_color[v_idx*3+1], o_color[v_idx*3+2]); } }
// Calculate T&B void OGF::CalculateTB() { u32 v_count_reserve = 3*iFloor(float(data.vertices.size())*1.33f); u32 i_count_reserve = 3*data.faces.size(); // Declare inputs xr_vector<NVMeshMender::VertexAttribute> input; input.push_back (NVMeshMender::VertexAttribute()); // pos input.push_back (NVMeshMender::VertexAttribute()); // norm input.push_back (NVMeshMender::VertexAttribute()); // tex0 input.push_back (NVMeshMender::VertexAttribute()); // color input.push_back (NVMeshMender::VertexAttribute()); // *** faces input[0].Name_= "position"; xr_vector<float>& i_position = input[0].floatVector_; i_position.reserve (v_count_reserve); input[1].Name_= "normal"; xr_vector<float>& i_normal = input[1].floatVector_; i_normal.reserve (v_count_reserve); input[2].Name_= "tex0"; xr_vector<float>& i_tc = input[2].floatVector_; i_tc.reserve (v_count_reserve); input[3].Name_= "clr"; xr_vector<float>& i_color = input[3].floatVector_; i_normal.reserve (v_count_reserve); input[4].Name_= "indices"; xr_vector<int>& i_indices = input[4].intVector_; i_indices.reserve (i_count_reserve); // Declare outputs xr_vector<NVMeshMender::VertexAttribute> output; output.push_back(NVMeshMender::VertexAttribute()); // position, needed for mender output.push_back(NVMeshMender::VertexAttribute()); // normal output.push_back(NVMeshMender::VertexAttribute()); // tangent output.push_back(NVMeshMender::VertexAttribute()); // binormal output.push_back(NVMeshMender::VertexAttribute()); // tex0 output.push_back(NVMeshMender::VertexAttribute()); // color output.push_back(NVMeshMender::VertexAttribute()); // *** faces output[0].Name_= "position"; output[1].Name_= "normal"; output[2].Name_= "tangent"; output[3].Name_= "binormal"; output[4].Name_= "tex0"; output[5].Name_= "clr"; output[6].Name_= "indices"; fill_mender_input( data.vertices, data.faces, i_position, i_normal, i_tc, i_color, i_indices ); // Perform munge NVMeshMender mender; if (!mender.Munge( input, // input attributes output, // outputs attributes deg2rad(75.f), // tangent space smooth angle 0, // no texture matrix applied to my texture coordinates NVMeshMender::FixTangents, // fix degenerate bases & texture mirroring NVMeshMender::DontFixCylindricalTexGen, // handle cylindrically mapped textures via vertex duplication NVMeshMender::DontWeightNormalsByFaceSize // weigh vertex normals by the triangle's size )) { xrDebug::Fatal (DEBUG_INFO,"NVMeshMender failed (%s)",mender.GetLastError().c_str()); } // Bind declarators xr_vector<float>& o_position = output[0].floatVector_; R_ASSERT(output[0].Name_=="position"); xr_vector<float>& o_normal = output[1].floatVector_; R_ASSERT(output[1].Name_=="normal"); xr_vector<float>& o_tangent = output[2].floatVector_; R_ASSERT(output[2].Name_=="tangent"); xr_vector<float>& o_binormal = output[3].floatVector_; R_ASSERT(output[3].Name_=="binormal"); xr_vector<float>& o_tc = output[4].floatVector_; R_ASSERT(output[4].Name_=="tex0"); xr_vector<float>& o_color = output[5].floatVector_; R_ASSERT(output[5].Name_=="clr"); xr_vector<int>& o_indices = output[6].intVector_; R_ASSERT(output[6].Name_=="indices"); // verify R_ASSERT (3*data.faces.size() == o_indices.size()); u32 v_cnt = o_position.size(); R_ASSERT (0==v_cnt%3); R_ASSERT (v_cnt == o_normal.size()); R_ASSERT (v_cnt == o_tangent.size()); R_ASSERT (v_cnt == o_binormal.size()); R_ASSERT (v_cnt == o_tc.size()); R_ASSERT (v_cnt == o_color.size()); retrive_data_from_mender_otput( data.vertices, data.faces, o_position, o_normal, o_tc, o_tangent, o_binormal, o_color, o_indices ); }
//---------------------------------------------------------------------------------- bool Helper_ComputeTBN(m_mesh & msh) { NVMeshMender aMender; // compute tangents and binormals std::vector<float> vpos; std::vector<int> triIndices; std::vector<float> vnor; std::vector<float> texCoords; for (size_t k = 0; k < msh.num_vertices; ++k) { Vector v(msh.vertices[k].x,msh.vertices[k].y,msh.vertices[k].z); Vector n(msh.normals[k].x,msh.normals[k].y,msh.normals[k].z); vpos.push_back(v.x); vpos.push_back(v.y); vpos.push_back(v.z); vnor.push_back(n.x); vnor.push_back(n.y); vnor.push_back(n.z); } for (size_t k = 0; k < msh.num_faces * 3; ++k) { triIndices.push_back(msh.faces_idx[k]); } for (size_t k = 0; k < msh.num_texcoord_sets; ++k) { texCoords.clear(); for (size_t l = 0; l < msh.num_vertices; ++l) { texCoords.push_back(msh.texcoord_sets[k].texcoords[l*2]); texCoords.push_back(msh.texcoord_sets[k].texcoords[l*2+1]); texCoords.push_back(m_zero); } std::vector<NVMeshMender::VertexAttribute> inputAtts;// What you have std::vector<NVMeshMender::VertexAttribute> outputAtts;// What you want. NVMeshMender::VertexAttribute posAtt; posAtt.Name_ = "position"; posAtt.floatVector_ = vpos; NVMeshMender::VertexAttribute triIndAtt; triIndAtt.Name_ = "indices"; triIndAtt.intVector_ = triIndices; NVMeshMender::VertexAttribute norAtt; norAtt.Name_ = "normal"; norAtt.floatVector_ = vnor; NVMeshMender::VertexAttribute texCoordAtt; texCoordAtt.Name_ = "tex0"; texCoordAtt.floatVector_ = texCoords; NVMeshMender::VertexAttribute tgtSpaceAtt; tgtSpaceAtt.Name_ = "tangent"; NVMeshMender::VertexAttribute binormalAtt; binormalAtt.Name_ = "binormal"; inputAtts.push_back(posAtt); inputAtts.push_back(triIndAtt); inputAtts.push_back(norAtt); inputAtts.push_back(texCoordAtt); outputAtts.push_back(posAtt); outputAtts.push_back(triIndAtt); outputAtts.push_back(norAtt); outputAtts.push_back(texCoordAtt); outputAtts.push_back(tgtSpaceAtt); outputAtts.push_back(binormalAtt); bool bSuccess = aMender.Munge( inputAtts, // these are my positions & indices outputAtts, // these are the outputs I requested, plus extra stuff generated on my behalf m_two_pi / (6.0f), // tangent space smooth angle NULL, // no Texture matrix applied to my tex0 coords NVMeshMender::DontFixTangents, // fix degenerate bases & texture mirroring NVMeshMender::DontFixCylindricalTexGen, // handle cylidrically mapped textures via vertex duplication NVMeshMender::DontWeightNormalsByFaceSize // weight vertex normals by the triangle's size ); if (bSuccess) { msh.texcoord_sets[k].binormals = new Vector[msh.num_vertices]; msh.texcoord_sets[k].tangents = new Vector[msh.num_vertices]; for (size_t l = 0; l < msh.num_vertices; ++l) { msh.texcoord_sets[k].tangents[l].x = outputAtts[4].floatVector_[l * 3]; msh.texcoord_sets[k].tangents[l].y = outputAtts[4].floatVector_[l * 3 + 1]; msh.texcoord_sets[k].tangents[l].z = outputAtts[4].floatVector_[l * 3 + 2]; msh.texcoord_sets[k].binormals[l].x = outputAtts[5].floatVector_[l * 3]; msh.texcoord_sets[k].binormals[l].y = outputAtts[5].floatVector_[l * 3 + 1]; msh.texcoord_sets[k].binormals[l].z = outputAtts[5].floatVector_[l * 3 + 2]; } } } return true; }