Last active
November 27, 2017 00:25
-
-
Save victorholt/40a22fa3936eb66b0ba5831198aee1d1 to your computer and use it in GitHub Desktop.
CustomMesh Source
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Created by Victor Holt on 3/18/2017. | |
// | |
#include <GameSencha/Game/Graphics/CustomMesh.h> | |
#include <GameSencha/Core/SenchaLogger.h> | |
gs_namespaces | |
//! Constructor. | |
//! \param context | |
//! \param isDynamic | |
CustomMesh::CustomMesh(Context* context, bool isDynamic) | |
: Object(context) | |
{ | |
scale_ = 1.0f; | |
isDynamic_ = isDynamic; | |
calcNormals_ = false; | |
calcTangents_ = false; | |
model_ = nullptr; | |
manualAddIndex_ = false; | |
useLargeIndices_ = false; | |
maxFaceCount_ = CM_MAX_FACES_PER_GEOM_SM; | |
geomData_.Push(new MeshGeomData(0)); | |
} | |
//! Destructor. | |
CustomMesh::~CustomMesh() | |
{ | |
for (auto geoData : geomData_) { | |
delete geoData; | |
} | |
geomData_.Clear(); | |
} | |
//! Adds a face to the mesh. | |
//! \param v0 | |
//! \param v1 | |
//! \param v2 | |
MeshFace* CustomMesh::AddFace(const Vector3& v0, const Vector3& v1, const Vector3& v2, const MeshUVType& uvType) | |
{ | |
faceCount_++; | |
relFaceCount_++; | |
if (relFaceCount_ > maxFaceCount_) { | |
relFaceCount_ = 0; | |
currentGeomIndex_++; | |
geomData_.Push(new MeshGeomData(currentGeomIndex_)); | |
} | |
MeshVertex* vert0 = AddVertex(v0, uvType); | |
MeshVertex* vert1 = AddVertex(v1, uvType); | |
MeshVertex* vert2 = AddVertex(v2, uvType); | |
MeshFace* face = CreateFace(vert0, vert1, vert2); | |
return face; | |
} | |
//! Adds a vertex. | |
//! \param v | |
//! \param uvType | |
MeshVertex* CustomMesh::AddVertex(const Vector3& v, const MeshUVType& uvType) | |
{ | |
vertexCount_++; | |
MutexLock lock(meshLock_); | |
MeshVertex* vert = new MeshVertex(); | |
vert->vertex_ = v; | |
vert->normal_ = Vector3::ZERO; | |
vert->uv_ = Vector2::ZERO; | |
vert->tangent_ = Vector4::ZERO; | |
vert->color_ = Color::WHITE; | |
vert->uvType_ = uvType; | |
geomData_[currentGeomIndex_]->meshVertexList_.Push(vert); | |
geomData_[currentGeomIndex_]->isDirty_ = true; | |
return vert; | |
} | |
//! Adds an index. | |
//! \param index | |
void CustomMesh::AddIndex(uint16_t index) | |
{ | |
indexCount_++; | |
MutexLock lock(meshLock_); | |
geomData_[currentGeomIndex_]->indexData_.Push(index); | |
manualAddIndex_ = true; | |
useLargeIndices_ = false; | |
geomData_[currentGeomIndex_]->isDirty_ = true; | |
} | |
//! Adds an index. | |
//! \param index | |
void CustomMesh::AddLargeIndex(uint32_t index) | |
{ | |
indexCount_++; | |
MutexLock lock(meshLock_); | |
geomData_[currentGeomIndex_]->largeIndexData_.Push(index); | |
useLargeIndices_ = true; | |
manualAddIndex_ = true; | |
geomData_[currentGeomIndex_]->isDirty_ = true; | |
} | |
void CustomMesh::Commit(bool updateNormals, bool updateTangents, bool updateMesh) | |
{ | |
if (geomData_[0]->meshVertexList_.Size() == 0) return; | |
boundingBox_.Clear(); | |
if (IsNullObject(model_)) { | |
for (auto geomData : geomData_) { | |
CreateMesh(geomData, updateNormals, updateTangents, updateMesh); | |
} | |
} else { | |
for (auto geomData : geomData_) { | |
UpdateMesh(geomData, updateNormals, updateTangents, updateMesh); | |
} | |
} | |
} | |
void CustomMesh::CreateMesh(MeshGeomData* geomData, bool updateNormals, bool updateTangents, bool updateMesh) | |
{ | |
MutexLock lock(meshLock_); | |
if (updateNormals) { | |
CalculateNormals(geomData, false); | |
} | |
// if (geomData->isDirty_) { | |
GenerateVertexData(geomData); | |
// } | |
if (updateTangents) { | |
CalculateTangents(geomData, false); | |
UpdateVertexData(geomData); | |
} | |
geomData->isDirty_ = false; | |
if (!updateMesh) { | |
return; | |
} | |
if(IsNullObject(model_)) | |
model_ = new Model(context_); | |
if (IsNullObject(geomData->vertexBuffer_)) | |
geomData->vertexBuffer_ = new VertexBuffer(context_); | |
if (IsNullObject(geomData->indexBuffer_)) | |
geomData->indexBuffer_ = new IndexBuffer(context_); | |
if (IsNullObject(geomData->geometry_)) | |
geomData->geometry_ = new Geometry(context_); | |
geomData->vertexBuffer_->SetShadowed(true); | |
geomData->indexBuffer_->SetShadowed(true); | |
uint32_t numIndices = 0; | |
if (useLargeIndices_) { | |
numIndices = geomData->largeIndexData_.Size(); | |
} else { | |
numIndices = geomData->indexData_.Size(); | |
} | |
PODVector<VertexElement> elements; | |
elements.Push(VertexElement(TYPE_VECTOR3, SEM_POSITION)); | |
elements.Push(VertexElement(TYPE_VECTOR3, SEM_NORMAL)); | |
elements.Push(VertexElement(TYPE_VECTOR2, SEM_TEXCOORD)); | |
if (useUV2_) { | |
elements.Push(VertexElement(TYPE_VECTOR2, SEM_TEXCOORD, 1)); | |
} | |
elements.Push(VertexElement(TYPE_VECTOR4, SEM_TANGENT)); | |
elements.Push(VertexElement(TYPE_VECTOR4, SEM_COLOR)); | |
geomData->vertexBuffer_->SetSize(numIndices, elements, isDynamic_); | |
geomData->indexBuffer_->SetSize(numIndices, useLargeIndices_, isDynamic_); | |
geomData->vertexBuffer_->SetData(geomData->vertexData_.Buffer()); | |
if (useLargeIndices_) { | |
geomData->indexBuffer_->SetData(geomData->largeIndexData_.Buffer()); | |
} else { | |
geomData->indexBuffer_->SetData(geomData->indexData_.Buffer()); | |
} | |
model_->SetBoundingBox(boundingBox_); | |
geomData->geometry_->SetNumVertexBuffers(1); | |
geomData->geometry_->SetVertexBuffer(0, geomData->vertexBuffer_); | |
geomData->geometry_->SetIndexBuffer(geomData->indexBuffer_); | |
geomData->geometry_->SetDrawRange(TRIANGLE_LIST, 0, numIndices); | |
model_->SetNumGeometries(currentGeomIndex_ + 1); | |
model_->SetGeometry(geomData->geomIndex_, 0, geomData->geometry_); | |
Vector<SharedPtr<VertexBuffer>> vertexBuffers; | |
Vector<SharedPtr<IndexBuffer>> indexBuffers; | |
vertexBuffers.Push(geomData->vertexBuffer_); | |
indexBuffers.Push(geomData->indexBuffer_); | |
PODVector<unsigned> morphRangeStarts; | |
PODVector<unsigned> morphRangeCounts; | |
morphRangeStarts.Push(0); | |
morphRangeCounts.Push(0); | |
model_->SetVertexBuffers(vertexBuffers, morphRangeStarts, morphRangeCounts); | |
model_->SetIndexBuffers(indexBuffers); | |
} | |
void CustomMesh::GenerateVertexData(MeshGeomData* geomData) | |
{ | |
if (!manualAddIndex_) { | |
if (useLargeIndices_) { | |
geomData->largeIndexData_.Clear(); | |
geomData->largeIndexData_.Reserve(geomData->meshVertexList_.Size() / 3); | |
} else { | |
geomData->indexData_.Clear(); | |
geomData->indexData_.Reserve(geomData->meshVertexList_.Size() / 3); | |
} | |
} | |
// Create faces. | |
uint16_t lastFaceVertIndexStart = 0; | |
unsigned faceIndex = 0; | |
for (unsigned int i = 0; i < geomData->meshVertexList_.Size(); i += 3) { | |
MeshVertex* v0 = geomData->meshVertexList_[i]; | |
MeshVertex* v1 = geomData->meshVertexList_[i + 1]; | |
MeshVertex* v2 = geomData->meshVertexList_[i + 2]; | |
boundingBox_.Merge(v0->vertex_); | |
boundingBox_.Merge(v1->vertex_); | |
boundingBox_.Merge(v2->vertex_); | |
if (geomData->faces_.Size() > 0) { | |
MeshFace* face = geomData->faces_[faceIndex]; | |
if (!IsNullObject(face)) { | |
face->vertIndexStart_ = i * 12; | |
faceIndex++; | |
} | |
} | |
if (!manualAddIndex_) { | |
if (useLargeIndices_) { | |
geomData->largeIndexData_.Push(lastFaceVertIndexStart); | |
geomData->largeIndexData_.Push(static_cast<uint32_t>(lastFaceVertIndexStart + 1)); | |
geomData->largeIndexData_.Push(static_cast<uint32_t>(lastFaceVertIndexStart + 2)); | |
} else { | |
geomData->indexData_.Push(lastFaceVertIndexStart); | |
geomData->indexData_.Push(static_cast<uint16_t>(lastFaceVertIndexStart + 1)); | |
geomData->indexData_.Push(static_cast<uint16_t>(lastFaceVertIndexStart + 2)); | |
} | |
lastFaceVertIndexStart += 3; | |
} | |
} | |
// Update vertex data. | |
UpdateVertexData(geomData); | |
} | |
void CustomMesh::UpdateVertexData(MeshGeomData* geomData) | |
{ | |
geomData->vertexData_.Clear(); | |
// MeshVertex = 12 | |
geomData->vertexData_.Reserve(geomData->meshVertexList_.Size() * 12); | |
// Update vertex data. | |
int numFaces = geomData->faces_.Size(); | |
for (unsigned int i = 0; i < numFaces; i++) { | |
// Update vertices. | |
// Face #1 | |
geomData->vertexData_.Push(geomData->faces_[i]->v0_->vertex_.x_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v0_->vertex_.y_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v0_->vertex_.z_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v0_->normal_.x_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v0_->normal_.y_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v0_->normal_.z_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v0_->uv_.x_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v0_->uv_.y_); | |
if (useUV2_) { | |
geomData->vertexData_.Push(geomData->faces_[i]->v0_->uv2_.x_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v0_->uv2_.y_); | |
} | |
geomData->vertexData_.Push(geomData->faces_[i]->v0_->tangent_.x_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v0_->tangent_.y_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v0_->tangent_.z_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v0_->tangent_.w_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v0_->color_.r_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v0_->color_.g_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v0_->color_.b_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v0_->color_.a_); | |
// Face #2 | |
geomData->vertexData_.Push(geomData->faces_[i]->v1_->vertex_.x_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v1_->vertex_.y_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v1_->vertex_.z_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v1_->normal_.x_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v1_->normal_.y_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v1_->normal_.z_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v1_->uv_.x_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v1_->uv_.y_); | |
if (useUV2_) { | |
geomData->vertexData_.Push(geomData->faces_[i]->v1_->uv2_.x_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v1_->uv2_.y_); | |
} | |
geomData->vertexData_.Push(geomData->faces_[i]->v1_->tangent_.x_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v1_->tangent_.y_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v1_->tangent_.z_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v1_->tangent_.w_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v1_->color_.r_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v1_->color_.g_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v1_->color_.b_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v1_->color_.a_); | |
// Face #3 | |
geomData->vertexData_.Push(geomData->faces_[i]->v2_->vertex_.x_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v2_->vertex_.y_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v2_->vertex_.z_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v2_->normal_.x_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v2_->normal_.y_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v2_->normal_.z_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v2_->uv_.x_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v2_->uv_.y_); | |
if (useUV2_) { | |
geomData->vertexData_.Push(geomData->faces_[i]->v2_->uv2_.x_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v2_->uv2_.y_); | |
} | |
geomData->vertexData_.Push(geomData->faces_[i]->v2_->tangent_.x_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v2_->tangent_.y_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v2_->tangent_.z_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v2_->tangent_.w_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v2_->color_.r_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v2_->color_.g_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v2_->color_.b_); | |
geomData->vertexData_.Push(geomData->faces_[i]->v2_->color_.a_); | |
} | |
} | |
MeshFace* CustomMesh::CreateFace(MeshVertex* v0, MeshVertex* v1, MeshVertex* v2) | |
{ | |
MeshFace* face = new MeshFace(); | |
face->v0_ = v0; | |
face->v1_ = v1; | |
face->v2_ = v2; | |
MeshUVType uvType = v0->uvType_; | |
if (uvType == MeshUVType::UV_XY) { | |
face->v0_->uv_ = Vector2(v0->vertex_.x_ / scale_, v0->vertex_.y_ / scale_); | |
face->v1_->uv_ = Vector2(v1->vertex_.x_ / scale_, v1->vertex_.y_ / scale_); | |
face->v2_->uv_ = Vector2(v2->vertex_.x_ / scale_, v2->vertex_.y_ / scale_); | |
} else if (uvType == MeshUVType::UV_XZ) { | |
face->v0_->uv_ = Vector2(v0->vertex_.x_ / scale_, v0->vertex_.z_ / scale_); | |
face->v1_->uv_ = Vector2(v1->vertex_.x_ / scale_, v1->vertex_.z_ / scale_); | |
face->v2_->uv_ = Vector2(v2->vertex_.x_ / scale_, v2->vertex_.z_ / scale_); | |
} else if (uvType == MeshUVType::UV_YZ) { | |
face->v0_->uv_ = Vector2(v0->vertex_.y_ / scale_, v0->vertex_.z_ / scale_); | |
face->v1_->uv_ = Vector2(v1->vertex_.y_ / scale_, v1->vertex_.z_ / scale_); | |
face->v2_->uv_ = Vector2(v2->vertex_.y_ / scale_, v2->vertex_.z_ / scale_); | |
} else if (uvType == MeshUVType::UV_ZY) { | |
face->v0_->uv_ = Vector2(v0->vertex_.z_ / scale_, v0->vertex_.y_ / scale_); | |
face->v1_->uv_ = Vector2(v1->vertex_.z_ / scale_, v1->vertex_.y_ / scale_); | |
face->v2_->uv_ = Vector2(v2->vertex_.z_ / scale_, v2->vertex_.y_ / scale_); | |
} | |
face->vertIndexStart_ = 0; | |
geomData_[currentGeomIndex_]->faces_.Push(face); | |
geomData_[currentGeomIndex_]->isDirty_ = true; | |
return face; | |
} | |
void CustomMesh::UpdateMesh(MeshGeomData* geomData, bool updateNormals, bool updateTangents, bool updateMesh) | |
{ | |
MutexLock lock(meshLock_); | |
if (updateNormals) { | |
CalculateNormals(geomData, false); | |
} | |
// if (geomData->isDirty_) { | |
GenerateVertexData(geomData); | |
// } | |
if (updateTangents) { | |
CalculateTangents(geomData, false); | |
UpdateVertexData(geomData); | |
} | |
geomData->isDirty_ = false; | |
if (!updateMesh) { | |
return; | |
} | |
unsigned char* vertexData = (unsigned char*)geomData->vertexBuffer_->Lock(0, geomData->vertexBuffer_->GetVertexCount()); | |
if (!vertexData) return; | |
uint32_t numIndices = 0; | |
numIndices = geomData->faces_.Size() * 3; | |
PODVector<VertexElement> elements; | |
elements.Push(VertexElement(TYPE_VECTOR3, SEM_POSITION)); | |
elements.Push(VertexElement(TYPE_VECTOR3, SEM_NORMAL)); | |
elements.Push(VertexElement(TYPE_VECTOR2, SEM_TEXCOORD)); | |
if (useUV2_) { | |
elements.Push(VertexElement(TYPE_VECTOR2, SEM_TEXCOORD, 1)); | |
} | |
elements.Push(VertexElement(TYPE_VECTOR4, SEM_TANGENT)); | |
elements.Push(VertexElement(TYPE_VECTOR4, SEM_COLOR)); | |
geomData->vertexBuffer_->SetSize(numIndices, elements, isDynamic_); | |
geomData->indexBuffer_->SetSize(numIndices, useLargeIndices_, isDynamic_); | |
geomData->vertexBuffer_->SetData(geomData->vertexData_.Buffer()); | |
if (useLargeIndices_) { | |
geomData->indexBuffer_->SetData(geomData->largeIndexData_.Buffer()); | |
} else { | |
geomData->indexBuffer_->SetData(geomData->indexData_.Buffer()); | |
} | |
model_->SetBoundingBox(boundingBox_); | |
geomData->vertexBuffer_->Unlock(); | |
} | |
//! Updates the bounding box for the mesh. | |
void CustomMesh::UpdateBoundingBox() | |
{ | |
MutexLock lock(calcMeshLock_); | |
boundingBox_.Clear(); | |
for (auto geomData : geomData_) { | |
for (unsigned int i = 0; i < geomData->meshVertexList_.Size(); i += 3) { | |
boundingBox_.Merge(geomData->meshVertexList_[i]->vertex_); | |
boundingBox_.Merge(geomData->meshVertexList_[i + 1]->vertex_); | |
boundingBox_.Merge(geomData->meshVertexList_[i + 2]->vertex_); | |
} | |
} | |
} | |
//! Calculates the mesh normals. | |
//! \param check | |
void CustomMesh::CalculateNormals(bool check) | |
{ | |
for (auto geomData : geomData_) { | |
CalculateNormals(geomData, check); | |
} | |
} | |
//! Calculates the mesh tangents. | |
//! \param check | |
void CustomMesh::CalculateTangents(bool check) | |
{ | |
for (auto geomData : geomData_) { | |
CalculateTangents(geomData, check); | |
} | |
} | |
void CustomMesh::CalculateNormals(MeshGeomData* geomData, bool check) | |
{ | |
MutexLock lock(calcMeshLock_); | |
if (check && calcNormals_) return; | |
calcNormals_ = true; | |
for (unsigned int i = 0; i < geomData->meshVertexList_.Size(); i) { | |
MeshVertex* v0 = geomData->meshVertexList_[i++]; | |
MeshVertex* v1 = geomData->meshVertexList_[i++]; | |
MeshVertex* v2 = geomData->meshVertexList_[i++]; | |
Vector3 edge1 = v0->vertex_ - v1->vertex_; | |
Vector3 edge2 = v0->vertex_ - v2->vertex_; | |
v0->normal_ = v1->normal_ = v2->normal_ = edge1.CrossProduct(edge2).Normalized(); | |
} | |
} | |
void CustomMesh::CalculateTangents(MeshGeomData* geomData, bool check) | |
{ | |
MutexLock lock(calcMeshLock_); | |
if (check && calcTangents_) return; | |
calcTangents_ = true; | |
float* vertData = geomData->vertexData_.Buffer(); | |
uint16_t* indexData = geomData->indexData_.Buffer(); | |
uint32_t* largeIndexData = geomData->largeIndexData_.Buffer(); | |
if (IsNullObject(vertData) || IsNullObject(indexData)) return; | |
int elemSize = useUV2_ ? 18 : 16; | |
int tangentStart = useUV2_ ? 10 : 8; | |
if (!useLargeIndices_) { | |
GenerateTangents(vertData, elemSize * sizeof(float), indexData, sizeof(uint16_t), 0, geomData->faces_.Size() * 3, | |
3 * sizeof(float), 6 * sizeof(float), tangentStart * sizeof(float)); | |
} else { | |
GenerateTangents(vertData, elemSize * sizeof(float), largeIndexData, sizeof(uint32_t), 0, geomData->faces_.Size() * 3, | |
3 * sizeof(float), 6 * sizeof(float), tangentStart * sizeof(float)); | |
} | |
unsigned j = 0; | |
for (unsigned int i = 0; i < geomData->faces_.Size(); i++) { | |
if (useUV2_) { | |
geomData->faces_[i]->v0_->tangent_ = *(reinterpret_cast<Vector4*>(&vertData[ | |
geomData->faces_[i]->vertIndexStart_ + 10])); | |
geomData->faces_[i]->v1_->tangent_ = *(reinterpret_cast<Vector4*>(&vertData[ | |
geomData->faces_[i]->vertIndexStart_ + 14])); | |
geomData->faces_[i]->v2_->tangent_ = *(reinterpret_cast<Vector4*>(&vertData[ | |
geomData->faces_[i]->vertIndexStart_ + 18])); | |
} else { | |
geomData->faces_[i]->v0_->tangent_ = *(reinterpret_cast<Vector4*>(&vertData[ | |
geomData->faces_[i]->vertIndexStart_ + 8])); | |
geomData->faces_[i]->v1_->tangent_ = *(reinterpret_cast<Vector4*>(&vertData[ | |
geomData->faces_[i]->vertIndexStart_ + 12])); | |
geomData->faces_[i]->v2_->tangent_ = *(reinterpret_cast<Vector4*>(&vertData[ | |
geomData->faces_[i]->vertIndexStart_ + 16])); | |
} | |
j += 3; | |
} | |
} | |
//! Updates the texture coordinates. | |
void CustomMesh::UpdateTexCoords() | |
{ | |
MutexLock lock(calcMeshLock_); | |
for (auto geomData : geomData_) { | |
for (unsigned int i = 0; i < geomData->faces_.Size(); i++) { | |
MeshFace* face = geomData->faces_[i]; | |
MeshVertex* v0 = face->v0_; | |
MeshVertex* v1 = face->v1_; | |
MeshVertex* v2 = face->v2_; | |
MeshUVType uvType = face->v0_->uvType_; | |
if (uvType == MeshUVType::UV_XY) { | |
face->v0_->uv_ = Vector2(v0->vertex_.x_, v0->vertex_.y_); | |
face->v1_->uv_ = Vector2(v1->vertex_.x_, v1->vertex_.y_); | |
face->v2_->uv_ = Vector2(v2->vertex_.x_, v2->vertex_.y_); | |
} else if (uvType == MeshUVType::UV_XZ) { | |
face->v0_->uv_ = Vector2(v0->vertex_.x_, v0->vertex_.z_); | |
face->v1_->uv_ = Vector2(v1->vertex_.x_, v1->vertex_.z_); | |
face->v2_->uv_ = Vector2(v2->vertex_.x_, v2->vertex_.z_); | |
} else if (uvType == MeshUVType::UV_YZ) { | |
face->v0_->uv_ = Vector2(v0->vertex_.y_, v0->vertex_.z_); | |
face->v1_->uv_ = Vector2(v1->vertex_.y_, v1->vertex_.z_); | |
face->v2_->uv_ = Vector2(v2->vertex_.y_, v2->vertex_.z_); | |
} else if (uvType == MeshUVType::UV_ZY) { | |
face->v0_->uv_ = Vector2(v0->vertex_.z_, v0->vertex_.y_); | |
face->v1_->uv_ = Vector2(v1->vertex_.z_, v1->vertex_.y_); | |
face->v2_->uv_ = Vector2(v2->vertex_.z_, v2->vertex_.y_); | |
} | |
} | |
} | |
} | |
//! Clears all vertex data of the mesh. | |
void CustomMesh::Clear() | |
{ | |
MutexLock lock(meshLock_); | |
for (auto geomData : geomData_) { | |
for (auto face : geomData->faces_) { | |
delete face; | |
} | |
for (auto vert : geomData->meshVertexList_) { | |
delete vert; | |
} | |
geomData->faces_.Clear(); | |
geomData->meshVertexList_.Clear(); | |
geomData->vertexData_.Clear(); | |
geomData->indexData_.Clear(); | |
geomData->largeIndexData_.Clear(); | |
} | |
boundingBox_.Clear(); | |
} | |
void CustomMesh::Save(const String& path) | |
{ | |
if (IsNullObject(model_)) | |
{ | |
SENCHA_LOGERROR("CustomMesh::Save Mesh is not built"); | |
return; | |
} | |
File file(context_, path, FILE_WRITE); | |
if (file.IsOpen()) { | |
model_->Save(file); | |
} | |
file.Close(); | |
} | |
void CustomMesh::SaveLightmapTexture(const String& path) | |
{ | |
} | |
Geometry* CustomMesh::GetGeometry(uint32_t index) | |
{ | |
return geomData_[index]->geometry_; | |
} | |
Model* CustomMesh::GetModel() | |
{ | |
return model_; | |
} | |
MeshFace* CustomMesh::GetFace(uint32_t geomIndex, uint32_t faceIndex) | |
{ | |
if (geomData_.Size() >= geomIndex) { | |
return nullptr; | |
} | |
MeshGeomData* geomData = geomData_[geomIndex]; | |
if (geomData->faces_.Size() >= faceIndex) { | |
return nullptr; | |
} | |
return geomData->faces_[faceIndex]; | |
} | |
void CustomMesh::PushGeometry() | |
{ | |
MeshGeomData* geomData = geomData_[currentGeomIndex_]; | |
// Ensure we don't push a new geom data if the current | |
// one does not already have faces. | |
if (geomData->faces_.Size() == 0) { | |
return; | |
} | |
currentGeomIndex_++; | |
geomData_.Push(new MeshGeomData(currentGeomIndex_)); | |
} | |
void CustomMesh::RotateFace(MeshFace* face, const Quaternion& rot) | |
{ | |
if (IsNullObject(face)) return; | |
MeshVertex* v0 = face->v0_; | |
MeshVertex* v1 = face->v1_; | |
MeshVertex* v2 = face->v2_; | |
Matrix3x4 transform = Matrix3x4::IDENTITY; | |
transform.SetRotation(rot.RotationMatrix()); | |
BoundingBox boundingBox; | |
boundingBox.Merge(v0->vertex_); | |
boundingBox.Merge(v1->vertex_); | |
boundingBox.Merge(v2->vertex_); | |
Vector3 center = boundingBox.Center(); | |
v0->vertex_ = transform.Rotation().Inverse() * (v0->vertex_ - center); | |
v1->vertex_ = transform.Rotation().Inverse() * (v1->vertex_ - center); | |
v2->vertex_ = transform.Rotation().Inverse() * (v2->vertex_ - center); | |
} | |
void CustomMesh::RotateFaceByIndex(uint32_t geomIndex, unsigned faceIndex, const Quaternion& rot) | |
{ | |
if (geomData_.Size() >= geomIndex) return; | |
MeshGeomData* geomData = geomData_[geomIndex]; | |
if (geomData->faces_.Size() < faceIndex) return; | |
MeshFace* face = geomData->faces_[faceIndex]; | |
RotateFace(face, rot); | |
} | |
void CustomMesh::Rotate(const Quaternion& rot) | |
{ | |
// Go through the vertices and rotate them. | |
transform_.SetRotation(rot.RotationMatrix()); | |
for (auto geomData : geomData_) { | |
for (unsigned int i = 0; i < geomData->meshVertexList_.Size(); i) { | |
MeshVertex* v0 = geomData->meshVertexList_[i++]; | |
MeshVertex* v1 = geomData->meshVertexList_[i++]; | |
MeshVertex* v2 = geomData->meshVertexList_[i++]; | |
BoundingBox boundingBox; | |
boundingBox.Merge(v0->vertex_); | |
boundingBox.Merge(v1->vertex_); | |
boundingBox.Merge(v2->vertex_); | |
Vector3 center = boundingBox.Center(); | |
v0->vertex_ = transform_.Rotation().Inverse() * (v0->vertex_ - center); | |
v1->vertex_ = transform_.Rotation().Inverse() * (v1->vertex_ - center); | |
v2->vertex_ = transform_.Rotation().Inverse() * (v2->vertex_ - center); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment