mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-20 04:34:48 +00:00
Expanded mesh baking functionality, now supporting baking of LODs and Collision meshes
This commit is contained in:
parent
e079536122
commit
f309b736ca
|
|
@ -1073,6 +1073,97 @@ bool TSStatic::buildPolyList(PolyListContext context, AbstractPolyList* polyList
|
|||
return true;
|
||||
}
|
||||
|
||||
bool TSStatic::buildExportPolyList(PolyListContext context, ColladaUtils::ExportData* exportData, const Box3F &box, const SphereF &)
|
||||
{
|
||||
if (!mShapeInstance)
|
||||
return false;
|
||||
|
||||
if (mCollisionType == Bounds)
|
||||
{
|
||||
ColladaUtils::ExportData::colMesh* colMesh;
|
||||
exportData->colMeshes.increment();
|
||||
colMesh = &exportData->colMeshes.last();
|
||||
|
||||
colMesh->mesh.setTransform(&mObjToWorld, mObjScale);
|
||||
colMesh->mesh.setObject(this);
|
||||
|
||||
colMesh->mesh.addBox(mObjBox);
|
||||
|
||||
colMesh->colMeshName = String::ToString("ColBox%d-1", exportData->colMeshes.size());
|
||||
}
|
||||
else if (mCollisionType == VisibleMesh)
|
||||
{
|
||||
ColladaUtils::ExportData::colMesh* colMesh;
|
||||
exportData->colMeshes.increment();
|
||||
colMesh = &exportData->colMeshes.last();
|
||||
|
||||
colMesh->mesh.setTransform(&mObjToWorld, mObjScale);
|
||||
colMesh->mesh.setObject(this);
|
||||
|
||||
mShapeInstance->buildPolyList(&colMesh->mesh, 0);
|
||||
|
||||
colMesh->colMeshName = String::ToString("ColMesh%d-1", exportData->colMeshes.size());
|
||||
}
|
||||
else if (mCollisionType == CollisionMesh)
|
||||
{
|
||||
// Everything else is done from the collision meshes
|
||||
// which may be built from either the visual mesh or
|
||||
// special collision geometry.
|
||||
for (U32 i = 0; i < mCollisionDetails.size(); i++)
|
||||
{
|
||||
ColladaUtils::ExportData::colMesh* colMesh;
|
||||
exportData->colMeshes.increment();
|
||||
colMesh = &exportData->colMeshes.last();
|
||||
|
||||
colMesh->mesh.setTransform(&mObjToWorld, mObjScale);
|
||||
colMesh->mesh.setObject(this);
|
||||
|
||||
mShapeInstance->buildPolyListOpcode(mCollisionDetails[i], &colMesh->mesh, box);
|
||||
|
||||
colMesh->colMeshName = String::ToString("ColMesh%d-1", exportData->colMeshes.size());
|
||||
}
|
||||
}
|
||||
|
||||
//Next, process the LOD levels and materials.
|
||||
if (isServerObject() && getClientObject())
|
||||
{
|
||||
TSStatic* clientShape = dynamic_cast<TSStatic*>(getClientObject());
|
||||
U32 numDetails = clientShape->mShapeInstance->getNumDetails() - 1;
|
||||
|
||||
exportData->meshData.increment();
|
||||
|
||||
//Prep a meshData for this shape in particular
|
||||
ColladaUtils::ExportData::meshLODData* meshData = &exportData->meshData.last();
|
||||
|
||||
//Fill out the info we'll need later to actually append our mesh data for the detail levels during the processing phase
|
||||
meshData->shapeInst = clientShape->mShapeInstance;
|
||||
meshData->originatingObject = this;
|
||||
meshData->meshTransform = mObjToWorld;
|
||||
meshData->scale = mObjScale;
|
||||
|
||||
//Iterate over all our detail levels
|
||||
for (U32 i = 0; i < clientShape->mShapeInstance->getNumDetails(); i++)
|
||||
{
|
||||
TSShape::Detail detail = clientShape->mShapeInstance->getShape()->details[i];
|
||||
|
||||
String detailName = String::ToLower(clientShape->mShapeInstance->getShape()->getName(detail.nameIndex));
|
||||
|
||||
//Skip it if it's a collision or line of sight element
|
||||
if (detailName.startsWith("col") || detailName.startsWith("los"))
|
||||
continue;
|
||||
|
||||
meshData->meshDetailLevels.increment();
|
||||
|
||||
ColladaUtils::ExportData::detailLevel* curDetail = &meshData->meshDetailLevels.last();
|
||||
|
||||
//Make sure we denote the size this detail level has
|
||||
curDetail->size = detail.size;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TSStatic::buildConvex(const Box3F& box, Convex* convex)
|
||||
{
|
||||
if ( mCollisionType == None )
|
||||
|
|
@ -1279,6 +1370,16 @@ void TSStatic::onUnmount( SceneObject *obj, S32 node )
|
|||
_updateShouldTick();
|
||||
}
|
||||
|
||||
U32 TSStatic::getNumDetails()
|
||||
{
|
||||
if (isServerObject() && getClientObject())
|
||||
{
|
||||
TSStatic* clientShape = dynamic_cast<TSStatic*>(getClientObject());
|
||||
return clientShape->mShapeInstance->getNumDetails();
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//These functions are duplicated in tsStatic and shapeBase.
|
||||
//They each function a little differently; but achieve the same purpose of gathering
|
||||
|
|
|
|||
|
|
@ -138,6 +138,7 @@ protected:
|
|||
bool castRay(const Point3F &start, const Point3F &end, RayInfo* info);
|
||||
bool castRayRendered(const Point3F &start, const Point3F &end, RayInfo* info);
|
||||
bool buildPolyList(PolyListContext context, AbstractPolyList* polyList, const Box3F &box, const SphereF& sphere);
|
||||
bool buildExportPolyList(PolyListContext context, ColladaUtils::ExportData* exportData, const Box3F &box, const SphereF &);
|
||||
void buildConvex(const Box3F& box, Convex* convex);
|
||||
|
||||
bool _createShape();
|
||||
|
|
@ -237,6 +238,8 @@ public:
|
|||
|
||||
TSShapeInstance* getShapeInstance() const { return mShapeInstance; }
|
||||
|
||||
U32 getNumDetails();
|
||||
|
||||
const Vector<S32>& getCollisionDetails() const { return mCollisionDetails; }
|
||||
|
||||
const Vector<S32>& getLOSDetails() const { return mLOSDetails; }
|
||||
|
|
|
|||
|
|
@ -3927,15 +3927,38 @@ void WorldEditor::makeSelectionAMesh(const char *filename)
|
|||
OptimizedPolyList polyList;
|
||||
polyList.setBaseTransform(orientation);
|
||||
|
||||
ColladaUtils::ExportData exportData;
|
||||
|
||||
for (S32 i = 0; i < objectList.size(); i++)
|
||||
{
|
||||
SceneObject *pObj = objectList[i];
|
||||
if (!pObj->buildPolyList(PLC_Export, &polyList, pObj->getWorldBox(), pObj->getWorldSphere()))
|
||||
if (!pObj->buildExportPolyList(PLC_Export, &exportData, pObj->getWorldBox(), pObj->getWorldSphere()))
|
||||
Con::warnf("colladaExportObjectList() - object %i returned no geometry.", pObj->getId());
|
||||
}
|
||||
|
||||
//Now that we have all of our mesh data, process it so we can correctly collapse everything.
|
||||
exportData.processData();
|
||||
|
||||
//recenter generated visual mesh results
|
||||
for (U32 dl = 0; dl < exportData.colMeshes.size(); dl++)
|
||||
{
|
||||
for (U32 pnt = 0; pnt < exportData.colMeshes[dl].mesh.mPoints.size(); pnt++)
|
||||
{
|
||||
exportData.colMeshes[dl].mesh.mPoints[pnt] -= centroid;
|
||||
}
|
||||
}
|
||||
|
||||
//recenter generated collision mesh results
|
||||
for (U32 dl = 0; dl < exportData.detailLevels.size(); dl++)
|
||||
{
|
||||
for (U32 pnt = 0; pnt < exportData.detailLevels[dl].mesh.mPoints.size(); pnt++)
|
||||
{
|
||||
exportData.detailLevels[dl].mesh.mPoints[pnt] -= centroid;
|
||||
}
|
||||
}
|
||||
|
||||
// Use a ColladaUtils function to do the actual export to a Collada file
|
||||
ColladaUtils::exportToCollada(filename, polyList);
|
||||
ColladaUtils::exportToCollada(filename, exportData);
|
||||
//
|
||||
|
||||
// Allocate TSStatic object and add to level.
|
||||
|
|
|
|||
|
|
@ -60,6 +60,9 @@
|
|||
#include "gfx/gfxDevice.h"
|
||||
#endif
|
||||
|
||||
#ifndef _COLLADA_UTILS_H_
|
||||
#include "ts/collada/colladaUtils.h"
|
||||
#endif
|
||||
|
||||
class SceneManager;
|
||||
class SceneRenderState;
|
||||
|
|
@ -550,6 +553,24 @@ class SceneObject : public NetObject, private SceneContainer::Link, public Proce
|
|||
const Box3F& box,
|
||||
const SphereF& sphere ) { return false; }
|
||||
|
||||
/// Builds a list of polygons which intersect a bounding volume for exporting
|
||||
///
|
||||
/// This will use either the sphere or the box, not both, the
|
||||
/// SceneObject implementation ignores sphere.
|
||||
///
|
||||
/// @see AbstractPolyList
|
||||
/// @param context A contentual hint as to the type of polylist to build.
|
||||
/// @param polyList Poly list build (out)
|
||||
/// @param box Box bounding volume
|
||||
/// @param sphere Sphere bounding volume
|
||||
///
|
||||
virtual bool buildExportPolyList(PolyListContext context,
|
||||
ColladaUtils::ExportData *exportData,
|
||||
const Box3F& box,
|
||||
const SphereF& sphere) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Casts a ray and obtain collision information, returns true if RayInfo is modified.
|
||||
///
|
||||
/// @param start Start point of ray
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -50,6 +50,10 @@
|
|||
#include "console/console.h"
|
||||
#endif
|
||||
|
||||
#ifndef _TSSHAPEINSTANCE_H_
|
||||
#include "ts/tsShapeInstance.h"
|
||||
#endif
|
||||
|
||||
#include "platform/tmm_off.h"
|
||||
|
||||
#include "dae.h"
|
||||
|
|
@ -63,6 +67,7 @@
|
|||
#include "dom/domCOLLADA.h"
|
||||
|
||||
#include "platform/tmm_on.h"
|
||||
#include "core/strings/findMatch.h"
|
||||
|
||||
namespace ColladaUtils
|
||||
{
|
||||
|
|
@ -100,7 +105,7 @@ namespace ColladaUtils
|
|||
{
|
||||
upAxis = UPAXISTYPE_COUNT;
|
||||
unit = -1.0f;
|
||||
lodType = DetectDTS;
|
||||
lodType = TrailingNumber;
|
||||
singleDetailSize = 2;
|
||||
matNamePrefix = "";
|
||||
alwaysImport = "";
|
||||
|
|
@ -117,6 +122,123 @@ namespace ColladaUtils
|
|||
|
||||
ImportOptions& getOptions();
|
||||
|
||||
struct ExportData
|
||||
{
|
||||
struct detailLevel
|
||||
{
|
||||
OptimizedPolyList mesh;
|
||||
S32 size;
|
||||
Map<int, int> materialRefList;
|
||||
};
|
||||
|
||||
struct meshLODData
|
||||
{
|
||||
Vector<detailLevel> meshDetailLevels;
|
||||
TSShapeInstance* shapeInst;
|
||||
MatrixF meshTransform;
|
||||
SceneObject* originatingObject;
|
||||
|
||||
Point3F scale;
|
||||
|
||||
S32 hasDetailLevel(S32 size)
|
||||
{
|
||||
for (U32 i = 0; i < meshDetailLevels.size(); ++i)
|
||||
{
|
||||
U32 mdlSize = meshDetailLevels[i].size;
|
||||
|
||||
if (mdlSize == size)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
struct colMesh
|
||||
{
|
||||
OptimizedPolyList mesh;
|
||||
String colMeshName;
|
||||
};
|
||||
|
||||
Vector<detailLevel> detailLevels;
|
||||
Vector<meshLODData> meshData;
|
||||
Vector<colMesh> colMeshes;
|
||||
Vector<BaseMatInstance*> materials;
|
||||
|
||||
void processData();
|
||||
|
||||
S32 hasDetailLevel(U32 dl)
|
||||
{
|
||||
for (U32 i = 0; i < detailLevels.size(); i++)
|
||||
{
|
||||
if (detailLevels[i].size == dl)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
S32 hasMaterialInstance(BaseMatInstance* matInst)
|
||||
{
|
||||
for (U32 i = 0; i < materials.size(); i++)
|
||||
{
|
||||
if (materials[i] == matInst)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
S32 numberOfDetailLevels()
|
||||
{
|
||||
Vector<S32> detailLevelIdxs;
|
||||
|
||||
for (U32 i = 0; i < meshData.size(); ++i)
|
||||
{
|
||||
for (U32 d = 0; d < meshData[i].meshDetailLevels.size(); ++d)
|
||||
{
|
||||
detailLevelIdxs.push_back_unique(meshData[i].meshDetailLevels[d].size);
|
||||
}
|
||||
}
|
||||
|
||||
return detailLevelIdxs.size();
|
||||
}
|
||||
|
||||
static S32 _Sort(const S32 *p1, const S32 *p2)
|
||||
{
|
||||
S32 e1 = (*p1);
|
||||
S32 e2 = (*p2);
|
||||
|
||||
if (e1 > e2)
|
||||
return 1;
|
||||
else if (e1 < e2)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
S32 getDetailLevelSize(U32 detailIdx)
|
||||
{
|
||||
Vector<S32> detailLevelIdxs;
|
||||
|
||||
for (U32 i = 0; i < meshData.size(); ++i)
|
||||
{
|
||||
for (U32 d = 0; d < meshData[i].meshDetailLevels.size(); ++d)
|
||||
{
|
||||
S32 mdlSize = meshData[i].meshDetailLevels[d].size;
|
||||
detailLevelIdxs.push_back_unique(mdlSize);
|
||||
}
|
||||
}
|
||||
|
||||
if (detailIdx >= detailLevelIdxs.size())
|
||||
return -1;
|
||||
|
||||
detailLevelIdxs.sort(&_Sort);
|
||||
|
||||
return detailLevelIdxs[detailIdx];
|
||||
}
|
||||
};
|
||||
|
||||
void convertTransform(MatrixF& m);
|
||||
|
||||
void collapsePath(std::string& path);
|
||||
|
|
@ -139,8 +261,15 @@ namespace ColladaUtils
|
|||
void exportColladaMesh(TiXmlElement* rootNode, const OptimizedPolyList& mesh, const String& meshName, const Vector<String>& matNames);
|
||||
void exportColladaScene(TiXmlElement* rootNode, const String& meshName, const Vector<String>& matNames);
|
||||
|
||||
void exportColladaMaterials(TiXmlElement* rootNode, const ExportData& exportData, const Torque::Path& colladaFile);
|
||||
void exportColladaMesh(TiXmlElement* rootNode, const ExportData& exportData, const String& meshName);
|
||||
void exportColladaCollisionTriangles(TiXmlElement* meshNode, const ExportData& exportData, const U32 collisionIdx);
|
||||
void exportColladaTriangles(TiXmlElement* meshNode, const ExportData& exportData, const U32 detailLevel, const String& meshName);
|
||||
void exportColladaScene(TiXmlElement* rootNode, const ExportData& exportData, const String& meshName);
|
||||
|
||||
// Export an OptimizedPolyList to a simple Collada file
|
||||
void exportToCollada(const Torque::Path& colladaFile, const OptimizedPolyList& mesh, const String& meshName = String::EmptyString);
|
||||
void exportToCollada(const Torque::Path& colladaFile, const ExportData& exportData);
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -535,7 +664,7 @@ template<> inline const domListOfUInts *ColladaPrimitive<domTristrips>::getTrian
|
|||
continue;
|
||||
|
||||
domUint* pSrcData = &(P->getValue()[0]);
|
||||
S32 numTriangles = (P->getValue().getCount() / stride) - 2;
|
||||
size_t numTriangles = (P->getValue().getCount() / stride) - 2;
|
||||
|
||||
// Convert the strip back to a triangle list
|
||||
domUint* v0 = pSrcData;
|
||||
|
|
@ -576,7 +705,7 @@ template<> inline const domListOfUInts *ColladaPrimitive<domTrifans>::getTriangl
|
|||
continue;
|
||||
|
||||
domUint* pSrcData = &(P->getValue()[0]);
|
||||
S32 numTriangles = (P->getValue().getCount() / stride) - 2;
|
||||
size_t numTriangles = (P->getValue().getCount() / stride) - 2;
|
||||
|
||||
// Convert the fan back to a triangle list
|
||||
domUint* v0 = pSrcData + stride;
|
||||
|
|
@ -608,7 +737,7 @@ template<> inline const domListOfUInts *ColladaPrimitive<domPolygons>::getTriang
|
|||
continue;
|
||||
|
||||
domUint* pSrcData = &(P->getValue()[0]);
|
||||
S32 numPoints = P->getValue().getCount() / stride;
|
||||
size_t numPoints = P->getValue().getCount() / stride;
|
||||
|
||||
// Use a simple tri-fan (centered at the first point) method of
|
||||
// converting the polygon to triangles.
|
||||
|
|
|
|||
|
|
@ -135,6 +135,20 @@ IMPLEMENT_CONOBJECT(TSShapeConstructor);
|
|||
TSShapeConstructor::TSShapeConstructor()
|
||||
: mShapePath(""), mLoadingShape(false)
|
||||
{
|
||||
mOptions.upAxis = UPAXISTYPE_COUNT;
|
||||
mOptions.unit = -1.0f;
|
||||
mOptions.lodType = ColladaUtils::ImportOptions::TrailingNumber;
|
||||
mOptions.singleDetailSize = 2;
|
||||
mOptions.matNamePrefix = "";
|
||||
mOptions.alwaysImport = "";
|
||||
mOptions.neverImport = String(Con::getVariable("$TSShapeConstructor::neverImport"));
|
||||
mOptions.alwaysImportMesh = "";
|
||||
mOptions.neverImportMesh = String(Con::getVariable("$TSShapeConstructor::neverImportMesh"));
|
||||
mOptions.ignoreNodeScale = false;
|
||||
mOptions.adjustCenter = false;
|
||||
mOptions.adjustFloor = false;
|
||||
mOptions.forceUpdateMaterials = false;
|
||||
mOptions.useDiffuseNames = false;
|
||||
mShape = NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue