Initial commit

This commit is contained in:
alexpete
2021-03-05 11:26:34 -08:00
commit a10351f38d
27091 changed files with 5521199 additions and 0 deletions
@@ -0,0 +1,16 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "EditorDefs.h"
#include "EdGeometry.h"
+84
View File
@@ -0,0 +1,84 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef CRYINCLUDE_EDITOR_GEOMETRY_EDGEOMETRY_H
#define CRYINCLUDE_EDITOR_GEOMETRY_EDGEOMETRY_H
#pragma once
struct IIndexedMesh;
struct DisplayContext;
struct HitContext;
struct SSubObjSelectionModifyContext;
class CObjectArchive;
// Basic supported geometry types.
enum EEdGeometryType
{
GEOM_TYPE_MESH = 0, // Mesh geometry.
GEOM_TYPE_BRUSH, // Solid brush geometry.
GEOM_TYPE_PATCH, // Bezier patch surface geometry.
GEOM_TYPE_NURB, // Nurbs surface geometry.
};
//////////////////////////////////////////////////////////////////////////
// Description:
// CEdGeometry is a base class for all supported editable geometries.
//////////////////////////////////////////////////////////////////////////
class CRYEDIT_API CEdGeometry
: public CRefCountBase
{
public:
CEdGeometry() {};
// Query the type of the geometry mesh.
virtual EEdGeometryType GetType() const = 0;
// Serialize geometry.
virtual void Serialize(CObjectArchive& ar) = 0;
// Return geometry axis aligned bounding box.
virtual void GetBounds(AABB& box) = 0;
// Clones Geometry, returns exact copy of the original geometry.
virtual CEdGeometry* Clone() = 0;
// Access to the indexed mesh.
// Return false if geometry can not be represented by an indexed mesh.
virtual IIndexedMesh* GetIndexedMesh(size_t idx = 0) = 0;
virtual IStatObj* GetIStatObj() const = 0;
virtual void GetTM(Matrix34* pTM, size_t idx = 0) = 0;
//////////////////////////////////////////////////////////////////////////
// Advanced geometry interface for SubObject selection and modification.
//////////////////////////////////////////////////////////////////////////
virtual void SetModified(bool bModified = true) = 0;
virtual bool IsModified() const = 0;
virtual bool StartSubObjSelection(const Matrix34& nodeWorldTM, int elemType, int nFlags) = 0;
virtual void EndSubObjSelection() = 0;
// Display geometry for sub object selection.
virtual void Display(DisplayContext& dc) = 0;
// Sub geometry hit testing and selection.
virtual bool HitTest(HitContext& hit) = 0;
//////////////////////////////////////////////////////////////////////////
virtual void ModifySelection(SSubObjSelectionModifyContext& modCtx, bool isUndo = true) = 0;
// Called when selection modification is accepted.
virtual void AcceptModifySelection() = 0;
protected:
~CEdGeometry() {};
};
#endif // CRYINCLUDE_EDITOR_GEOMETRY_EDGEOMETRY_H
File diff suppressed because it is too large Load Diff
+194
View File
@@ -0,0 +1,194 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
// Description : Editor structure that wraps access to IStatObj
#ifndef CRYINCLUDE_EDITOR_GEOMETRY_EDMESH_H
#define CRYINCLUDE_EDITOR_GEOMETRY_EDMESH_H
#pragma once
#include "EdGeometry.h"
#include "Objects/SubObjSelection.h"
#include "TriMesh.h"
// Flags that can be set on CEdMesh.
enum CEdMeshFlags
{
};
//////////////////////////////////////////////////////////////////////////
// Description:
// CEdMesh is a Geometry kind representing simple mesh.
// Holds IStatObj interface from the 3D Engine.
//////////////////////////////////////////////////////////////////////////
class CRYEDIT_API CEdMesh
: public CEdGeometry
{
public:
//////////////////////////////////////////////////////////////////////////
// CEdGeometry implementation.
//////////////////////////////////////////////////////////////////////////
virtual EEdGeometryType GetType() const { return GEOM_TYPE_MESH; };
virtual void Serialize(CObjectArchive& ar);
virtual void GetBounds(AABB& box);
virtual CEdGeometry* Clone();
virtual IIndexedMesh* GetIndexedMesh(size_t idx = 0);
virtual void GetTM(Matrix34* pTM, size_t idx = 0);
virtual void SetModified(bool bModified = true);
virtual bool IsModified() const { return m_bModified; };
virtual bool StartSubObjSelection(const Matrix34& nodeWorldTM, int elemType, int nFlags);
virtual void EndSubObjSelection();
virtual void Display(DisplayContext& dc);
virtual bool HitTest(HitContext& hit);
bool GetSelectionReferenceFrame(Matrix34& refFrame);
virtual void ModifySelection(SSubObjSelectionModifyContext& modCtx, bool isUndo = true);
virtual void AcceptModifySelection();
//////////////////////////////////////////////////////////////////////////
~CEdMesh();
// Return filename of mesh.
const QString& GetFilename() const { return m_filename; };
void SetFilename(const QString& filename);
//! Reload geometry of mesh.
void ReloadGeometry();
void AddUser();
void RemoveUser();
int GetUserCount() const { return m_nUserCount; };
//////////////////////////////////////////////////////////////////////////
void SetFlags(int nFlags) { m_nFlags = nFlags; };
int GetFlags() { return m_nFlags; }
//////////////////////////////////////////////////////////////////////////
//! Access stored IStatObj.
IStatObj* GetIStatObj() const { return m_pStatObj; }
//! Returns true if filename and geomname refer to the same object as this one.
bool IsSameObject(const char* filename);
//! RenderMesh.
void Render(SRendParams& rp, const SRenderingPassInfo& passInfo);
//! Make new CEdMesh, if same IStatObj loaded, and CEdMesh for this IStatObj is allocated.
//! This instance of CEdMesh will be returned.
static CEdMesh* LoadMesh(const char* filename);
// Creates a new mesh not from a file.
// Create a new StatObj and IndexedMesh.
static CEdMesh* CreateMesh(const char* name);
//! Reload all geometries.
static void ReloadAllGeometries();
static void ReleaseAll();
//! Check if default object was loaded.
bool IsDefaultObject();
//////////////////////////////////////////////////////////////////////////
// Copy EdMesh data to the specified mesh.
void CopyToMesh(CTriMesh& toMesh, int nCopyFlags);
// Copy EdMesh data from the specified mesh.
void CopyFromMesh(CTriMesh& fromMesh, int nCopyFlags, bool bUndo);
// Retrieve mesh class.
CTriMesh* GetMesh();
//////////////////////////////////////////////////////////////////////////
void InvalidateMesh();
void SetWorldTM(const Matrix34& worldTM);
// Save mesh into the file.
// Optionally can provide pointer to the pak file where to save files into.
void SaveToCGF(const char* sFilename, CPakFile* pPakFile = NULL, _smart_ptr<IMaterial> pMaterial = NULL);
// Draw debug representation of this mesh.
void DebugDraw(const SGeometryDebugDrawInfo& info, float fExtrdueScale = 0.01f);
private:
//////////////////////////////////////////////////////////////////////////
CEdMesh(IStatObj* pGeom);
CEdMesh();
void UpdateSubObjCache();
void UpdateIndexedMeshFromCache(bool bFast);
void OnSelectionChange();
//////////////////////////////////////////////////////////////////////////
struct SSubObjHitTestEnvironment
{
Vec3 vWSCameraPos;
Vec3 vWSCameraVector;
Vec3 vOSCameraVector;
bool bHitTestNearest;
bool bHitTestSelected;
bool bSelectOnHit;
bool bAdd;
bool bRemove;
bool bSelectValue;
bool bHighlightOnly;
bool bIgnoreBackfacing;
};
struct SSubObjHitTestResult
{
CTriMesh::EStream stream; // To What stream of the TriMesh this result apply.
MeshElementsArray elems; // List of hit elements.
float minDistance; // Minimal distance to the hit.
SSubObjHitTestResult() { minDistance = FLT_MAX; }
};
bool HitTestVertex(HitContext& hit, SSubObjHitTestEnvironment& env, SSubObjHitTestResult& result);
bool HitTestEdge(HitContext& hit, SSubObjHitTestEnvironment& env, SSubObjHitTestResult& result);
bool HitTestFace(HitContext& hit, SSubObjHitTestEnvironment& env, SSubObjHitTestResult& result);
// Return`s true if selection changed.
bool SelectSubObjElements(SSubObjHitTestEnvironment& env, SSubObjHitTestResult& result);
bool IsHitTestResultSelected(SSubObjHitTestResult& result);
//////////////////////////////////////////////////////////////////////////
//! CGF filename.
QString m_filename;
IStatObj* m_pStatObj;
int m_nUserCount;
int m_nFlags;
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
typedef std::map<QString, CEdMesh*, stl::less_stricmp<QString> > MeshMap;
static MeshMap m_meshMap;
// This cache is created when sub object selection is needed.
struct SubObjCache
{
// Cache of data in geometry.
// World space mesh.
CTriMesh* pTriMesh;
Matrix34 worldTM;
Matrix34 invWorldTM;
CBitArray m_tempBitArray;
bool bNoDisplay;
SubObjCache()
: pTriMesh(0)
, bNoDisplay(false) {};
};
SubObjCache* m_pSubObjCache;
bool m_bModified;
std::vector<IIndexedMesh*> m_tempIndexedMeshes;
std::vector<Matrix34> m_tempMatrices;
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
};
#endif // CRYINCLUDE_EDITOR_GEOMETRY_EDMESH_H
+716
View File
@@ -0,0 +1,716 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "EditorDefs.h"
#include "TriMesh.h"
// Editor
#include "Util/fastlib.h"
#include "Objects/SubObjSelection.h"
//////////////////////////////////////////////////////////////////////////
CTriMesh::CTriMesh()
{
pFaces = NULL;
pVertices = NULL;
pWSVertices = NULL;
pUV = NULL;
pColors = NULL;
pEdges = NULL;
pWeights = NULL;
nFacesCount = 0;
nVertCount = 0;
nUVCount = 0;
nEdgeCount = 0;
selectionType = SO_ELEM_NONE;
memset(m_streamSize, 0, sizeof(m_streamSize));
memset(m_streamSel, 0, sizeof(m_streamSel));
streamSelMask = 0;
m_streamSel[VERTICES] = &vertSel;
m_streamSel[EDGES] = &edgeSel;
m_streamSel[FACES] = &faceSel;
}
//////////////////////////////////////////////////////////////////////////
CTriMesh::~CTriMesh()
{
free(pFaces);
free(pEdges);
free(pVertices);
free(pUV);
free(pColors);
free(pWSVertices);
free(pWeights);
}
// Set stream size.
void CTriMesh::ReallocStream(int stream, int nNewCount)
{
assert(stream >= 0 && stream < LAST_STREAM);
if (stream < 0 || stream >= LAST_STREAM)
{
return;
}
if (m_streamSize[stream] == nNewCount)
{
return; // Stream already have required size.
}
void* pStream = 0;
int nElementSize = 0;
GetStreamInfo(stream, pStream, nElementSize);
pStream = ReAllocElements(pStream, nNewCount, nElementSize);
m_streamSize[stream] = nNewCount;
switch (stream)
{
case VERTICES:
pVertices = (CTriVertex*)pStream;
nVertCount = nNewCount;
vertSel.resize(nNewCount);
break;
case FACES:
pFaces = (CTriFace*)pStream;
nFacesCount = nNewCount;
faceSel.resize(nNewCount);
break;
case EDGES:
pEdges = (CTriEdge*)pStream;
nEdgeCount = nNewCount;
edgeSel.resize(nNewCount);
break;
case TEXCOORDS:
pUV = (SMeshTexCoord*)pStream;
nUVCount = nNewCount;
break;
case COLORS:
pColors = (SMeshColor*)pStream;
break;
case WEIGHTS:
pWeights = (float*)pStream;
break;
case LINES:
pLines = (CTriLine*)pStream;
break;
case WS_POSITIONS:
pWSVertices = (Vec3*)pStream;
break;
default:
assert(0); // unknown stream.
}
m_streamSize[stream] = nNewCount;
}
// Set stream size.
void CTriMesh::GetStreamInfo(int stream, void*& pStream, int& nElementSize) const
{
assert(stream >= 0 && stream < LAST_STREAM);
switch (stream)
{
case VERTICES:
pStream = pVertices;
nElementSize = sizeof(CTriVertex);
break;
case FACES:
pStream = pFaces;
nElementSize = sizeof(CTriFace);
break;
case EDGES:
pStream = pEdges;
nElementSize = sizeof(CTriEdge);
break;
case TEXCOORDS:
pStream = pUV;
nElementSize = sizeof(SMeshTexCoord);
break;
case COLORS:
pStream = pColors;
nElementSize = sizeof(SMeshColor);
break;
case WEIGHTS:
pStream = pWeights;
nElementSize = sizeof(float);
break;
case LINES:
pStream = pLines;
nElementSize = sizeof(CTriLine);
break;
case WS_POSITIONS:
pStream = pWSVertices;
nElementSize = sizeof(Vec3);
break;
default:
assert(0); // unknown stream.
}
}
//////////////////////////////////////////////////////////////////////////
void* CTriMesh::ReAllocElements(void* old_ptr, int new_elem_num, int size_of_element)
{
return realloc(old_ptr, new_elem_num * size_of_element);
}
//////////////////////////////////////////////////////////////////////////
// Unshare all vertices and split on 3 arrays, positions/texcoords.
//////////////////////////////////////////////////////////////////////////
void CTriMesh::SetFromMesh(CMesh& mesh)
{
bbox = mesh.m_bbox;
int maxVerts = mesh.GetIndexCount();
SetVertexCount(maxVerts);
SetUVCount(maxVerts);
if (mesh.m_pColor0)
{
SetColorsCount(maxVerts);
}
SetFacesCount(mesh.GetIndexCount());
int numv = 0;
int numface = 0;
for (int nSubset = 0; nSubset < mesh.GetSubSetCount(); nSubset++)
{
SMeshSubset& subset = mesh.m_subsets[nSubset];
for (int i = subset.nFirstIndexId; i < subset.nFirstIndexId + subset.nNumIndices; i += 3)
{
CTriFace& face = pFaces[numface++];
for (int j = 0; j < 3; j++)
{
int idx = mesh.m_pIndices[i + j];
pVertices[numv].pos = mesh.m_pPositions ? mesh.m_pPositions[idx] : mesh.m_pPositionsF16[idx].ToVec3();
pWeights[numv] = 0.0f;
pUV[numv] = mesh.m_pTexCoord[idx];
if (mesh.m_pColor0)
{
pColors[numv] = mesh.m_pColor0[idx];
}
face.v [j] = numv;
face.uv[j] = numv;
face.n [j] = mesh.m_pNorms[idx].GetN();
face.MatID = subset.nMatID;
face.flags = 0;
numv++;
}
}
}
SetFacesCount(numface);
SharePositions();
ShareUV();
UpdateEdges();
CalcFaceNormals();
}
/////////////////////////////////////////////////////////////////////////////////////
inline int FindVertexInHash(const Vec3& vPosToFind, const CTriVertex* pVectors, std::vector<int>& hash, float fEpsilon)
{
for (uint32 i = 0; i < hash.size(); i++)
{
const Vec3& v0 = pVectors[hash[i]].pos;
const Vec3& v1 = vPosToFind;
if (fabsf(v0.y - v1.y) < fEpsilon && fabsf(v0.x - v1.x) < fEpsilon && fabsf(v0.z - v1.z) < fEpsilon)
{
return hash[i];
}
}
return -1;
}
/////////////////////////////////////////////////////////////////////////////////////
inline int FindTexCoordInHash(const SMeshTexCoord& coordToFind, const SMeshTexCoord* pCoords, std::vector<int>& hash, float fEpsilon)
{
for (uint32 i = 0; i < hash.size(); i++)
{
const SMeshTexCoord& t0 = pCoords[hash[i]];
const SMeshTexCoord& t1 = coordToFind;
if (t0.IsEquivalent(t1, fEpsilon))
{
return hash[i];
}
}
return -1;
}
//////////////////////////////////////////////////////////////////////////
void CTriMesh::SharePositions()
{
float fEpsilon = 0.0001f;
float fHashScale = 256.0f / MAX(bbox.GetSize().GetLength(), fEpsilon);
std::vector<int> arrHashTable[256];
CTriVertex* pNewVerts = new CTriVertex[GetVertexCount()];
SMeshColor* pNewColors = 0;
if (pColors)
{
pNewColors = new SMeshColor[GetVertexCount()];
}
int nLastIndex = 0;
for (int f = 0; f < GetFacesCount(); f++)
{
CTriFace& face = pFaces[f];
for (int i = 0; i < 3; i++)
{
const Vec3& v = pVertices[face.v[i]].pos;
uint8 nHash = RoundFloatToInt((v.x + v.y + v.z) * fHashScale);
int find = FindVertexInHash(v, pNewVerts, arrHashTable[nHash], fEpsilon);
if (find < 0)
{
pNewVerts[nLastIndex] = pVertices[face.v[i]];
if (pColors)
{
pNewColors[nLastIndex] = pColors[face.v[i]];
}
face.v[i] = nLastIndex;
// Reserve some space already.
arrHashTable[nHash].reserve(100);
arrHashTable[nHash].push_back(nLastIndex);
nLastIndex++;
}
else
{
face.v[i] = find;
}
}
}
SetVertexCount(nLastIndex);
memcpy(pVertices, pNewVerts, nLastIndex * sizeof(CTriVertex));
delete []pNewVerts;
if (pColors)
{
SetColorsCount(nLastIndex);
memcpy(pColors, pNewColors, nLastIndex * sizeof(SMeshColor));
delete []pNewColors;
}
}
//////////////////////////////////////////////////////////////////////////
void CTriMesh::ShareUV()
{
float fEpsilon = 0.0001f;
float fHashScale = 256.0f;
std::vector<int> arrHashTable[256];
SMeshTexCoord* pNewUV = new SMeshTexCoord[GetUVCount()];
int nLastIndex = 0;
for (int f = 0; f < GetFacesCount(); f++)
{
CTriFace& face = pFaces[f];
for (int i = 0; i < 3; i++)
{
const Vec2 uv = pUV[face.uv[i]].GetUV();
uint8 nHash = RoundFloatToInt((uv.x + uv.y) * fHashScale);
int find = FindTexCoordInHash(pUV[face.uv[i]], pNewUV, arrHashTable[nHash], fEpsilon);
if (find < 0)
{
pNewUV[nLastIndex] = pUV[face.uv[i]];
face.uv[i] = nLastIndex;
arrHashTable[nHash].reserve(100);
arrHashTable[nHash].push_back(nLastIndex);
nLastIndex++;
}
else
{
face.uv[i] = find;
}
}
}
SetUVCount(nLastIndex);
memcpy(pUV, pNewUV, nLastIndex * sizeof(SMeshTexCoord));
delete []pNewUV;
}
//////////////////////////////////////////////////////////////////////////
void CTriMesh::CalcFaceNormals()
{
for (int i = 0; i < nFacesCount; i++)
{
CTriFace& face = pFaces[i];
Vec3 p1 = pVertices[face.v[0]].pos;
Vec3 p2 = pVertices[face.v[1]].pos;
Vec3 p3 = pVertices[face.v[2]].pos;
face.normal = (p2 - p1).Cross(p3 - p1);
face.normal.Normalize();
}
}
#define TEX_EPS 0.001f
#define VER_EPS 0.001f
//////////////////////////////////////////////////////////////////////////
void CTriMesh::UpdateIndexedMesh(IIndexedMesh* pIndexedMesh) const
{
{
const int maxVerts = nFacesCount * 3;
pIndexedMesh->SetVertexCount(maxVerts);
pIndexedMesh->SetTexCoordCount(maxVerts);
if (pColors)
{
pIndexedMesh->SetColorCount(maxVerts);
}
pIndexedMesh->SetIndexCount(0);
pIndexedMesh->SetFaceCount(nFacesCount);
}
//////////////////////////////////////////////////////////////////////////
// To find really used materials
std::vector<int> usedMaterialIds;
uint16 MatIdToSubset[MAX_SUB_MATERIALS];
int nLastSubsetId = 0;
memset(MatIdToSubset, 0, sizeof(MatIdToSubset));
//////////////////////////////////////////////////////////////////////////
CMesh& mesh = *pIndexedMesh->GetMesh();
AABB bb;
bb.Reset();
for (int i = 0; i < nFacesCount; ++i)
{
const CTriFace& face = pFaces[i];
SMeshFace& meshFace = mesh.m_pFaces[i];
// Remap new used material ID to index of chunk id.
if (!MatIdToSubset[face.MatID])
{
MatIdToSubset[face.MatID] = 1 + nLastSubsetId++;
usedMaterialIds.push_back(face.MatID); // Order of material ids in usedMaterialIds correspond to the indices of chunks.
}
meshFace.nSubset = MatIdToSubset[face.MatID] - 1;
for (int j = 0; j < 3; ++j)
{
const int dstVIdx = i * 3 + j;
mesh.m_pPositions[dstVIdx] = pVertices[face.v[j]].pos;
mesh.m_pNorms[dstVIdx] = SMeshNormal(face.n[j]);
mesh.m_pTexCoord[dstVIdx] = pUV[face.uv[j]];
if (pColors)
{
mesh.m_pColor0[dstVIdx] = pColors[face.v[j]];
}
meshFace.v[j] = dstVIdx;
bb.Add(mesh.m_pPositions[dstVIdx]);
}
}
pIndexedMesh->SetBBox(bb);
pIndexedMesh->SetSubSetCount(usedMaterialIds.size());
for (int i = 0; i < usedMaterialIds.size(); i++)
{
pIndexedMesh->SetSubsetMaterialId(i, usedMaterialIds[i]);
}
pIndexedMesh->Optimize();
}
//////////////////////////////////////////////////////////////////////////
void CTriMesh::CopyStream(CTriMesh& fromMesh, int stream)
{
void* pTrgStream = 0;
void* pSrcStream = 0;
int nElemSize = 0;
fromMesh.GetStreamInfo(stream, pSrcStream, nElemSize);
if (pSrcStream)
{
ReallocStream(stream, fromMesh.GetStreamSize(stream));
GetStreamInfo(stream, pTrgStream, nElemSize);
memcpy(pTrgStream, pSrcStream, nElemSize * fromMesh.GetStreamSize(stream));
}
}
//////////////////////////////////////////////////////////////////////////
void CTriMesh::Copy(CTriMesh& fromMesh, int nCopyFlags)
{
streamSelMask = fromMesh.streamSelMask;
if (nCopyFlags & COPY_VERTICES)
{
CopyStream(fromMesh, VERTICES);
}
if (nCopyFlags & COPY_FACES)
{
CopyStream(fromMesh, FACES);
}
if (nCopyFlags & COPY_EDGES)
{
CopyStream(fromMesh, EDGES);
}
if (nCopyFlags & COPY_TEXCOORDS)
{
CopyStream(fromMesh, TEXCOORDS);
}
if (nCopyFlags & COPY_COLORS)
{
CopyStream(fromMesh, COLORS);
}
if (nCopyFlags & COPY_WEIGHTS)
{
CopyStream(fromMesh, WEIGHTS);
}
if (nCopyFlags & COPY_LINES)
{
CopyStream(fromMesh, LINES);
}
if (nCopyFlags & COPY_VERT_SEL)
{
vertSel = fromMesh.vertSel;
}
if (nCopyFlags & COPY_EDGE_SEL)
{
edgeSel = fromMesh.edgeSel;
}
if (nCopyFlags & COPY_FACE_SEL)
{
faceSel = fromMesh.faceSel;
}
}
//////////////////////////////////////////////////////////////////////////
void CTriMesh::UpdateEdges()
{
SetEdgeCount(GetFacesCount() * 3);
std::map<CTriEdge, int> edgemap;
int nEdges = 0;
for (int i = 0; i < GetFacesCount(); i++)
{
CTriFace& face = pFaces[i];
for (int j = 0; j < 3; j++)
{
int v0 = j;
int v1 = (j != 2) ? j + 1 : 0;
CTriEdge edge;
edge.flags = 0;
// First vertex index must always be smaller.
if (face.v[v0] < face.v[v1])
{
edge.v[0] = face.v[v0];
edge.v[1] = face.v[v1];
}
else
{
edge.v[0] = face.v[v1];
edge.v[1] = face.v[v0];
}
edge.face[0] = i;
edge.face[1] = -1;
int nedge = stl::find_in_map(edgemap, edge, -1);
if (nedge >= 0)
{
// Assign this face as a second member of the edge.
if (pEdges[nedge].face[1] < 0)
{
pEdges[nedge].face[1] = i;
}
face.edge[j] = nedge;
}
else
{
edgemap[edge] = nEdges;
pEdges[nEdges] = edge;
face.edge[j] = nEdges;
nEdges++;
}
}
}
SetEdgeCount(nEdges);
}
//////////////////////////////////////////////////////////////////////////
void CTriMesh::SoftSelection(const SSubObjSelOptions& options)
{
int i;
int nVerts = GetVertexCount();
CTriVertex* pVerts = pVertices;
for (i = 0; i < nVerts; i++)
{
if (pWeights[i] == 1.0f)
{
const Vec3& vp = pVerts[i].pos;
for (int j = 0; j < nVerts; j++)
{
if (pWeights[j] != 1.0f)
{
if (vp.IsEquivalent(pVerts[j].pos, options.fSoftSelFalloff))
{
float fDist = vp.GetDistance(pVerts[j].pos);
if (fDist < options.fSoftSelFalloff)
{
float fWeight = 1.0f - (fDist / options.fSoftSelFalloff);
if (fWeight > pWeights[j])
{
pWeights[j] = fWeight;
}
}
}
}
}
}
}
}
//////////////////////////////////////////////////////////////////////////
bool CTriMesh::UpdateSelection()
{
bool bAnySelected = false;
if (selectionType == SO_ELEM_VERTEX)
{
for (int i = 0; i < GetVertexCount(); i++)
{
if (vertSel[i])
{
bAnySelected = true;
pWeights[i] = 1.0f;
}
else
{
pWeights[i] = 0;
}
}
}
if (selectionType == SO_ELEM_EDGE)
{
// Clear weights.
for (int i = 0; i < GetVertexCount(); i++)
{
pWeights[i] = 0;
}
for (int i = 0; i < GetEdgeCount(); i++)
{
if (edgeSel[i])
{
bAnySelected = true;
CTriEdge& edge = pEdges[i];
for (int j = 0; j < 2; j++)
{
pWeights[edge.v[j]] = 1.0f;
}
}
}
}
else if (selectionType == SO_ELEM_FACE)
{
// Clear weights.
for (int i = 0; i < GetVertexCount(); i++)
{
pWeights[i] = 0;
}
for (int i = 0; i < GetFacesCount(); i++)
{
if (faceSel[i])
{
bAnySelected = true;
CTriFace& face = pFaces[i];
for (int j = 0; j < 3; j++)
{
pWeights[face.v[j]] = 1.0f;
}
}
}
}
return bAnySelected;
}
//////////////////////////////////////////////////////////////////////////
bool CTriMesh::ClearSelection()
{
bool bWasSelected = false;
// Remove all selections.
int i;
for (i = 0; i < GetVertexCount(); i++)
{
pWeights[i] = 0;
}
streamSelMask = 0;
for (int ii = 0; ii < LAST_STREAM; ii++)
{
if (m_streamSel[ii] && !m_streamSel[ii]->is_zero())
{
bWasSelected = true;
m_streamSel[ii]->clear();
}
}
return bWasSelected;
}
//////////////////////////////////////////////////////////////////////////
void CTriMesh::GetEdgesByVertex(MeshElementsArray& inVertices, MeshElementsArray& outEdges)
{
// Brute force algorithm using binary search.
// for every edge check if edge vertex is inside inVertices array.
std::sort(inVertices.begin(), inVertices.end());
for (int i = 0; i < GetEdgeCount(); i++)
{
if (stl::binary_find(inVertices.begin(), inVertices.end(), pEdges[i].v[0]) != inVertices.end())
{
outEdges.push_back(i);
}
else if (stl::binary_find(inVertices.begin(), inVertices.end(), pEdges[i].v[1]) != inVertices.end())
{
outEdges.push_back(i);
}
}
}
//////////////////////////////////////////////////////////////////////////
void CTriMesh::GetFacesByVertex(MeshElementsArray& inVertices, MeshElementsArray& outFaces)
{
// Brute force algorithm using binary search.
// for every face check if face vertex is inside inVertices array.
std::sort(inVertices.begin(), inVertices.end());
for (int i = 0; i < GetFacesCount(); i++)
{
if (stl::binary_find(inVertices.begin(), inVertices.end(), pFaces[i].v[0]) != inVertices.end())
{
outFaces.push_back(i);
}
else if (stl::binary_find(inVertices.begin(), inVertices.end(), pFaces[i].v[1]) != inVertices.end())
{
outFaces.push_back(i);
}
else if (stl::binary_find(inVertices.begin(), inVertices.end(), pFaces[i].v[2]) != inVertices.end())
{
outFaces.push_back(i);
}
}
}
+244
View File
@@ -0,0 +1,244 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef CRYINCLUDE_EDITOR_GEOMETRY_TRIMESH_H
#define CRYINCLUDE_EDITOR_GEOMETRY_TRIMESH_H
#pragma once
#include <IIndexedMesh.h>
#include "Util/bitarray.h"
struct SSubObjSelOptions;
typedef std::vector<int> MeshElementsArray;
//////////////////////////////////////////////////////////////////////////
// Vertex used in the TriMesh.
//////////////////////////////////////////////////////////////////////////
struct CTriVertex
{
Vec3 pos;
//float weight; // Selection weight in 0-1 range.
};
//////////////////////////////////////////////////////////////////////////
// Triangle face used by the Triangle mesh.
//////////////////////////////////////////////////////////////////////////
struct CTriFace
{
uint32 v[3]; // Indices to vertices array.
uint32 uv[3]; // Indices to texture coordinates array.
Vec3 n[3]; // Vertex normals at face vertices.
Vec3 normal; // Face normal.
uint32 edge[3]; // Indices to the face edges.
unsigned char MatID; // Index of face sub material.
unsigned char flags; // see ETriMeshFlags
};
//////////////////////////////////////////////////////////////////////////
// Mesh edge.
//////////////////////////////////////////////////////////////////////////
struct CTriEdge
{
uint32 v[2]; // Indices to edge vertices.
int face[2]; // Indices to edge faces (-1 if no face).
uint32 flags; // see ETriMeshFlags
CTriEdge() {}
bool operator==(const CTriEdge& edge) const
{
if ((v[0] == edge.v[0] && v[1] == edge.v[1]) ||
(v[0] == edge.v[1] && v[1] == edge.v[0]))
{
return true;
}
return false;
}
bool operator!=(const CTriEdge& edge) const { return !(*this == edge); }
bool operator<(const CTriEdge& edge) const { return (*(uint64*)v < *(uint64*)edge.v); }
bool operator>(const CTriEdge& edge) const { return (*(uint64*)v > *(uint64*)edge.v); }
};
//////////////////////////////////////////////////////////////////////////
// Mesh line.
//////////////////////////////////////////////////////////////////////////
struct CTriLine
{
uint32 v[2]; // Indices to edge vertices.
CTriLine() {}
bool operator==(const CTriLine& edge) const
{
if ((v[0] == edge.v[0] && v[1] == edge.v[1]) ||
(v[0] == edge.v[1] && v[1] == edge.v[0]))
{
return true;
}
return false;
}
bool operator!=(const CTriLine& edge) const { return !(*this == edge); }
bool operator<(const CTriLine& edge) const { return (*(uint64*)v < *(uint64*)edge.v); }
bool operator>(const CTriLine& edge) const { return (*(uint64*)v > *(uint64*)edge.v); }
};
//////////////////////////////////////////////////////////////////////////
struct CTriMeshPoly
{
std::vector<uint32> v; // Indices to vertices array.
std::vector<uint32> uv; // Indices to texture coordinates array.
std::vector<Vec3> n; // Vertex normals at face vertices.
Vec3 normal; // Polygon normal.
uint32 edge[3]; // Indices to the face edges.
unsigned char MatID; // Index of face sub material.
unsigned char flags; // optional flags.
};
//////////////////////////////////////////////////////////////////////////
// CTriMesh is used in the Editor as a general purpose editable triangle mesh.
//////////////////////////////////////////////////////////////////////////
class CTriMesh
{
public:
enum EStream
{
VERTICES,
FACES,
EDGES,
TEXCOORDS,
COLORS,
WEIGHTS,
LINES,
WS_POSITIONS,
LAST_STREAM,
};
enum ECopyFlags
{
COPY_VERTICES = BIT(1),
COPY_FACES = BIT(2),
COPY_EDGES = BIT(3),
COPY_TEXCOORDS = BIT(4),
COPY_COLORS = BIT(5),
COPY_VERT_SEL = BIT(6),
COPY_EDGE_SEL = BIT(7),
COPY_FACE_SEL = BIT(8),
COPY_WEIGHTS = BIT(9),
COPY_LINES = BIT(10),
COPY_ALL = 0xFFFF,
};
// geometry data
CTriFace* pFaces;
CTriEdge* pEdges;
CTriVertex* pVertices;
SMeshTexCoord* pUV;
SMeshColor* pColors; // If allocated same size as pVerts array.
Vec3* pWSVertices; // World space vertices.
float* pWeights;
CTriLine* pLines;
int nFacesCount;
int nVertCount;
int nUVCount;
int nEdgeCount;
int nLinesCount;
AABB bbox;
//////////////////////////////////////////////////////////////////////////
// Selections.
//////////////////////////////////////////////////////////////////////////
CBitArray vertSel;
CBitArray edgeSel;
CBitArray faceSel;
// Every bit of the selection mask correspond to a stream, if bit is set this stream have some elements selected
int streamSelMask;
// Selection element type.
// see ESubObjElementType
int selectionType;
//////////////////////////////////////////////////////////////////////////
// Vertices of the front facing triangles.
CBitArray frontFacingVerts;
//////////////////////////////////////////////////////////////////////////
// Functions.
//////////////////////////////////////////////////////////////////////////
CTriMesh();
~CTriMesh();
int GetFacesCount() const { return nFacesCount; }
int GetVertexCount() const { return nVertCount; }
int GetUVCount() const { return nUVCount; }
int GetEdgeCount() const { return nEdgeCount; }
int GetLinesCount() const { return nLinesCount; }
//////////////////////////////////////////////////////////////////////////
void SetFacesCount(int nNewCount) { ReallocStream(FACES, nNewCount); }
void SetVertexCount(int nNewCount)
{
ReallocStream(VERTICES, nNewCount);
if (pColors)
{
ReallocStream(COLORS, nNewCount);
}
ReallocStream(WEIGHTS, nNewCount);
}
void SetColorsCount(int nNewCount) { ReallocStream(COLORS, nNewCount); }
void SetUVCount(int nNewCount) { ReallocStream(TEXCOORDS, nNewCount); }
void SetEdgeCount(int nNewCount) { ReallocStream(EDGES, nNewCount); }
void SetLinesCount(int nNewCount) { ReallocStream(LINES, nNewCount); }
void ReallocStream(int stream, int nNewCount);
void GetStreamInfo(int stream, void*& pStream, int& nElementSize) const;
int GetStreamSize(int stream) const { return m_streamSize[stream]; };
void SetFromMesh(CMesh& mesh);
void UpdateIndexedMesh(IIndexedMesh* pIndexedMesh) const;
// Calculate per face normal.
void CalcFaceNormals();
//////////////////////////////////////////////////////////////////////////
// Welding functions.
//////////////////////////////////////////////////////////////////////////
void SharePositions();
void ShareUV();
//////////////////////////////////////////////////////////////////////////
// Recreate edges of the mesh.
void UpdateEdges();
void Copy(CTriMesh& fromMesh, int nCopyFlags = COPY_ALL);
//////////////////////////////////////////////////////////////////////////
// Sub-object selection specific methods.
//////////////////////////////////////////////////////////////////////////
// Return true if something is selected.
bool UpdateSelection();
// Clear all selections, return true if something was selected.
bool ClearSelection();
void SoftSelection(const SSubObjSelOptions& options);
CBitArray* GetStreamSelection(int nStream) { return m_streamSel[nStream]; };
// Returns true if specified stream have any selected elements.
bool StreamHaveSelection(int nStream) { return streamSelMask & (1 << nStream); }
void GetEdgesByVertex(MeshElementsArray& inVertices, MeshElementsArray& outEdges);
void GetFacesByVertex(MeshElementsArray& inVertices, MeshElementsArray& outFaces);
private:
void* ReAllocElements(void* old_ptr, int new_elem_num, int size_of_element);
void CopyStream(CTriMesh& fromMesh, int stream);
// For internal use.
int m_streamSize[LAST_STREAM];
CBitArray* m_streamSel[LAST_STREAM];
};
#endif // CRYINCLUDE_EDITOR_GEOMETRY_TRIMESH_H