Expanded mesh baking functionality, now supporting baking of LODs and Collision meshes

This commit is contained in:
Areloch 2018-03-01 01:51:18 -06:00
parent e079536122
commit f309b736ca
7 changed files with 1578 additions and 8 deletions

View file

@ -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

View file

@ -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; }

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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;
}