mirror of
https://port.numenaute.org/aleajactaest/khanat-opennel-code.git
synced 2024-11-14 11:19:07 +00:00
9bc219ee14
About Shared Library (shared) and Module Library (module) type of cmake target INSTALL command has different behaviour for ARCHIVE LIBRARY RUNTIME depending on the platform
674 lines
No EOL
18 KiB
C++
674 lines
No EOL
18 KiB
C++
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
|
|
// Copyright (C) 2010 Winch Gate Property Limited
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as
|
|
// published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
#include <nel/misc/file.h>
|
|
#include <nel/3d/mesh.h>
|
|
#include <nel/3d/mesh_mrm.h>
|
|
#include <nel/3d/mesh_mrm_skinned.h>
|
|
#include <nel/3d/scene.h>
|
|
#include <nel/3d/register_3d.h>
|
|
#include <nel/misc/app_context.h>
|
|
#include <nel/misc/o_xml.h>
|
|
#include <nel/misc/i_xml.h>
|
|
|
|
#include <fstream>
|
|
#include <iostream>
|
|
|
|
using namespace NLMISC;
|
|
using namespace NL3D;
|
|
using namespace std;
|
|
|
|
struct CVertex
|
|
{
|
|
CVector vertex;
|
|
CVector normal;
|
|
CUV uv;
|
|
};
|
|
|
|
bool operator == (const CVertex &v1, const CVertex &v2)
|
|
{
|
|
return (v1.vertex == v2.vertex) && (v1.normal == v2.normal) && (v1.uv == v2.uv);
|
|
}
|
|
|
|
bool operator < (const CVertex &v1, const CVertex &v2)
|
|
{
|
|
return (v1.vertex < v2.vertex);
|
|
}
|
|
|
|
const CIndexBuffer *getRdrPassPrimitiveBlock(const CMeshMRMGeom *mesh, uint lodId, uint renderPass)
|
|
{
|
|
return &(mesh->getRdrPassPrimitiveBlock(lodId, renderPass));
|
|
}
|
|
|
|
// ***************************************************************************
|
|
|
|
const CIndexBuffer *getRdrPassPrimitiveBlock(const CMeshMRMSkinnedGeom *mesh, uint lodId, uint renderPass)
|
|
{
|
|
static CIndexBuffer block;
|
|
mesh->getRdrPassPrimitiveBlock(lodId, renderPass, block);
|
|
return █
|
|
}
|
|
|
|
// ***************************************************************************
|
|
|
|
bool ProcessMeshMRMSkinned(const std::string &filename, IShape *shapeMesh);
|
|
bool ProcessMeshMRM(const std::string &filename, IShape *shapeMesh);
|
|
//bool ProcessMesh(const std::string &filename, IShape *shapeMesh);
|
|
|
|
int main(int argc, char* argv[])
|
|
{
|
|
if (argc < 2)
|
|
{
|
|
cout << "Syntax : shape2obj <NeL .shape file>" << endl;
|
|
|
|
return 1;
|
|
}
|
|
|
|
if (!NLMISC::INelContext::isContextInitialised()) new NLMISC::CApplicationContext();
|
|
|
|
registerSerial3d();
|
|
CScene::registerBasics();
|
|
|
|
IShape *shapeMesh = NULL;
|
|
|
|
CIFile ifile;
|
|
|
|
// Sream a shape
|
|
CShapeStream streamShape;
|
|
|
|
string filename = argv[1];
|
|
|
|
if (!ifile.open(filename)) return 1;
|
|
|
|
try
|
|
{
|
|
// Stream it
|
|
streamShape.serial(ifile);
|
|
|
|
// Add the shape
|
|
shapeMesh = streamShape.getShapePointer();
|
|
}
|
|
catch (Exception& e)
|
|
{
|
|
cout << "Error : " << e.what() << endl;
|
|
|
|
return 1;
|
|
}
|
|
|
|
if (ProcessMeshMRMSkinned(filename, shapeMesh)) return 0;
|
|
if (ProcessMeshMRM(filename, shapeMesh)) return 0;
|
|
// if (ProcessMesh(filename, shapeMesh)) return 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool ProcessMeshMRMSkinned(const std::string &filename, IShape *shapeMesh)
|
|
{
|
|
CMeshMRMSkinned *mesh = dynamic_cast<CMeshMRMSkinned*>(shapeMesh);
|
|
|
|
if (!mesh) return false;
|
|
|
|
COFile ofile;
|
|
|
|
CMeshMRMSkinnedGeom* meshIn = (CMeshMRMSkinnedGeom*)&mesh->getMeshGeom();
|
|
|
|
std::vector<CMesh::CSkinWeight> skinWeights;
|
|
meshIn->getSkinWeights(skinWeights);
|
|
CVertexBuffer vertexBuffer;
|
|
meshIn->getVertexBuffer(vertexBuffer);
|
|
|
|
CVertexBufferRead vba;
|
|
vertexBuffer.lock (vba);
|
|
uint i, j;
|
|
|
|
// **** Select the Lod.
|
|
uint numLods= meshIn->getNbLod();
|
|
|
|
// get the max tris displayed
|
|
float numMeshFacesMin= (float)meshIn->getLevelDetail().MinFaceUsed;
|
|
float numMeshFacesMax= (float)meshIn->getLevelDetail().MaxFaceUsed;
|
|
// find the lod
|
|
sint lodId = numLods-1;
|
|
|
|
// **** First, for the best lod indicate what vertex is used or not. Also index geomorphs to know what real vertex is used
|
|
vector<sint> vertexUsed;
|
|
// -1 means "not used"
|
|
vertexUsed.resize(skinWeights.size(), -1);
|
|
// Parse all triangles.
|
|
for(i=0;i<meshIn->getNbRdrPass(lodId); ++i)
|
|
{
|
|
const CIndexBuffer *pb = getRdrPassPrimitiveBlock(meshIn, lodId, i);
|
|
CIndexBufferRead iba;
|
|
pb->lock (iba);
|
|
if (iba.getFormat() == CIndexBuffer::Indices32)
|
|
{
|
|
const uint32 *triPtr= (const uint32 *) iba.getPtr();
|
|
for(j=0;j<pb->getNumIndexes(); ++j)
|
|
{
|
|
uint idx= *triPtr;
|
|
// Flag the vertex with its own index => used.
|
|
vertexUsed[idx]= idx;
|
|
triPtr++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const uint16 *triPtr= (const uint16 *) iba.getPtr();
|
|
for(j=0;j<pb->getNumIndexes(); ++j)
|
|
{
|
|
uint idx= *triPtr;
|
|
// Flag the vertex with its own index => used.
|
|
vertexUsed[idx]= idx;
|
|
triPtr++;
|
|
}
|
|
}
|
|
}
|
|
// Special for Geomorphs: must take The End target vertex.
|
|
const std::vector<CMRMWedgeGeom> &geomorphs= meshIn->getGeomorphs(lodId);
|
|
for(i=0;i<geomorphs.size(); ++i)
|
|
{
|
|
uint trueIdx= geomorphs[i].End;
|
|
// map to the Geomorph Target.
|
|
vertexUsed[i]= trueIdx;
|
|
// mark also the real vertex used as used.
|
|
vertexUsed[trueIdx]= trueIdx;
|
|
}
|
|
|
|
|
|
// **** For all vertices used (not geomorphs), compute vertex Skins.
|
|
vector<CVertex> shadowVertices;
|
|
vector<sint> vertexToVSkin;
|
|
vertexToVSkin.resize(vertexUsed.size());
|
|
shadowVertices.reserve(vertexUsed.size());
|
|
// use a map to remove duplicates (because of UV/normal discontinuities before!!)
|
|
map<CVertex, uint> shadowVertexMap;
|
|
uint numMerged= 0;
|
|
// Skip Geomorphs.
|
|
for(i=geomorphs.size();i<vertexUsed.size(); ++i)
|
|
{
|
|
// If this vertex is used.
|
|
if(vertexUsed[i]!=-1)
|
|
{
|
|
// Build the vertex
|
|
CVertex shadowVert;
|
|
CUV uv;
|
|
shadowVert.vertex = *(CVector*)vba.getVertexCoordPointer(i);
|
|
shadowVert.normal = *(CVector*)vba.getNormalCoordPointer(i);
|
|
shadowVert.uv = *(CUV*)vba.getTexCoordPointer(i);
|
|
/*
|
|
// Select the best Matrix.
|
|
CMesh::CSkinWeight sw= skinWeights[i];
|
|
float maxW= 0;
|
|
uint matId= 0;
|
|
for(j=0;j<NL3D_MESH_SKINNING_MAX_MATRIX;j++)
|
|
{
|
|
// if no more matrix influenced, stop
|
|
if(sw.Weights[j]==0)
|
|
break;
|
|
if(sw.Weights[j]>maxW)
|
|
{
|
|
matId= sw.MatrixId[j];
|
|
maxW= sw.Weights[j];
|
|
}
|
|
}
|
|
// shadowVert.MatrixId= matId;
|
|
*/
|
|
// If dont find the shadowVertex in the map.
|
|
map<CVertex, uint>::iterator it= shadowVertexMap.find(shadowVert);
|
|
if(it==shadowVertexMap.end())
|
|
{
|
|
// Append
|
|
uint index= shadowVertices.size();
|
|
vertexToVSkin[i]= index;
|
|
shadowVertices.push_back(shadowVert);
|
|
shadowVertexMap.insert(make_pair(shadowVert, index));
|
|
}
|
|
else
|
|
{
|
|
// Ok, map.
|
|
vertexToVSkin[i]= it->second;
|
|
numMerged++;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
ofstream ofs(string(filename + ".obj").c_str());
|
|
|
|
for(size_t y = 0; y < shadowVertices.size(); ++y)
|
|
{
|
|
CVector v = shadowVertices[y].vertex;
|
|
CVector vn = shadowVertices[y].normal;
|
|
CUV vt = shadowVertices[y].uv;
|
|
|
|
ofs << "v " << v.x << " " << v.y << " " << v.z << endl;
|
|
ofs << "vn " << vn.x << " " << vn.y << " " << vn.z << endl;
|
|
ofs << "vt " << vt.U << " " << vt.V << endl;
|
|
}
|
|
|
|
// **** Get All Faces
|
|
// Final List Of Triangles that match the bone.
|
|
vector<uint32> shadowTriangles;
|
|
shadowTriangles.reserve(1000);
|
|
// Parse all input tri of the mesh.
|
|
for(i=0; i<meshIn->getNbRdrPass(lodId); ++i)
|
|
{
|
|
ofs << "g pass" << i << endl;
|
|
|
|
const CIndexBuffer *pb = getRdrPassPrimitiveBlock(meshIn, lodId, i);
|
|
CIndexBufferRead iba;
|
|
pb->lock (iba);
|
|
if (iba.getFormat() == CIndexBuffer::Indices32)
|
|
{
|
|
const uint32 *triPtr= (const uint32 *) iba.getPtr();
|
|
|
|
for(j=0; j<pb->getNumIndexes(); ++j)
|
|
{
|
|
uint idx= *triPtr;
|
|
// Get the real Vertex (ie not the geomporhed one).
|
|
idx= vertexUsed[idx];
|
|
// Get the ShadowVertex associated
|
|
idx= vertexToVSkin[idx];
|
|
|
|
shadowTriangles.push_back(idx);
|
|
triPtr++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const uint16 *triPtr= (const uint16 *) iba.getPtr();
|
|
for(j=0; j<pb->getNumIndexes(); ++j)
|
|
{
|
|
uint idx= *triPtr;
|
|
// Get the real Vertex (ie not the geomporhed one).
|
|
idx= vertexUsed[idx];
|
|
// Get the ShadowVertex associated
|
|
idx= vertexToVSkin[idx];
|
|
|
|
shadowTriangles.push_back(idx);
|
|
triPtr++;
|
|
}
|
|
}
|
|
|
|
for(size_t pass = 0; pass<shadowTriangles.size(); pass += 3)
|
|
{
|
|
ofs << "f " << shadowTriangles[pass]+1 << "/" << shadowTriangles[pass]+1 << "/" << shadowTriangles[pass]+1 << " ";
|
|
ofs << shadowTriangles[pass+1]+1 << "/" << shadowTriangles[pass+1]+1 << "/" << shadowTriangles[pass+1]+1 << " ";
|
|
ofs << shadowTriangles[pass+2]+1 << "/" << shadowTriangles[pass+2]+1 << "/" << shadowTriangles[pass+2]+1 << endl;
|
|
}
|
|
|
|
shadowTriangles.clear();
|
|
}
|
|
|
|
ofs.close();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ProcessMeshMRM(const std::string &filename, IShape *shapeMesh)
|
|
{
|
|
CMeshMRM *mesh = dynamic_cast<CMeshMRM*>(shapeMesh);
|
|
|
|
if (!mesh) return false;
|
|
|
|
COFile ofile;
|
|
|
|
CMeshMRMGeom* meshIn = (CMeshMRMGeom*)&mesh->getMeshGeom();
|
|
|
|
std::vector<CMesh::CSkinWeight> skinWeights = meshIn->getSkinWeights();
|
|
CVertexBuffer vertexBuffer = meshIn->getVertexBuffer();
|
|
|
|
CVertexBufferRead vba;
|
|
vertexBuffer.lock (vba);
|
|
uint i, j;
|
|
|
|
// **** Select the Lod.
|
|
uint numLods= meshIn->getNbLod();
|
|
|
|
// get the max tris displayed
|
|
float numMeshFacesMin= (float)meshIn->getLevelDetail().MinFaceUsed;
|
|
float numMeshFacesMax= (float)meshIn->getLevelDetail().MaxFaceUsed;
|
|
// find the lod
|
|
sint lodId = numLods-1;
|
|
|
|
// **** First, for the best lod indicate what vertex is used or not. Also index geomorphs to know what real vertex is used
|
|
vector<sint> vertexUsed;
|
|
// -1 means "not used"
|
|
vertexUsed.resize(skinWeights.size(), -1);
|
|
// Parse all triangles.
|
|
for(i=0;i<meshIn->getNbRdrPass(lodId); ++i)
|
|
{
|
|
const CIndexBuffer *pb = getRdrPassPrimitiveBlock(meshIn, lodId, i);
|
|
CIndexBufferRead iba;
|
|
pb->lock (iba);
|
|
if (iba.getFormat() == CIndexBuffer::Indices32)
|
|
{
|
|
const uint32 *triPtr= (const uint32 *) iba.getPtr();
|
|
for(j=0;j<pb->getNumIndexes(); ++j)
|
|
{
|
|
uint idx= *triPtr;
|
|
// Flag the vertex with its own index => used.
|
|
vertexUsed[idx]= idx;
|
|
triPtr++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const uint16 *triPtr= (const uint16 *) iba.getPtr();
|
|
for(j=0;j<pb->getNumIndexes(); ++j)
|
|
{
|
|
uint idx= *triPtr;
|
|
// Flag the vertex with its own index => used.
|
|
vertexUsed[idx]= idx;
|
|
triPtr++;
|
|
}
|
|
}
|
|
}
|
|
// Special for Geomorphs: must take The End target vertex.
|
|
const std::vector<CMRMWedgeGeom> &geomorphs= meshIn->getGeomorphs(lodId);
|
|
for(i=0;i<geomorphs.size(); ++i)
|
|
{
|
|
uint trueIdx= geomorphs[i].End;
|
|
// map to the Geomorph Target.
|
|
vertexUsed[i]= trueIdx;
|
|
// mark also the real vertex used as used.
|
|
vertexUsed[trueIdx]= trueIdx;
|
|
}
|
|
|
|
|
|
// **** For all vertices used (not geomorphs), compute vertex Skins.
|
|
vector<CVertex> shadowVertices;
|
|
vector<sint> vertexToVSkin;
|
|
vertexToVSkin.resize(vertexUsed.size());
|
|
shadowVertices.reserve(vertexUsed.size());
|
|
// use a map to remove duplicates (because of UV/normal discontinuities before!!)
|
|
map<CVertex, uint> shadowVertexMap;
|
|
uint numMerged= 0;
|
|
// Skip Geomorphs.
|
|
for(i=geomorphs.size();i<vertexUsed.size(); ++i)
|
|
{
|
|
// If this vertex is used.
|
|
if(vertexUsed[i]!=-1)
|
|
{
|
|
// Build the vertex
|
|
CVertex shadowVert;
|
|
CUV uv;
|
|
shadowVert.vertex = *(CVector*)vba.getVertexCoordPointer(i);
|
|
shadowVert.normal = *(CVector*)vba.getNormalCoordPointer(i);
|
|
shadowVert.uv = *(CUV*)vba.getTexCoordPointer(i);
|
|
/*
|
|
// Select the best Matrix.
|
|
CMesh::CSkinWeight sw= skinWeights[i];
|
|
float maxW= 0;
|
|
uint matId= 0;
|
|
for(j=0;j<NL3D_MESH_SKINNING_MAX_MATRIX;j++)
|
|
{
|
|
// if no more matrix influenced, stop
|
|
if(sw.Weights[j]==0)
|
|
break;
|
|
if(sw.Weights[j]>maxW)
|
|
{
|
|
matId= sw.MatrixId[j];
|
|
maxW= sw.Weights[j];
|
|
}
|
|
}
|
|
// shadowVert.MatrixId= matId;
|
|
*/
|
|
// If dont find the shadowVertex in the map.
|
|
map<CVertex, uint>::iterator it= shadowVertexMap.find(shadowVert);
|
|
if(it==shadowVertexMap.end())
|
|
{
|
|
// Append
|
|
uint index= shadowVertices.size();
|
|
vertexToVSkin[i]= index;
|
|
shadowVertices.push_back(shadowVert);
|
|
shadowVertexMap.insert(make_pair(shadowVert, index));
|
|
}
|
|
else
|
|
{
|
|
// Ok, map.
|
|
vertexToVSkin[i]= it->second;
|
|
numMerged++;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
ofstream ofs(string(filename + ".obj").c_str());
|
|
|
|
for(size_t y = 0; y < shadowVertices.size(); ++y)
|
|
{
|
|
CVector v = shadowVertices[y].vertex;
|
|
CVector vn = shadowVertices[y].normal;
|
|
CUV vt = shadowVertices[y].uv;
|
|
|
|
ofs << "v " << v.x << " " << v.y << " " << v.z << endl;
|
|
ofs << "vn " << vn.x << " " << vn.y << " " << vn.z << endl;
|
|
ofs << "vt " << vt.U << " " << vt.V << endl;
|
|
}
|
|
|
|
// **** Get All Faces
|
|
// Final List Of Triangles that match the bone.
|
|
vector<uint32> shadowTriangles;
|
|
shadowTriangles.reserve(1000);
|
|
// Parse all input tri of the mesh.
|
|
for(i=0; i<meshIn->getNbRdrPass(lodId); ++i)
|
|
{
|
|
ofs << "g pass" << i << endl;
|
|
|
|
const CIndexBuffer *pb = getRdrPassPrimitiveBlock(meshIn, lodId, i);
|
|
CIndexBufferRead iba;
|
|
pb->lock (iba);
|
|
if (iba.getFormat() == CIndexBuffer::Indices32)
|
|
{
|
|
const uint32 *triPtr= (const uint32 *) iba.getPtr();
|
|
|
|
for(j=0; j<pb->getNumIndexes(); ++j)
|
|
{
|
|
uint idx= *triPtr;
|
|
// Get the real Vertex (ie not the geomporhed one).
|
|
idx= vertexUsed[idx];
|
|
// Get the ShadowVertex associated
|
|
idx= vertexToVSkin[idx];
|
|
|
|
shadowTriangles.push_back(idx);
|
|
triPtr++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const uint16 *triPtr= (const uint16 *) iba.getPtr();
|
|
for(j=0; j<pb->getNumIndexes(); ++j)
|
|
{
|
|
uint idx= *triPtr;
|
|
// Get the real Vertex (ie not the geomporhed one).
|
|
idx= vertexUsed[idx];
|
|
// Get the ShadowVertex associated
|
|
idx= vertexToVSkin[idx];
|
|
|
|
shadowTriangles.push_back(idx);
|
|
triPtr++;
|
|
}
|
|
}
|
|
|
|
for(size_t pass = 0; pass<shadowTriangles.size(); pass += 3)
|
|
{
|
|
ofs << "f " << shadowTriangles[pass]+1 << "/" << shadowTriangles[pass]+1 << "/" << shadowTriangles[pass]+1 << " ";
|
|
ofs << shadowTriangles[pass+1]+1 << "/" << shadowTriangles[pass+1]+1 << "/" << shadowTriangles[pass+1]+1 << " ";
|
|
ofs << shadowTriangles[pass+2]+1 << "/" << shadowTriangles[pass+2]+1 << "/" << shadowTriangles[pass+2]+1 << endl;
|
|
}
|
|
|
|
shadowTriangles.clear();
|
|
}
|
|
|
|
ofs.close();
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
|
|
TODO: implement this
|
|
|
|
bool ProcessMesh(const std::string &filename, IShape *shapeMesh)
|
|
{
|
|
CMesh *mesh = dynamic_cast<CMesh*>(shapeMesh);
|
|
|
|
if (!mesh) return false;
|
|
|
|
COFile ofile;
|
|
|
|
CMeshGeom* meshIn = (CMeshGeom*)&mesh->getMeshGeom();
|
|
|
|
CVertexBuffer vertexBuffer = meshIn->getVertexBuffer();
|
|
|
|
// CVertexBufferRead vba;
|
|
// vertexBuffer.lock (vba);
|
|
|
|
uint i = vertexBuffer.getNumVertices();
|
|
|
|
std::vector<NLMISC::CVector> vertices;
|
|
meshIn->retrieveVertices(vertices);
|
|
|
|
std::vector<uint32> indices;
|
|
meshIn->retrieveTriangles(indices);
|
|
|
|
|
|
// **** For all vertices used (not geomorphs), compute vertex Skins.
|
|
vector<CVertex> shadowVertices;
|
|
vector<sint> vertexToVSkin;
|
|
vertexToVSkin.resize(indices.size());
|
|
shadowVertices.reserve(indices.size());
|
|
// use a map to remove duplicates (because of UV/normal discontinuities before!!)
|
|
map<CVertex, uint> shadowVertexMap;
|
|
uint numMerged= 0;
|
|
// Skip Geomorphs.
|
|
for(i=0;i<indices.size(); ++i)
|
|
{
|
|
// Build the vertex
|
|
CVertex shadowVert;
|
|
CUV uv;
|
|
shadowVert.vertex = *(CVector*)vba.getVertexCoordPointer(i);
|
|
shadowVert.normal = *(CVector*)vba.getNormalCoordPointer(i);
|
|
shadowVert.uv = *(CUV*)vba.getTexCoordPointer(i);
|
|
|
|
// Select the best Matrix.
|
|
CMesh::CSkinWeight sw= skinWeights[i];
|
|
float maxW= 0;
|
|
uint matId= 0;
|
|
for(j=0;j<NL3D_MESH_SKINNING_MAX_MATRIX;j++)
|
|
{
|
|
// if no more matrix influenced, stop
|
|
if(sw.Weights[j]==0)
|
|
break;
|
|
if(sw.Weights[j]>maxW)
|
|
{
|
|
matId= sw.MatrixId[j];
|
|
maxW= sw.Weights[j];
|
|
}
|
|
}
|
|
|
|
// If dont find the shadowVertex in the map.
|
|
map<CVertex, uint>::iterator it= shadowVertexMap.find(shadowVert);
|
|
if(it==shadowVertexMap.end())
|
|
{
|
|
// Append
|
|
uint index= shadowVertices.size();
|
|
vertexToVSkin[i]= index;
|
|
shadowVertices.push_back(shadowVert);
|
|
shadowVertexMap.insert(make_pair(shadowVert, index));
|
|
}
|
|
else
|
|
{
|
|
// Ok, map.
|
|
vertexToVSkin[i]= it->second;
|
|
numMerged++;
|
|
}
|
|
}
|
|
|
|
ofstream ofs(string(filename + ".obj").c_str());
|
|
|
|
for(size_t y = 0; y < shadowVertices.size(); ++y)
|
|
{
|
|
CVector v = shadowVertices[y].vertex;
|
|
CVector vn = shadowVertices[y].normal;
|
|
CUV vt = shadowVertices[y].uv;
|
|
|
|
ofs << "v " << v.x << " " << v.y << " " << v.z << endl;
|
|
ofs << "vn " << vn.x << " " << vn.y << " " << vn.z << endl;
|
|
ofs << "vt " << vt.U << " " << vt.V << endl;
|
|
}
|
|
|
|
// **** Get All Faces
|
|
// Final List Of Triangles that match the bone.
|
|
vector<uint32> shadowTriangles;
|
|
shadowTriangles.reserve(1000);
|
|
// Parse all input tri of the mesh.
|
|
for(i=0; i<meshIn->getNbRdrPass(lodId); ++i)
|
|
{
|
|
ofs << "g pass" << i << endl;
|
|
|
|
const CIndexBuffer *pb = getRdrPassPrimitiveBlock(meshIn, lodId, i);
|
|
CIndexBufferRead iba;
|
|
pb->lock (iba);
|
|
if (iba.getFormat() == CIndexBuffer::Indices32)
|
|
{
|
|
const uint32 *triPtr= (const uint32 *) iba.getPtr();
|
|
|
|
for(j=0; j<pb->getNumIndexes(); ++j)
|
|
{
|
|
uint idx= *triPtr;
|
|
// Get the real Vertex (ie not the geomporhed one).
|
|
idx= vertexUsed[idx];
|
|
// Get the ShadowVertex associated
|
|
idx= vertexToVSkin[idx];
|
|
|
|
shadowTriangles.push_back(idx);
|
|
triPtr++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const uint16 *triPtr= (const uint16 *) iba.getPtr();
|
|
for(j=0; j<pb->getNumIndexes(); ++j)
|
|
{
|
|
uint idx= *triPtr;
|
|
// Get the real Vertex (ie not the geomporhed one).
|
|
idx= vertexUsed[idx];
|
|
// Get the ShadowVertex associated
|
|
idx= vertexToVSkin[idx];
|
|
|
|
shadowTriangles.push_back(idx);
|
|
triPtr++;
|
|
}
|
|
}
|
|
|
|
for(size_t pass = 0; pass<shadowTriangles.size(); pass += 3)
|
|
{
|
|
ofs << "f " << shadowTriangles[pass]+1 << "/" << shadowTriangles[pass]+1 << "/" << shadowTriangles[pass]+1 << " ";
|
|
ofs << shadowTriangles[pass+1]+1 << "/" << shadowTriangles[pass+1]+1 << "/" << shadowTriangles[pass+1]+1 << " ";
|
|
ofs << shadowTriangles[pass+2]+1 << "/" << shadowTriangles[pass+2]+1 << "/" << shadowTriangles[pass+2]+1 << endl;
|
|
}
|
|
|
|
shadowTriangles.clear();
|
|
}
|
|
|
|
ofs.close();
|
|
|
|
return true;
|
|
}
|
|
|
|
*/ |