mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-20 12:44:46 +00:00
- Adds entry to RMB menu in Asset Browser to restore an asset to a backup copy taken from autosaves - Adds reparent out-of-bounds objects button to SceneGroup inspector - Adds ability to have SubScene have a different loading bounds from the actual subscene bounds, allowing load triggering to happen ahead of the bounds of the subscene itself - Fixes asset importer handling of animFPS field to be the correct type - Adds onInspect handling to GameBase allowing better handling for any game class type with editor integration - Add getAssetLooseFileCount and getAssetLooseFile to AssetManager to be able to iterate over all loose files associated to an asset - Add standard/default preload function def to forestItem - Fixes handling of text placement on GuiIconButtonCtrl when text is set to the right - Adds setGlobalCenter utility function - Adds ability to set guiInputCtrl active state - Matched util functions for tracking if left and right mouse buttons are down to EditTSCtrl alongside the existing middle mouse - Add empty element sanity check to appMesh loader - Add callback for GameBase when game is created - Add default graphics options config for steamdeck - Fix typo in assetImportConfig default - Filters SceneGroup utility buttons in inspector to only show for relevent class types
183 lines
5.6 KiB
C++
183 lines
5.6 KiB
C++
//-----------------------------------------------------------------------------
|
|
// Copyright (c) 2012 GarageGames, LLC
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to
|
|
// deal in the Software without restriction, including without limitation the
|
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
// sell copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
// IN THE SOFTWARE.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "ts/loader/appMesh.h"
|
|
#include "ts/loader/tsShapeLoader.h"
|
|
|
|
Vector<AppMaterial*> AppMesh::appMaterials;
|
|
|
|
AppMesh::AppMesh()
|
|
: flags(0), vertsPerFrame(0),numFrames(0), numMatFrames(0), detailSize(1)
|
|
{
|
|
}
|
|
|
|
AppMesh::~AppMesh()
|
|
{
|
|
}
|
|
|
|
void AppMesh::computeBounds(Box3F& bounds)
|
|
{
|
|
bounds = Box3F::Invalid;
|
|
|
|
if ( isSkin() )
|
|
{
|
|
// Need to skin the mesh before we can compute the bounds
|
|
|
|
// Setup bone transforms
|
|
Vector<MatrixF> boneTransforms;
|
|
boneTransforms.setSize( nodeIndex.size() );
|
|
for (S32 iBone = 0; iBone < boneTransforms.size(); iBone++)
|
|
{
|
|
MatrixF nodeMat = bones[iBone]->getNodeTransform( TSShapeLoader::DefaultTime );
|
|
TSShapeLoader::zapScale(nodeMat);
|
|
boneTransforms[iBone].mul( nodeMat, initialTransforms[iBone] );
|
|
}
|
|
|
|
// Multiply verts by weighted bone transforms
|
|
for (S32 iVert = 0; iVert < initialVerts.size(); iVert++)
|
|
points[iVert].set( Point3F::Zero );
|
|
|
|
for (S32 iWeight = 0; iWeight < vertexIndex.size(); iWeight++)
|
|
{
|
|
const S32& vertIndex = vertexIndex[iWeight];
|
|
const MatrixF& deltaTransform = boneTransforms[ boneIndex[iWeight] ];
|
|
|
|
Point3F v;
|
|
deltaTransform.mulP( initialVerts[vertIndex], &v );
|
|
v *= weight[iWeight];
|
|
|
|
points[vertIndex] += v;
|
|
}
|
|
|
|
// compute bounds for the skinned mesh
|
|
for (S32 iVert = 0; iVert < initialVerts.size(); iVert++)
|
|
bounds.extend( points[iVert] );
|
|
}
|
|
else
|
|
{
|
|
MatrixF transform = getMeshTransform(TSShapeLoader::DefaultTime);
|
|
TSShapeLoader::zapScale(transform);
|
|
|
|
for (S32 iVert = 0; iVert < points.size(); iVert++)
|
|
{
|
|
Point3F p;
|
|
transform.mulP(points[iVert], &p);
|
|
bounds.extend(p);
|
|
}
|
|
}
|
|
}
|
|
|
|
void AppMesh::computeNormals()
|
|
{
|
|
// Clear normals
|
|
normals.setSize( points.size() );
|
|
for (S32 iNorm = 0; iNorm < normals.size(); iNorm++)
|
|
normals[iNorm] = Point3F::Zero;
|
|
|
|
// Sum triangle normals for each vertex
|
|
for (S32 iPrim = 0; iPrim < primitives.size(); iPrim++)
|
|
{
|
|
const TSDrawPrimitive& prim = primitives[iPrim];
|
|
|
|
for (S32 iInd = 0; iInd < prim.numElements; iInd += 3)
|
|
{
|
|
// Compute the normal for this triangle
|
|
S32 idx0 = indices[prim.start + iInd + 0];
|
|
S32 idx1 = indices[prim.start + iInd + 1];
|
|
S32 idx2 = indices[prim.start + iInd + 2];
|
|
|
|
const Point3F& v0 = points[idx0];
|
|
const Point3F& v1 = points[idx1];
|
|
const Point3F& v2 = points[idx2];
|
|
|
|
Point3F n;
|
|
mCross(v2 - v0, v1 - v0, &n);
|
|
n.normalize(); // remove this to use 'weighted' normals (large triangles will have more effect)
|
|
|
|
normals[idx0] += n;
|
|
normals[idx1] += n;
|
|
normals[idx2] += n;
|
|
}
|
|
}
|
|
|
|
// Normalize the vertex normals (this takes care of averaging the triangle normals)
|
|
for (S32 iNorm = 0; iNorm < normals.size(); iNorm++)
|
|
normals[iNorm].normalize();
|
|
}
|
|
|
|
TSMesh* AppMesh::constructTSMesh()
|
|
{
|
|
if (points.empty() || normals.empty() || primitives.empty() || indices.empty())
|
|
return NULL;
|
|
|
|
TSMesh* tsmesh;
|
|
if (isSkin())
|
|
{
|
|
TSSkinMesh* tsskin = new TSSkinMesh();
|
|
tsmesh = tsskin;
|
|
|
|
// Copy skin elements
|
|
tsskin->weight = weight;
|
|
tsskin->boneIndex = boneIndex;
|
|
tsskin->vertexIndex = vertexIndex;
|
|
tsskin->batchData.nodeIndex = nodeIndex;
|
|
tsskin->batchData.initialTransforms = initialTransforms;
|
|
tsskin->batchData.initialVerts = initialVerts;
|
|
tsskin->batchData.initialNorms = initialNorms;
|
|
}
|
|
else
|
|
{
|
|
tsmesh = new TSMesh();
|
|
}
|
|
|
|
// Copy mesh elements
|
|
tsmesh->mVerts = points;
|
|
tsmesh->mNorms = normals;
|
|
tsmesh->mTverts = uvs;
|
|
tsmesh->mPrimitives = primitives;
|
|
tsmesh->mIndices = indices;
|
|
tsmesh->mColors = colors;
|
|
tsmesh->mTverts2 = uv2s;
|
|
|
|
// Finish initializing the shape
|
|
tsmesh->setFlags(flags);
|
|
tsmesh->updateMeshFlags();
|
|
tsmesh->computeBounds();
|
|
tsmesh->numFrames = numFrames;
|
|
tsmesh->numMatFrames = numMatFrames;
|
|
tsmesh->vertsPerFrame = vertsPerFrame;
|
|
tsmesh->createTangents(tsmesh->mVerts, tsmesh->mNorms);
|
|
tsmesh->mEncodedNorms.set(NULL,0);
|
|
|
|
return tsmesh;
|
|
}
|
|
|
|
bool AppMesh::isBillboard()
|
|
{
|
|
return !dStrnicmp(getName(),"BB::",4) || !dStrnicmp(getName(),"BB_",3) || isBillboardZAxis();
|
|
}
|
|
|
|
bool AppMesh::isBillboardZAxis()
|
|
{
|
|
return !dStrnicmp(getName(),"BBZ::",5) || !dStrnicmp(getName(),"BBZ_",4);
|
|
}
|