Skip to content

Instantly share code, notes, and snippets.

@victorholt
Last active November 27, 2017 00:25
Show Gist options
  • Save victorholt/40a22fa3936eb66b0ba5831198aee1d1 to your computer and use it in GitHub Desktop.
Save victorholt/40a22fa3936eb66b0ba5831198aee1d1 to your computer and use it in GitHub Desktop.
CustomMesh Source
//
// 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