git mv Code\Sandbox\Editor Code/Editor

Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
This commit is contained in:
Esteban Papp
2021-06-29 12:41:59 -07:00
parent 9f0bbf3b74
commit e34e36cb35
1415 changed files with 0 additions and 0 deletions
+711
View File
@@ -0,0 +1,711 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#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);
}
}
}
+239
View File
@@ -0,0 +1,239 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#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