[Scummvm-git-logs] scummvm master -> 2b24709eafa9c6a2bd4b8626e46509e514cce223
aquadran
noreply at scummvm.org
Sun Feb 12 14:58:58 UTC 2023
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
2b24709eaf WME3D: Separate XMesh and skin mesh loader to much original code
Commit: 2b24709eafa9c6a2bd4b8626e46509e514cce223
https://github.com/scummvm/scummvm/commit/2b24709eafa9c6a2bd4b8626e46509e514cce223
Author: PaweÅ KoÅodziejski (aquadran at gmail.com)
Date: 2023-02-12T15:58:52+01:00
Commit Message:
WME3D: Separate XMesh and skin mesh loader to much original code
Changed paths:
A engines/wintermute/base/gfx/skin_mesh_helper.cpp
A engines/wintermute/base/gfx/skin_mesh_helper.h
A engines/wintermute/base/gfx/xskinmesh_loader.cpp
A engines/wintermute/base/gfx/xskinmesh_loader.h
engines/wintermute/base/gfx/opengl/meshx_opengl.cpp
engines/wintermute/base/gfx/opengl/meshx_opengl_shader.cpp
engines/wintermute/base/gfx/xmesh.cpp
engines/wintermute/base/gfx/xmesh.h
engines/wintermute/module.mk
diff --git a/engines/wintermute/base/gfx/opengl/meshx_opengl.cpp b/engines/wintermute/base/gfx/opengl/meshx_opengl.cpp
index f9f451a2925..35620f66908 100644
--- a/engines/wintermute/base/gfx/opengl/meshx_opengl.cpp
+++ b/engines/wintermute/base/gfx/opengl/meshx_opengl.cpp
@@ -26,6 +26,8 @@
*/
#include "engines/wintermute/base/gfx/xmaterial.h"
+#include "engines/wintermute/base/gfx/xskinmesh_loader.h"
+#include "engines/wintermute/base/gfx/skin_mesh_helper.h"
#include "graphics/opengl/system_headers.h"
@@ -46,12 +48,16 @@ XMeshOpenGL::~XMeshOpenGL() {
//////////////////////////////////////////////////////////////////////////
bool XMeshOpenGL::render(XModel *model) {
- if (_vertexData == nullptr) {
+ float *vertexData = _skinMesh->_mesh->_vertexData;
+ auto indexData = _skinMesh->_mesh->_indexData;
+ auto indexRanges = _skinMesh->_mesh->_indexRanges;
+ auto materialIndices = _skinMesh->_mesh->_materialIndices;
+ if (vertexData == nullptr) {
return false;
}
for (uint32 i = 0; i < _numAttrs; i++) {
- int materialIndex = _materialIndices[i];
+ int materialIndex = materialIndices[i];
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, _materials[materialIndex]->_diffuse.data);
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, _materials[materialIndex]->_diffuse.data);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, _materials[materialIndex]->_specular.data);
@@ -73,12 +79,12 @@ bool XMeshOpenGL::render(XModel *model) {
if (textureEnable)
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glVertexPointer(3, GL_FLOAT, kVertexComponentCount * sizeof(float), _vertexData + kPositionOffset);
- glNormalPointer(GL_FLOAT, kVertexComponentCount * sizeof(float), _vertexData + kNormalOffset);
+ glVertexPointer(3, GL_FLOAT, XSkinMeshLoader::kVertexComponentCount * sizeof(float), vertexData + XSkinMeshLoader::kPositionOffset);
+ glNormalPointer(GL_FLOAT, XSkinMeshLoader::kVertexComponentCount * sizeof(float), vertexData + XSkinMeshLoader::kNormalOffset);
if (textureEnable)
- glTexCoordPointer(2, GL_FLOAT, kVertexComponentCount * sizeof(float), _vertexData + kTextureCoordOffset);
+ glTexCoordPointer(2, GL_FLOAT, XSkinMeshLoader::kVertexComponentCount * sizeof(float), vertexData + XSkinMeshLoader::kTextureCoordOffset);
- glDrawElements(GL_TRIANGLES, _indexRanges[i + 1] - _indexRanges[i], GL_UNSIGNED_SHORT, _indexData.data() + _indexRanges[i]);
+ glDrawElements(GL_TRIANGLES, indexRanges[i + 1] - indexRanges[i], GL_UNSIGNED_SHORT, indexData.data() + indexRanges[i]);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
diff --git a/engines/wintermute/base/gfx/opengl/meshx_opengl_shader.cpp b/engines/wintermute/base/gfx/opengl/meshx_opengl_shader.cpp
index b2c14985c8c..031b2466547 100644
--- a/engines/wintermute/base/gfx/opengl/meshx_opengl_shader.cpp
+++ b/engines/wintermute/base/gfx/opengl/meshx_opengl_shader.cpp
@@ -26,6 +26,8 @@
*/
#include "engines/wintermute/base/gfx/xmaterial.h"
+#include "engines/wintermute/base/gfx/xskinmesh_loader.h"
+#include "engines/wintermute/base/gfx/skin_mesh_helper.h"
#include "graphics/opengl/system_headers.h"
@@ -50,12 +52,16 @@ XMeshOpenGLShader::~XMeshOpenGLShader() {
}
bool XMeshOpenGLShader::loadFromXData(const Common::String &filename, XFileData *xobj, Common::Array<MaterialReference> &materialReferences) {
+ auto indexData = _skinMesh->_mesh->_indexData;
+ float *vertexData = _skinMesh->_mesh->_vertexData;
+ uint32 vertexCount = _skinMesh->_mesh->_vertexCount;
+
if (XMesh::loadFromXData(filename, xobj, materialReferences)) {
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
- glBufferData(GL_ARRAY_BUFFER, 4 * kVertexComponentCount * _vertexCount, _vertexData, GL_DYNAMIC_DRAW);
+ glBufferData(GL_ARRAY_BUFFER, 4 * XSkinMeshLoader::kVertexComponentCount * vertexCount, vertexData, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, 2 * _indexData.size(), _indexData.data(), GL_STATIC_DRAW);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, 2 * indexData.size(), indexData.data(), GL_STATIC_DRAW);
return true;
}
@@ -65,20 +71,23 @@ bool XMeshOpenGLShader::loadFromXData(const Common::String &filename, XFileData
//////////////////////////////////////////////////////////////////////////
bool XMeshOpenGLShader::render(XModel *model) {
- if (_vertexData == nullptr) {
+ float *vertexData = _skinMesh->_mesh->_vertexData;
+ auto indexRanges = _skinMesh->_mesh->_indexRanges;
+ auto materialIndices = _skinMesh->_mesh->_materialIndices;
+ if (vertexData == nullptr) {
return false;
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
- _shader->enableVertexAttribute("position", _vertexBuffer, 3, GL_FLOAT, false, 4 * kVertexComponentCount, 4 * kPositionOffset);
- _shader->enableVertexAttribute("texcoord", _vertexBuffer, 2, GL_FLOAT, false, 4 * kVertexComponentCount, 4 * kTextureCoordOffset);
- _shader->enableVertexAttribute("normal", _vertexBuffer, 3, GL_FLOAT, false, 4 * kVertexComponentCount, 4 * kNormalOffset);
+ _shader->enableVertexAttribute("position", _vertexBuffer, 3, GL_FLOAT, false, 4 * XSkinMeshLoader::kVertexComponentCount, 4 * XSkinMeshLoader::kPositionOffset);
+ _shader->enableVertexAttribute("texcoord", _vertexBuffer, 2, GL_FLOAT, false, 4 * XSkinMeshLoader::kVertexComponentCount, 4 * XSkinMeshLoader::kTextureCoordOffset);
+ _shader->enableVertexAttribute("normal", _vertexBuffer, 3, GL_FLOAT, false, 4 * XSkinMeshLoader::kVertexComponentCount, 4 * XSkinMeshLoader::kNormalOffset);
_shader->use(true);
for (uint32 i = 0; i < _numAttrs; i++) {
- int materialIndex = _materialIndices[i];
+ int materialIndex = materialIndices[i];
if (_materials[materialIndex]->getSurface()) {
glEnable(GL_TEXTURE_2D);
@@ -93,8 +102,8 @@ bool XMeshOpenGLShader::render(XModel *model) {
_shader->setUniform("diffuse", diffuse);
_shader->setUniform("ambient", diffuse);
- size_t offset = 2 * _indexRanges[i];
- glDrawElements(GL_TRIANGLES, _indexRanges[i + 1] - _indexRanges[i], GL_UNSIGNED_SHORT, (void *)offset);
+ size_t offset = 2 * indexRanges[i];
+ glDrawElements(GL_TRIANGLES, indexRanges[i + 1] - indexRanges[i], GL_UNSIGNED_SHORT, (void *)offset);
}
glBindTexture(GL_TEXTURE_2D, 0);
@@ -107,16 +116,18 @@ bool XMeshOpenGLShader::render(XModel *model) {
}
bool XMeshOpenGLShader::renderFlatShadowModel() {
- if (_vertexData == nullptr) {
+ float *vertexData = _skinMesh->_mesh->_vertexData;
+ auto indexRanges = _skinMesh->_mesh->_indexRanges;
+ if (vertexData == nullptr) {
return false;
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
- _flatShadowShader->enableVertexAttribute("position", _vertexBuffer, 3, GL_FLOAT, false, 4 * kVertexComponentCount, 4 * kPositionOffset);
+ _flatShadowShader->enableVertexAttribute("position", _vertexBuffer, 3, GL_FLOAT, false, 4 * XSkinMeshLoader::kVertexComponentCount, 4 * XSkinMeshLoader::kPositionOffset);
_flatShadowShader->use(true);
- glDrawElements(GL_TRIANGLES, _indexRanges.back(), GL_UNSIGNED_SHORT, 0);
+ glDrawElements(GL_TRIANGLES, indexRanges.back(), GL_UNSIGNED_SHORT, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
@@ -127,8 +138,11 @@ bool XMeshOpenGLShader::renderFlatShadowModel() {
bool XMeshOpenGLShader::update(FrameNode *parentFrame) {
XMesh::update(parentFrame);
+ float *vertexData = _skinMesh->_mesh->_vertexData;
+ uint32 vertexCount = _skinMesh->_mesh->_vertexCount;
+
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * kVertexComponentCount * _vertexCount, _vertexData);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * XSkinMeshLoader::kVertexComponentCount * vertexCount, vertexData);
return true;
}
diff --git a/engines/wintermute/base/gfx/skin_mesh_helper.cpp b/engines/wintermute/base/gfx/skin_mesh_helper.cpp
new file mode 100644
index 00000000000..9f95c6be3ca
--- /dev/null
+++ b/engines/wintermute/base/gfx/skin_mesh_helper.cpp
@@ -0,0 +1,84 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*
+ * This file is based on WME.
+ * http://dead-code.org/redir.php?target=wme
+ * Copyright (c) 2003-2013 Jan Nedoma and contributors
+ */
+
+#include "engines/wintermute/dcgf.h"
+#include "engines/wintermute/base/gfx/skin_mesh_helper.h"
+#include "engines/wintermute/base/gfx/xskinmesh_loader.h"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////////
+SkinMeshHelper::SkinMeshHelper(XSkinMeshLoader *mesh) {
+ _mesh = mesh;
+}
+
+//////////////////////////////////////////////////////////////////////////
+SkinMeshHelper::~SkinMeshHelper() {
+ delete _mesh;
+}
+
+//////////////////////////////////////////////////////////////////////////
+uint SkinMeshHelper::getNumFaces() {
+ return 0;//_mesh->getNumFaces();
+}
+
+//////////////////////////////////////////////////////////////////////////
+uint SkinMeshHelper::getNumBones() {
+ return 0;//_mesh->getNumBones();
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool SkinMeshHelper::getOriginalMesh(XSkinMeshLoader **mesh) {
+ return true;//_mesh->cloneMeshFVF(_mesh->getOptions(), _mesh->getFVF(), mesh);
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool SkinMeshHelper::generateSkinnedMesh(uint32 options, float minWeight, uint32 *adjacencyOut, XSkinMeshLoader **mesh) {
+ bool res = getOriginalMesh(mesh);
+ /* if (res) {
+ (*mesh)->generateAdjacency(adjacencyOut);
+ }*/
+
+ return res;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool SkinMeshHelper::updateSkinnedMesh(const Math::Matrix4 *boneTransforms, XSkinMeshLoader *mesh) {
+ return true;//_mesh->updateSkinnedMesh(boneTransforms);
+}
+
+//////////////////////////////////////////////////////////////////////////
+const char *SkinMeshHelper::getBoneName(uint boneIndex) {
+ return "";//_mesh->getBoneName(boneIndex);
+}
+
+//////////////////////////////////////////////////////////////////////////
+Math::Matrix4 SkinMeshHelper::getBoneOffsetMatrix(uint boneIndex) {
+ return Math::Matrix4();//_mesh->getBoneOffsetMatrix(boneIndex);
+}
+
+} // namespace Wintermute
diff --git a/engines/wintermute/base/gfx/skin_mesh_helper.h b/engines/wintermute/base/gfx/skin_mesh_helper.h
new file mode 100644
index 00000000000..a8e847bd034
--- /dev/null
+++ b/engines/wintermute/base/gfx/skin_mesh_helper.h
@@ -0,0 +1,64 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*
+ * This file is based on WME.
+ * http://dead-code.org/redir.php?target=wme
+ * Copyright (c) 2003-2013 Jan Nedoma and contributors
+ */
+
+#ifndef WINTERMUTE_SKIN_MESH_HELPER_H
+#define WINTERMUTE_SKIN_MESH_HELPER_H
+
+#include "math/matrix4.h"
+#include "math/vector3d.h"
+
+namespace Wintermute {
+
+class XSkinMeshLoader;
+class XMesh;
+class XMeshOpenGL;
+class XMeshOpenGLShader;
+
+class SkinMeshHelper {
+ friend class XMesh;
+ friend class XMeshOpenGL;
+ friend class XMeshOpenGLShader;
+
+public:
+ SkinMeshHelper(XSkinMeshLoader *mesh);
+ virtual ~SkinMeshHelper();
+
+ uint getNumFaces();
+ uint getNumBones();
+ bool getOriginalMesh(XSkinMeshLoader **mesh);
+ bool generateSkinnedMesh(uint32 options, float minWeight, uint32 *adjacencyOut, XSkinMeshLoader **mesh);
+ bool updateSkinnedMesh(const Math::Matrix4 *boneTransforms, XSkinMeshLoader *mesh);
+ const char *getBoneName(uint boneIndex);
+ Math::Matrix4 getBoneOffsetMatrix(uint boneIndex);
+
+private:
+ XSkinMeshLoader *_mesh;
+};
+
+} // namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/gfx/xmesh.cpp b/engines/wintermute/base/gfx/xmesh.cpp
index ebcdc0b2062..7161944108b 100644
--- a/engines/wintermute/base/gfx/xmesh.cpp
+++ b/engines/wintermute/base/gfx/xmesh.cpp
@@ -28,6 +28,8 @@
#include "engines/wintermute/base/gfx/3dshadow_volume.h"
#include "engines/wintermute/base/gfx/xmaterial.h"
#include "engines/wintermute/base/gfx/xmesh.h"
+#include "engines/wintermute/base/gfx/xskinmesh_loader.h"
+#include "engines/wintermute/base/gfx/skin_mesh_helper.h"
#include "engines/wintermute/base/gfx/xframe_node.h"
#include "engines/wintermute/base/gfx/xfile_loader.h"
#include "engines/wintermute/base/gfx/xmodel.h"
@@ -36,27 +38,18 @@
namespace Wintermute {
-// define constant to make it available to the linker
-const uint32 XMesh::kNullIndex;
-
XMesh::XMesh(Wintermute::BaseGame *inGame) : BaseNamedObject(inGame) {
_numAttrs = 0;
+
+ _skinMesh = nullptr;
_skinnedMesh = false;
_BBoxStart = Math::Vector3d(0.0f, 0.0f, 0.0f);
_BBoxEnd = Math::Vector3d(0.0f, 0.0f, 0.0f);
-
- _vertexData = nullptr;
- _vertexPositionData = nullptr;
- _vertexNormalData = nullptr;
- _vertexCount = 0;
}
XMesh::~XMesh() {
- delete[] _vertexData;
- delete[] _vertexPositionData;
- delete[] _vertexNormalData;
-
+ delete _skinMesh;
_materials.clear();
}
@@ -68,28 +61,31 @@ bool XMesh::loadFromXData(const Common::String &filename, XFileData *xobj, Commo
return false;
}
- XMeshObject *mesh = xobj->getXMeshObject();
- if (!mesh) {
+ XMeshObject *meshObject = xobj->getXMeshObject();
+ if (!meshObject) {
BaseEngine::LOG(0, "Error loading skin mesh");
return false;
}
- _vertexCount = mesh->_numVertices;
+ XSkinMeshLoader *mesh = new XSkinMeshLoader(this);
+ _skinMesh = new SkinMeshHelper(mesh);
+
+ mesh->_vertexCount = meshObject->_numVertices;
// vertex format for .X meshes will be position + normals + textures
- _vertexData = new float[kVertexComponentCount * _vertexCount]();
- _vertexPositionData = new float[3 * _vertexCount]();
+ mesh->_vertexData = new float[XSkinMeshLoader::kVertexComponentCount * mesh->_vertexCount]();
+ mesh->_vertexPositionData = new float[3 * mesh->_vertexCount]();
// we already know how big this is supposed to be
// TODO: might have to generate normals if file does not contain any
- _vertexNormalData = new float[3 * _vertexCount]();
+ mesh->_vertexNormalData = new float[3 * mesh->_vertexCount]();
- parsePositionCoords(mesh);
+ mesh->parsePositionCoords(meshObject);
- int faceCount = mesh->_numFaces;
+ int faceCount = meshObject->_numFaces;
Common::Array<int> indexCountPerFace;
- parseFaces(mesh, faceCount, indexCountPerFace);
+ mesh->parseFaces(meshObject, faceCount, indexCountPerFace);
uint numChildren = 0;
xobj->getChildren(numChildren);
@@ -100,11 +96,11 @@ bool XMesh::loadFromXData(const Common::String &filename, XFileData *xobj, Commo
if (xobj->getChild(i, xchildData)) {
if (xchildData.getType(objectType)) {
if (objectType == kXClassMeshTextureCoords) {
- parseTextureCoords(&xchildData);
+ mesh->parseTextureCoords(&xchildData);
} else if (objectType == kXClassMeshNormals) {
- parseNormalCoords(&xchildData);
+ mesh->parseNormalCoords(&xchildData);
} else if (objectType == kXClassMeshMaterialList) {
- parseMaterials(&xchildData, faceCount, filename, materialReferences, indexCountPerFace);
+ mesh->parseMaterials(&xchildData, _gameRef, faceCount, filename, materialReferences, indexCountPerFace);
} else if (objectType == kXClassMaterial) {
Material *mat = new Material(_gameRef);
mat->loadFromX(&xchildData, filename);
@@ -112,77 +108,33 @@ bool XMesh::loadFromXData(const Common::String &filename, XFileData *xobj, Commo
// one material = one index range
_numAttrs = 1;
- _indexRanges.push_back(0);
- _indexRanges.push_back(_indexData.size());
+ mesh->_indexRanges.push_back(0);
+ mesh->_indexRanges.push_back(mesh->_indexData.size());
} else if (objectType == kXClassSkinMeshHeader) {
int boneCount = xchildData.getXSkinMeshHeaderObject()->_nBones;
_skinnedMesh = boneCount > 0;
} else if (objectType == kXClassSkinWeights) {
_skinnedMesh = true;
- parseSkinWeights(&xchildData);
+ mesh->parseSkinWeights(&xchildData);
} else if (objectType == kXClassDeclData) {
- parseVertexDeclaration(&xchildData);
+ mesh->parseVertexDeclaration(&xchildData);
}
}
}
}
- generateAdjacency();
-
- return true;
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool XMesh::generateAdjacency() {
- _adjacency = Common::Array<uint32>(_indexData.size(), kNullIndex);
-
- for (uint32 i = 0; i < _indexData.size() / 3; ++i) {
- for (uint32 j = i + 1; j < _indexData.size() / 3; ++j) {
- for (int edge1 = 0; edge1 < 3; ++edge1) {
- uint16 index1 = _indexData[i * 3 + edge1];
- uint16 index2 = _indexData[i * 3 + (edge1 + 1) % 3];
-
- for (int edge2 = 0; edge2 < 3; ++edge2) {
- uint16 index3 = _indexData[j * 3 + edge2];
- uint16 index4 = _indexData[j * 3 + (edge2 + 1) % 3];
-
- if (_adjacency[i * 3 + edge1] == kNullIndex && _adjacency[j * 3 + edge2] == kNullIndex && adjacentEdge(index1, index2, index3, index4)) {
- _adjacency[i * 3 + edge1] = j;
- _adjacency[j * 3 + edge2] = i;
-
- break;
- }
- }
- }
- }
- }
+ mesh->generateAdjacency(_adjacency);
return true;
}
-bool XMesh::adjacentEdge(uint16 index1, uint16 index2, uint16 index3, uint16 index4) {
- Math::Vector3d vertex1(_vertexPositionData + 3 * index1);
- Math::Vector3d vertex2(_vertexPositionData + 3 * index2);
- Math::Vector3d vertex3(_vertexPositionData + 3 * index3);
- Math::Vector3d vertex4(_vertexPositionData + 3 * index4);
-
- // wme uses a function from the D3DX library, which takes in an epsilon for floating point comparison
- // wme passes in zero, so we just do a direct comparison
- if (vertex1 == vertex3 && vertex2 == vertex4) {
- return true;
- } else if (vertex1 == vertex4 && vertex2 == vertex3) {
- return true;
- }
-
- return false;
-}
-
//////////////////////////////////////////////////////////////////////////
bool XMesh::findBones(FrameNode *rootFrame) {
// normal meshes don't have bones
if (!_skinnedMesh) {
return true;
}
+ auto skinWeightsList = _skinMesh->_mesh->_skinWeightsList;
_boneMatrices.resize(skinWeightsList.size());
@@ -201,10 +153,16 @@ bool XMesh::findBones(FrameNode *rootFrame) {
//////////////////////////////////////////////////////////////////////////
bool XMesh::update(FrameNode *parentFrame) {
- if (_vertexData == nullptr) {
+ float *vertexData = _skinMesh->_mesh->_vertexData;
+ if (vertexData == nullptr) {
return false;
}
+ float *vertexPositionData = _skinMesh->_mesh->_vertexPositionData;
+ float *vertexNormalData = _skinMesh->_mesh->_vertexNormalData;
+ uint32 vertexCount = _skinMesh->_mesh->_vertexCount;
+ auto skinWeightsList = _skinMesh->_mesh->_skinWeightsList;
+
// update skinned mesh
if (_skinnedMesh) {
BaseArray<Math::Matrix4> finalBoneMatrices;
@@ -217,9 +175,9 @@ bool XMesh::update(FrameNode *parentFrame) {
// the new vertex coordinates are the weighted sum of the product
// of the combined bone transformation matrices and the static pose coordinates
// to be able too add the weighted summands together, we reset everything to zero first
- for (uint32 i = 0; i < _vertexCount; ++i) {
+ for (uint32 i = 0; i < vertexCount; ++i) {
for (int j = 0; j < 3; ++j) {
- _vertexData[i * kVertexComponentCount + kPositionOffset + j] = 0.0f;
+ vertexData[i * XSkinMeshLoader::kVertexComponentCount + XSkinMeshLoader::kPositionOffset + j] = 0.0f;
}
}
@@ -231,12 +189,12 @@ bool XMesh::update(FrameNode *parentFrame) {
for (uint i = 0; i < skinWeightsList[boneIndex]._vertexIndices.size(); ++i) {
uint32 vertexIndex = skinWeightsList[boneIndex]._vertexIndices[i];
Math::Vector3d pos;
- pos.setData(_vertexPositionData + vertexIndex * 3);
+ pos.setData(vertexPositionData + vertexIndex * 3);
finalBoneMatrices[boneIndex].transform(&pos, true);
pos *= skinWeightsList[boneIndex]._vertexWeights[i];
for (uint j = 0; j < 3; ++j) {
- _vertexData[vertexIndex * kVertexComponentCount + kPositionOffset + j] += pos.getData()[j];
+ vertexData[vertexIndex * XSkinMeshLoader::kVertexComponentCount + XSkinMeshLoader::kPositionOffset + j] += pos.getData()[j];
}
}
}
@@ -248,9 +206,9 @@ bool XMesh::update(FrameNode *parentFrame) {
}
// reset so we can form the weighted sums
- for (uint32 i = 0; i < _vertexCount; ++i) {
+ for (uint32 i = 0; i < vertexCount; ++i) {
for (int j = 0; j < 3; ++j) {
- _vertexData[i * kVertexComponentCount + kNormalOffset + j] = 0.0f;
+ vertexData[i * XSkinMeshLoader::kVertexComponentCount + XSkinMeshLoader::kNormalOffset + j] = 0.0f;
}
}
@@ -258,24 +216,24 @@ bool XMesh::update(FrameNode *parentFrame) {
for (uint i = 0; i < skinWeightsList[boneIndex]._vertexIndices.size(); ++i) {
uint32 vertexIndex = skinWeightsList[boneIndex]._vertexIndices[i];
Math::Vector3d pos;
- pos.setData(_vertexNormalData + vertexIndex * 3);
+ pos.setData(vertexNormalData + vertexIndex * 3);
finalBoneMatrices[boneIndex].transform(&pos, true);
pos *= skinWeightsList[boneIndex]._vertexWeights[i];
for (uint j = 0; j < 3; ++j) {
- _vertexData[vertexIndex * kVertexComponentCount + kNormalOffset + j] += pos.getData()[j];
+ vertexData[vertexIndex * XSkinMeshLoader::kVertexComponentCount + XSkinMeshLoader::kNormalOffset + j] += pos.getData()[j];
}
}
}
//updateNormals();
} else { // update static
- for (uint32 i = 0; i < _vertexCount; ++i) {
- Math::Vector3d pos(_vertexPositionData + 3 * i);
+ for (uint32 i = 0; i < vertexCount; ++i) {
+ Math::Vector3d pos(vertexPositionData + 3 * i);
parentFrame->getCombinedMatrix()->transform(&pos, true);
for (uint j = 0; j < 3; ++j) {
- _vertexData[i * kVertexComponentCount + kPositionOffset + j] = pos.getData()[j];
+ vertexData[i * XSkinMeshLoader::kVertexComponentCount + XSkinMeshLoader::kPositionOffset + j] = pos.getData()[j];
}
}
}
@@ -287,7 +245,8 @@ bool XMesh::update(FrameNode *parentFrame) {
//////////////////////////////////////////////////////////////////////////
bool XMesh::updateShadowVol(ShadowVolume *shadow, Math::Matrix4 &modelMat, const Math::Vector3d &light, float extrusionDepth) {
- if (_vertexData == nullptr) {
+ float *vertexData = _skinMesh->_mesh->_vertexData;
+ if (vertexData == nullptr) {
return false;
}
@@ -298,17 +257,18 @@ bool XMesh::updateShadowVol(ShadowVolume *shadow, Math::Matrix4 &modelMat, const
uint32 numEdges = 0;
- Common::Array<bool> isFront(_indexData.size() / 3, false);
+ auto indexData = _skinMesh->_mesh->_indexData;
+ Common::Array<bool> isFront(indexData.size() / 3, false);
// First pass : for each face, record if it is front or back facing the light
- for (uint32 i = 0; i < _indexData.size() / 3; i++) {
- uint16 index0 = _indexData[3 * i + 0];
- uint16 index1 = _indexData[3 * i + 1];
- uint16 index2 = _indexData[3 * i + 2];
+ for (uint32 i = 0; i < indexData.size() / 3; i++) {
+ uint16 index0 = indexData[3 * i + 0];
+ uint16 index1 = indexData[3 * i + 1];
+ uint16 index2 = indexData[3 * i + 2];
- Math::Vector3d v0(_vertexData + index0 * kVertexComponentCount + kPositionOffset);
- Math::Vector3d v1(_vertexData + index1 * kVertexComponentCount + kPositionOffset);
- Math::Vector3d v2(_vertexData + index2 * kVertexComponentCount + kPositionOffset);
+ Math::Vector3d v0(vertexData + index0 * XSkinMeshLoader::kVertexComponentCount + XSkinMeshLoader::kPositionOffset);
+ Math::Vector3d v1(vertexData + index1 * XSkinMeshLoader::kVertexComponentCount + XSkinMeshLoader::kPositionOffset);
+ Math::Vector3d v2(vertexData + index2 * XSkinMeshLoader::kVertexComponentCount + XSkinMeshLoader::kPositionOffset);
// Transform vertices or transform light?
Math::Vector3d vNormal = Math::Vector3d::crossProduct(v2 - v1, v1 - v0);
@@ -321,32 +281,32 @@ bool XMesh::updateShadowVol(ShadowVolume *shadow, Math::Matrix4 &modelMat, const
}
// Allocate a temporary edge list
- Common::Array<uint16> edges(_indexData.size() * 2, 0);
+ Common::Array<uint16> edges(indexData.size() * 2, 0);
// First pass : for each face, record if it is front or back facing the light
- for (uint32 i = 0; i < _indexData.size() / 3; i++) {
+ for (uint32 i = 0; i < indexData.size() / 3; i++) {
if (isFront[i]) {
- uint16 wFace0 = _indexData[3 * i + 0];
- uint16 wFace1 = _indexData[3 * i + 1];
- uint16 wFace2 = _indexData[3 * i + 2];
+ uint16 wFace0 = indexData[3 * i + 0];
+ uint16 wFace1 = indexData[3 * i + 1];
+ uint16 wFace2 = indexData[3 * i + 2];
uint32 adjacent0 = _adjacency[3 * i + 0];
uint32 adjacent1 = _adjacency[3 * i + 1];
uint32 adjacent2 = _adjacency[3 * i + 2];
- if (adjacent0 == kNullIndex || isFront[adjacent0] == false) {
+ if (adjacent0 == XSkinMeshLoader::kNullIndex || isFront[adjacent0] == false) {
// add edge v0-v1
edges[2 * numEdges + 0] = wFace0;
edges[2 * numEdges + 1] = wFace1;
numEdges++;
}
- if (adjacent1 == kNullIndex || isFront[adjacent1] == false) {
+ if (adjacent1 == XSkinMeshLoader::kNullIndex || isFront[adjacent1] == false) {
// add edge v1-v2
edges[2 * numEdges + 0] = wFace1;
edges[2 * numEdges + 1] = wFace2;
numEdges++;
}
- if (adjacent2 == kNullIndex || isFront[adjacent2] == false) {
+ if (adjacent2 == XSkinMeshLoader::kNullIndex || isFront[adjacent2] == false) {
// add edge v2-v0
edges[2 * numEdges + 0] = wFace2;
edges[2 * numEdges + 1] = wFace0;
@@ -356,8 +316,8 @@ bool XMesh::updateShadowVol(ShadowVolume *shadow, Math::Matrix4 &modelMat, const
}
for (uint32 i = 0; i < numEdges; i++) {
- Math::Vector3d v1(_vertexData + edges[2 * i + 0] * kVertexComponentCount + kPositionOffset);
- Math::Vector3d v2(_vertexData + edges[2 * i + 1] * kVertexComponentCount + kPositionOffset);
+ Math::Vector3d v1(vertexData + edges[2 * i + 0] * XSkinMeshLoader::kVertexComponentCount + XSkinMeshLoader::kPositionOffset);
+ Math::Vector3d v2(vertexData + edges[2 * i + 1] * XSkinMeshLoader::kVertexComponentCount + XSkinMeshLoader::kPositionOffset);
Math::Vector3d v3 = v1 - invLight * extrusionDepth;
Math::Vector3d v4 = v2 - invLight * extrusionDepth;
@@ -375,23 +335,25 @@ bool XMesh::updateShadowVol(ShadowVolume *shadow, Math::Matrix4 &modelMat, const
//////////////////////////////////////////////////////////////////////////
bool XMesh::pickPoly(Math::Vector3d *pickRayOrig, Math::Vector3d *pickRayDir) {
- if (_vertexData == nullptr) {
+ float *vertexData = _skinMesh->_mesh->_vertexData;
+ if (vertexData == nullptr) {
return false;
}
bool res = false;
- for (uint16 i = 0; i < _indexData.size(); i += 3) {
- uint16 index1 = _indexData[i + 0];
- uint16 index2 = _indexData[i + 1];
- uint16 index3 = _indexData[i + 2];
+ auto indexData = _skinMesh->_mesh->_indexData;
+ for (uint16 i = 0; i < indexData.size(); i += 3) {
+ uint16 index1 = indexData[i + 0];
+ uint16 index2 = indexData[i + 1];
+ uint16 index3 = indexData[i + 2];
Math::Vector3d v0;
- v0.setData(&_vertexData[index1 * kVertexComponentCount + kPositionOffset]);
+ v0.setData(&vertexData[index1 * XSkinMeshLoader::kVertexComponentCount + XSkinMeshLoader::kPositionOffset]);
Math::Vector3d v1;
- v1.setData(&_vertexData[index2 * kVertexComponentCount + kPositionOffset]);
+ v1.setData(&vertexData[index2 * XSkinMeshLoader::kVertexComponentCount + XSkinMeshLoader::kPositionOffset]);
Math::Vector3d v2;
- v2.setData(&_vertexData[index3 * kVertexComponentCount + kPositionOffset]);
+ v2.setData(&vertexData[index3 * XSkinMeshLoader::kVertexComponentCount + XSkinMeshLoader::kPositionOffset]);
if (isnan(v0.x()))
continue;
@@ -444,405 +406,25 @@ bool XMesh::restoreDeviceObjects() {
}
if (_skinnedMesh) {
- return generateAdjacency();
+ return _skinMesh->_mesh->generateAdjacency(_adjacency);
} else {
return true;
}
}
-bool XMesh::parsePositionCoords(XMeshObject *mesh) {
- for (uint i = 0; i < _vertexCount; ++i) {
- _vertexPositionData[i * 3 + 0] = mesh->_vertices[i]._x;
- _vertexPositionData[i * 3 + 1] = mesh->_vertices[i]._y;
- _vertexPositionData[i * 3 + 2] = mesh->_vertices[i]._z;
- for (int j = 0; j < 3; ++j) {
- _vertexData[i * kVertexComponentCount + kPositionOffset + j] = _vertexPositionData[i * 3 + j];
- }
-
- _vertexPositionData[i * 3 + 2] *= -1.0f;
- _vertexData[i * kVertexComponentCount + kPositionOffset + 2] *= -1.0f;
- }
-
- return true;
-}
-
-bool XMesh::parseFaces(XMeshObject *mesh, int faceCount, Common::Array<int> &indexCountPerFace) {
- for (int i = 0; i < faceCount; ++i) {
- XMeshFace *face = &mesh->_faces[i];
- int indexCount = face->_numFaceVertexIndices;
- if (indexCount == 3) {
- uint16 index1 = face->_faceVertexIndices[0];
- uint16 index2 = face->_faceVertexIndices[1];
- uint16 index3 = face->_faceVertexIndices[2];
-
- _indexData.push_back(index3);
- _indexData.push_back(index2);
- _indexData.push_back(index1);
-
- indexCountPerFace.push_back(3);
- } else if (indexCount == 4) {
- uint16 index1 = face->_faceVertexIndices[0];
- uint16 index2 = face->_faceVertexIndices[1];
- uint16 index3 = face->_faceVertexIndices[2];
- uint16 index4 = face->_faceVertexIndices[3];
-
- _indexData.push_back(index3);
- _indexData.push_back(index2);
- _indexData.push_back(index1);
-
- _indexData.push_back(index4);
- _indexData.push_back(index3);
- _indexData.push_back(index1);
-
- indexCountPerFace.push_back(6);
- } else {
- warning("XMeshOpenGL::loadFromX faces with more than four vertices are not supported");
- return false;
- }
- }
-
- return true;
-}
-
-bool XMesh::parseTextureCoords(XFileData *xobj) {
- XMeshTextureCoordsObject *texCoords = xobj->getXMeshTextureCoordsObject();
- if (!texCoords)
- return false;
- // should be the same as _vertexCount
- int textureCoordCount = texCoords->_numTextureCoords;
-
- for (int i = 0; i < textureCoordCount; ++i) {
- _vertexData[i * kVertexComponentCount + kTextureCoordOffset + 0] = texCoords->_textureCoords[i]._u;
- _vertexData[i * kVertexComponentCount + kTextureCoordOffset + 1] = texCoords->_textureCoords[i]._v;
- }
-
- return true;
-}
-
-bool XMesh::parseNormalCoords(XFileData *xobj) {
- XMeshNormalsObject *normals = xobj->getXMeshNormalsObject();
- if (!normals)
- return false;
- // should be the same as _vertex count
- uint vertexNormalCount = normals->_numNormals;
- //assert(vertexNormalCount == _vertexCount);
-
- Common::Array<float> vertexNormalData;
- vertexNormalData.resize(3 * vertexNormalCount);
-
- for (uint i = 0; i < vertexNormalCount; ++i) {
- vertexNormalData[i * 3 + 0] = normals->_normals[i]._x;
- vertexNormalData[i * 3 + 1] = normals->_normals[i]._y;
- // mirror z coordinate to change to OpenGL coordinate system
- vertexNormalData[i * 3 + 2] = -normals->_normals[i]._z;
- }
-
- uint faceNormalCount = normals->_numFaceNormals;
- Common::Array<int> faceNormals;
-
- for (uint i = 0; i < faceNormalCount; ++i) {
- XMeshFace *normalFace = &normals->_faceNormals[i];
- int indexCount = normalFace->_numFaceVertexIndices;
-
- if (indexCount == 3) {
- uint16 index1 = normalFace->_faceVertexIndices[0];
- uint16 index2 = normalFace->_faceVertexIndices[1];
- uint16 index3 = normalFace->_faceVertexIndices[2];
-
- faceNormals.push_back(index3);
- faceNormals.push_back(index2);
- faceNormals.push_back(index1);
- } else if (indexCount == 4) {
- uint16 index1 = normalFace->_faceVertexIndices[0];
- uint16 index2 = normalFace->_faceVertexIndices[1];
- uint16 index3 = normalFace->_faceVertexIndices[2];
- uint16 index4 = normalFace->_faceVertexIndices[3];
-
- faceNormals.push_back(index3);
- faceNormals.push_back(index2);
- faceNormals.push_back(index1);
-
- faceNormals.push_back(index4);
- faceNormals.push_back(index3);
- faceNormals.push_back(index1);
- } else {
- warning("XMeshOpenGL::loadFromX faces with more than four vertices are not supported");
- return false;
- }
- }
-
- assert(_indexData.size() == faceNormals.size());
-
- for (uint i = 0; i < faceNormals.size(); ++i) {
- uint16 vertexIndex = _indexData[i];
- int normalIndex = faceNormals[i];
-
- for (int j = 0; j < 3; ++j) {
- _vertexData[vertexIndex * kVertexComponentCount + kNormalOffset + j] = vertexNormalData[3 * normalIndex + j];
- _vertexNormalData[3 * vertexIndex + j] = vertexNormalData[3 * normalIndex + j];
- }
- }
-
- return true;
-}
-
-bool XMesh::parseMaterials(XFileData *xobj, int faceCount, const Common::String &filename, Common::Array<MaterialReference> &materialReferences, const Common::Array<int> &indexCountPerFace) {
- XMeshMaterialListObject *materialList = xobj->getXMeshMaterialListObject();
- if (!materialList)
- return false;
-
- // there can be unused materials inside a .X file
- // so this piece of information is probably useless
- // should be the same as faceCount
- int faceMaterialCount = materialList->_numFaceIndexes;
- assert(faceMaterialCount == faceCount);
-
- _indexRanges.push_back(0);
- int currentMaterialIndex = materialList->_faceIndexes[0];
- _materialIndices.push_back(currentMaterialIndex);
-
- int currentIndex = indexCountPerFace[0];
-
- for (int i = 1; i < faceMaterialCount; ++i) {
- int currentMaterialIndexTmp = materialList->_faceIndexes[i];
-
- if (currentMaterialIndex != currentMaterialIndexTmp) {
- currentMaterialIndex = currentMaterialIndexTmp;
- _indexRanges.push_back(currentIndex);
- _materialIndices.push_back(currentMaterialIndex);
- }
-
- currentIndex += indexCountPerFace[i];
- }
-
- _indexRanges.push_back(currentIndex);
- _numAttrs = _indexRanges.size() - 1;
-
- uint numChildren = 0;
- xobj->getChildren(numChildren);
-
- for (uint32 i = 0; i < numChildren; i++) {
- XFileData xchildData;
- XClassType objectType;
- bool res = xobj->getChild(i, xchildData);
- if (res) {
- res = xchildData.getType(objectType);
- if (res) {
- if (xchildData.isReference()) {
- Common::String materialReference;
- xchildData.getName(materialReference);
- for (uint32 j = 0; j < materialReferences.size(); j++) {
- if (materialReferences[j]._name == materialReference) {
- _materials.add(materialReferences[j]._material);
- break;
- }
- }
- } else if (objectType == kXClassMaterial) {
- Material *mat = new Material(_gameRef);
- mat->loadFromX(&xchildData, filename);
- _materials.add(mat);
- MaterialReference materialReference;
- materialReference._material = mat;
- materialReferences.push_back(materialReference);
- }
- }
- }
- }
-
- return true;
-}
-
-bool XMesh::parseSkinWeights(XFileData *xobj) {
- XSkinWeightsObject *skinWeights = xobj->getXSkinWeightsObject();
- if (!skinWeights)
- return false;
-
- skinWeightsList.resize(skinWeightsList.size() + 1);
- SkinWeights &currSkinWeights = skinWeightsList.back();
-
- currSkinWeights._boneName = skinWeights->_transformNodeName;
-
- int weightCount = skinWeights->_numWeights;
- currSkinWeights._vertexIndices.resize(weightCount);
- currSkinWeights._vertexWeights.resize(weightCount);
-
- for (int i = 0; i < weightCount; ++i) {
- currSkinWeights._vertexIndices[i] = skinWeights->_vertexIndices[i];
- }
-
- for (int i = 0; i < weightCount; ++i) {
- currSkinWeights._vertexWeights[i] = skinWeights->_weights[i];
- }
-
- for (int r = 0; r < 4; ++r) {
- for (int c = 0; c < 4; ++c) {
- currSkinWeights._offsetMatrix(c, r) = skinWeights->_matrixOffset[r * 4 + c];
- }
- }
-
- // mirror at orign
- currSkinWeights._offsetMatrix(2, 3) *= -1.0f;
-
- // mirror base vectors
- currSkinWeights._offsetMatrix(2, 0) *= -1.0f;
- currSkinWeights._offsetMatrix(2, 1) *= -1.0f;
-
- // change handedness
- currSkinWeights._offsetMatrix(0, 2) *= -1.0f;
- currSkinWeights._offsetMatrix(1, 2) *= -1.0f;
-
- return true;
-}
-
-bool XMesh::parseVertexDeclaration(XFileData *xobj) {
- XDeclDataObject *declData = xobj->getXDeclDataObject();
- if (!declData)
- return false;
-
- int vertexElementCount = declData->_numElements;
-
- // size of a vertex measured in four byte blocks
- int vertexSize = 0;
- int normalOffset = -1;
- int textureOffset = -1;
-
- for (int i = 0; i < vertexElementCount; ++i) {
- int type = declData->_elements[i]._type;
- int method = declData->_elements[i]._method;
- int usage = declData->_elements[i]._usage;
- int usageIndex = declData->_elements[i]._usageIndex;
-
- debug("Vertex Element: Type: %i, Method: %i, Usage: %i, Usage index: %i", type, method, usage, usageIndex);
-
- // we only care about normal vectors and texture coords
- switch (usage) {
- case 3:
- normalOffset = vertexSize;
- break;
- case 5:
- textureOffset = vertexSize;
- break;
- }
-
- // This is a first guess, based on
- // https://docs.microsoft.com/en-us/windows/win32/direct3d9/vertexelement
- switch (type) {
- case 0:
- vertexSize += 1;
- warning("D3DDECLTYPE_FLOAT1 encountered in .X model");
- break;
- case 1:
- vertexSize += 2;
- break;
- case 2:
- vertexSize += 3;
- break;
- case 3:
- vertexSize += 4;
- warning("D3DDECLTYPE_FLOAT4 encountered in .X model");
- break;
- case 4:
- vertexSize += 1;
- warning("D3DDECLTYPE_D3DCOLOR encountered in .X model");
- break;
- case 5:
- vertexSize += 1;
- warning("D3DDECLTYPE_UBYTE4 encountered in .X model");
- break;
- case 6:
- vertexSize += 2;
- warning("D3DDECLTYPE_SHORT2 encountered in .X model");
- break;
- case 7:
- vertexSize += 4;
- warning("D3DDECLTYPE_SHORT4 encountered in .X model");
- break;
- case 8:
- vertexSize += 1;
- warning("D3DDECLTYPE_UBYTE4N encountered in .X model");
- break;
- case 9:
- vertexSize += 2;
- warning("D3DDECLTYPE_SHORT2N encountered in .X model");
- break;
- case 10:
- vertexSize += 4;
- warning("D3DDECLTYPE_SHORT4N encountered in .X model");
- break;
- case 11:
- vertexSize += 2;
- warning("D3DDECLTYPE_USHORT2N encountered in .X model");
- break;
- case 12:
- vertexSize += 4;
- warning("D3DDECLTYPE_USHORT4N encountered in .X model");
- break;
- case 13:
- vertexSize += 3;
- warning("D3DDECLTYPE_UDEC3 encountered in .X model");
- break;
- case 14:
- vertexSize += 3;
- warning("D3DDECLTYPE_DEC3N encountered in .X model");
- break;
- case 15:
- vertexSize += 2;
- warning("D3DDECLTYPE_FLOAT16_2 encountered in .X model");
- break;
- case 16:
- vertexSize += 4;
- warning("D3DDECLTYPE_FLOAT16_4 encountered in .X model");
- break;
- default:
- warning("Unknown type in vertex declaration encountered");
- break;
- }
- }
-
- int dataSize = declData->_numData;
- Common::Array<uint32> data;
- data.reserve(dataSize);
-
- for (int i = 0; i < dataSize; ++i) {
- data.push_back(declData->_data[i]);
- }
-
- assert(dataSize % vertexSize == 0);
- assert(dataSize / vertexSize == static_cast<int>(_vertexCount));
-
- for (uint i = 0; i < _vertexCount; ++i) {
- if (normalOffset != -1) {
- float *vertexNormalData = reinterpret_cast<float *>(data.data() + vertexSize * i + normalOffset);
-
- for (int j = 0; j < 3; ++j) {
- _vertexNormalData[3 * i + j] = vertexNormalData[j];
- _vertexData[kVertexComponentCount * i + kNormalOffset + j] = vertexNormalData[j];
- }
- }
-
- if (textureOffset != -1) {
- float *vertexTextureCoordsData = reinterpret_cast<float *>(data.data() + vertexSize * i + textureOffset);
-
- _vertexData[kVertexComponentCount * i + kTextureCoordOffset + 0] = vertexTextureCoordsData[0];
- _vertexData[kVertexComponentCount * i + kTextureCoordOffset + 1] = vertexTextureCoordsData[1];
- }
- }
-
- return true;
-}
-
void XMesh::updateBoundingBox() {
- if (_vertexData == nullptr || _vertexCount == 0) {
+ float *vertexData = _skinMesh->_mesh->_vertexData;
+ uint32 vertexCount = _skinMesh->_mesh->_vertexCount;
+ if (vertexData == nullptr || vertexCount == 0) {
return;
}
- _BBoxStart.setData(&_vertexData[0 + kPositionOffset]);
- _BBoxEnd.setData(&_vertexData[0 + kPositionOffset]);
-
- for (uint16 i = 1; i < _vertexCount; ++i) {
+ _BBoxStart.setData(&vertexData[0 + XSkinMeshLoader::kPositionOffset]);
+ _BBoxEnd.setData(&vertexData[0 + XSkinMeshLoader::kPositionOffset]);
+ for (uint16 i = 1; i < vertexCount; ++i) {
Math::Vector3d v;
- v.setData(&_vertexData[i * kVertexComponentCount + kPositionOffset]);
+ v.setData(&vertexData[i * XSkinMeshLoader::kVertexComponentCount + XSkinMeshLoader::kPositionOffset]);
_BBoxStart.x() = MIN(_BBoxStart.x(), v.x());
_BBoxStart.y() = MIN(_BBoxStart.y(), v.y());
diff --git a/engines/wintermute/base/gfx/xmesh.h b/engines/wintermute/base/gfx/xmesh.h
index 17542d61142..48349e4d3cf 100644
--- a/engines/wintermute/base/gfx/xmesh.h
+++ b/engines/wintermute/base/gfx/xmesh.h
@@ -40,19 +40,13 @@ namespace Wintermute {
class BaseSprite;
class FrameNode;
class Material;
-class XModel;
class ShadowVolume;
class VideoTheoraPlayer;
+class SkinMeshHelper;
struct XMeshObject;
-struct SkinWeights {
- Common::String _boneName;
- Math::Matrix4 _offsetMatrix;
- BaseArray<uint32> _vertexIndices;
- BaseArray<float> _vertexWeights;
-};
-
class XMesh : public BaseNamedObject {
+ friend class XSkinMeshLoader;
public:
XMesh(BaseGame *inGame);
virtual ~XMesh();
@@ -76,47 +70,23 @@ public:
bool restoreDeviceObjects();
protected:
- static const int kVertexComponentCount = 8;
- static const int kPositionOffset = 5;
- static const int kTextureCoordOffset = 0;
- static const int kNormalOffset = 2;
-
- // anything which does not fit into 16 bits would we fine
- static const uint32 kNullIndex = 0xFFFFFFFF;
-
- bool parsePositionCoords(XMeshObject *mesh);
- bool parseFaces(XMeshObject *mesh, int faceCount, Common::Array<int> &indexCountPerFace);
- bool parseTextureCoords(XFileData *xobj);
- bool parseNormalCoords(XFileData *xobj);
- bool parseMaterials(XFileData *xobj, int faceCount, const Common::String &filename, Common::Array<MaterialReference> &materialReferences, const Common::Array<int> &indexCountPerFace);
- bool parseSkinWeights(XFileData *xobj);
- bool parseVertexDeclaration(XFileData *xobj);
void updateBoundingBox();
- bool generateAdjacency();
- bool adjacentEdge(uint16 index1, uint16 index2, uint16 index3, uint16 index4);
+ uint32 _numAttrs;
+
+ // Wintermute3D used the ID3DXSKININFO interface
+ // we will only store, whether this mesh is skinned at all
+ // and factor out the necessary computations into some functions
+ bool _skinnedMesh;
- float *_vertexData;
- float *_vertexPositionData;
- float *_vertexNormalData;
- uint32 _vertexCount;
- Common::Array<uint16> _indexData;
+ SkinMeshHelper *_skinMesh;
BaseArray<Math::Matrix4 *> _boneMatrices;
- BaseArray<SkinWeights> skinWeightsList;
Common::Array<uint32> _adjacency;
BaseArray<Material *> _materials;
- BaseArray<int> _indexRanges;
- BaseArray<int> _materialIndices;
- uint32 _numAttrs;
-
- // Wintermute3D used the ID3DXSKININFO interface
- // we will only store, whether this mesh is skinned at all
- // and factor out the necessary computations into some functions
- bool _skinnedMesh;
};
} // namespace Wintermute
diff --git a/engines/wintermute/base/gfx/xskinmesh_loader.cpp b/engines/wintermute/base/gfx/xskinmesh_loader.cpp
new file mode 100644
index 00000000000..87c2862fb40
--- /dev/null
+++ b/engines/wintermute/base/gfx/xskinmesh_loader.cpp
@@ -0,0 +1,480 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "engines/wintermute/base/gfx/3dshadow_volume.h"
+#include "engines/wintermute/base/gfx/xmaterial.h"
+#include "engines/wintermute/base/gfx/xskinmesh_loader.h"
+#include "engines/wintermute/base/gfx/xframe_node.h"
+#include "engines/wintermute/base/gfx/xfile_loader.h"
+#include "engines/wintermute/base/gfx/xskinmesh_loader.h"
+#include "engines/wintermute/base/gfx/xmodel.h"
+#include "engines/wintermute/base/base_engine.h"
+#include "engines/wintermute/math/math_util.h"
+
+namespace Wintermute {
+
+// define constant to make it available to the linker
+const uint32 XSkinMeshLoader::kNullIndex;
+
+XSkinMeshLoader::XSkinMeshLoader(XMesh *mesh) {
+ _mesh = mesh;
+
+ _vertexData = nullptr;
+ _vertexPositionData = nullptr;
+ _vertexNormalData = nullptr;
+ _vertexCount = 0;
+}
+
+XSkinMeshLoader::~XSkinMeshLoader() {
+ delete[] _vertexData;
+ delete[] _vertexPositionData;
+ delete[] _vertexNormalData;
+}
+
+bool XSkinMeshLoader::parsePositionCoords(XMeshObject *mesh) {
+ for (uint i = 0; i < _vertexCount; ++i) {
+ _vertexPositionData[i * 3 + 0] = mesh->_vertices[i]._x;
+ _vertexPositionData[i * 3 + 1] = mesh->_vertices[i]._y;
+ _vertexPositionData[i * 3 + 2] = mesh->_vertices[i]._z;
+ for (int j = 0; j < 3; ++j) {
+ _vertexData[i * kVertexComponentCount + kPositionOffset + j] = _vertexPositionData[i * 3 + j];
+ }
+
+ _vertexPositionData[i * 3 + 2] *= -1.0f;
+ _vertexData[i * kVertexComponentCount + kPositionOffset + 2] *= -1.0f;
+ }
+
+ return true;
+}
+
+bool XSkinMeshLoader::parseFaces(XMeshObject *mesh, int faceCount, Common::Array<int> &indexCountPerFace) {
+ for (int i = 0; i < faceCount; ++i) {
+ XMeshFace *face = &mesh->_faces[i];
+ int indexCount = face->_numFaceVertexIndices;
+ if (indexCount == 3) {
+ uint16 index1 = face->_faceVertexIndices[0];
+ uint16 index2 = face->_faceVertexIndices[1];
+ uint16 index3 = face->_faceVertexIndices[2];
+
+ _indexData.push_back(index3);
+ _indexData.push_back(index2);
+ _indexData.push_back(index1);
+
+ indexCountPerFace.push_back(3);
+ } else if (indexCount == 4) {
+ uint16 index1 = face->_faceVertexIndices[0];
+ uint16 index2 = face->_faceVertexIndices[1];
+ uint16 index3 = face->_faceVertexIndices[2];
+ uint16 index4 = face->_faceVertexIndices[3];
+
+ _indexData.push_back(index3);
+ _indexData.push_back(index2);
+ _indexData.push_back(index1);
+
+ _indexData.push_back(index4);
+ _indexData.push_back(index3);
+ _indexData.push_back(index1);
+
+ indexCountPerFace.push_back(6);
+ } else {
+ warning("XMeshLoader::parseFaces faces with more than four vertices are not supported");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool XSkinMeshLoader::parseTextureCoords(XFileData *xobj) {
+ XMeshTextureCoordsObject *texCoords = xobj->getXMeshTextureCoordsObject();
+ if (!texCoords)
+ return false;
+ // should be the same as _vertexCount
+ int textureCoordCount = texCoords->_numTextureCoords;
+
+ for (int i = 0; i < textureCoordCount; ++i) {
+ _vertexData[i * kVertexComponentCount + kTextureCoordOffset + 0] = texCoords->_textureCoords[i]._u;
+ _vertexData[i * kVertexComponentCount + kTextureCoordOffset + 1] = texCoords->_textureCoords[i]._v;
+ }
+
+ return true;
+}
+
+bool XSkinMeshLoader::parseNormalCoords(XFileData *xobj) {
+ XMeshNormalsObject *normals = xobj->getXMeshNormalsObject();
+ if (!normals)
+ return false;
+ // should be the same as _vertex count
+ uint vertexNormalCount = normals->_numNormals;
+ //assert(vertexNormalCount == _vertexCount);
+
+ Common::Array<float> vertexNormalData;
+ vertexNormalData.resize(3 * vertexNormalCount);
+
+ for (uint i = 0; i < vertexNormalCount; ++i) {
+ vertexNormalData[i * 3 + 0] = normals->_normals[i]._x;
+ vertexNormalData[i * 3 + 1] = normals->_normals[i]._y;
+ // mirror z coordinate to change to OpenGL coordinate system
+ vertexNormalData[i * 3 + 2] = -normals->_normals[i]._z;
+ }
+
+ uint faceNormalCount = normals->_numFaceNormals;
+ Common::Array<int> faceNormals;
+
+ for (uint i = 0; i < faceNormalCount; ++i) {
+ XMeshFace *normalFace = &normals->_faceNormals[i];
+ int indexCount = normalFace->_numFaceVertexIndices;
+
+ if (indexCount == 3) {
+ uint16 index1 = normalFace->_faceVertexIndices[0];
+ uint16 index2 = normalFace->_faceVertexIndices[1];
+ uint16 index3 = normalFace->_faceVertexIndices[2];
+
+ faceNormals.push_back(index3);
+ faceNormals.push_back(index2);
+ faceNormals.push_back(index1);
+ } else if (indexCount == 4) {
+ uint16 index1 = normalFace->_faceVertexIndices[0];
+ uint16 index2 = normalFace->_faceVertexIndices[1];
+ uint16 index3 = normalFace->_faceVertexIndices[2];
+ uint16 index4 = normalFace->_faceVertexIndices[3];
+
+ faceNormals.push_back(index3);
+ faceNormals.push_back(index2);
+ faceNormals.push_back(index1);
+
+ faceNormals.push_back(index4);
+ faceNormals.push_back(index3);
+ faceNormals.push_back(index1);
+ } else {
+ warning("XMeshLoader::parseNormalCoords faces with more than four vertices are not supported");
+ return false;
+ }
+ }
+
+ assert(_indexData.size() == faceNormals.size());
+
+ for (uint i = 0; i < faceNormals.size(); ++i) {
+ uint16 vertexIndex = _indexData[i];
+ int normalIndex = faceNormals[i];
+
+ for (int j = 0; j < 3; ++j) {
+ _vertexData[vertexIndex * kVertexComponentCount + kNormalOffset + j] = vertexNormalData[3 * normalIndex + j];
+ _vertexNormalData[3 * vertexIndex + j] = vertexNormalData[3 * normalIndex + j];
+ }
+ }
+
+ return true;
+}
+
+bool XSkinMeshLoader::parseMaterials(XFileData *xobj, BaseGame *inGame,
+ int faceCount, const Common::String &filename,
+ Common::Array<MaterialReference> &materialReferences,
+ const Common::Array<int> &indexCountPerFace) {
+ XMeshMaterialListObject *materialList = xobj->getXMeshMaterialListObject();
+ if (!materialList)
+ return false;
+
+ // there can be unused materials inside a .X file
+ // so this piece of information is probably useless
+ // should be the same as faceCount
+ int faceMaterialCount = materialList->_numFaceIndexes;
+ assert(faceMaterialCount == faceCount);
+
+ _indexRanges.push_back(0);
+ int currentMaterialIndex = materialList->_faceIndexes[0];
+ _materialIndices.push_back(currentMaterialIndex);
+
+ int currentIndex = indexCountPerFace[0];
+
+ for (int i = 1; i < faceMaterialCount; ++i) {
+ int currentMaterialIndexTmp = materialList->_faceIndexes[i];
+
+ if (currentMaterialIndex != currentMaterialIndexTmp) {
+ currentMaterialIndex = currentMaterialIndexTmp;
+ _indexRanges.push_back(currentIndex);
+ _materialIndices.push_back(currentMaterialIndex);
+ }
+
+ currentIndex += indexCountPerFace[i];
+ }
+
+ _indexRanges.push_back(currentIndex);
+ _mesh->_numAttrs = _indexRanges.size() - 1;
+
+ uint numChildren = 0;
+ xobj->getChildren(numChildren);
+
+ for (uint32 i = 0; i < numChildren; i++) {
+ XFileData xchildData;
+ XClassType objectType;
+ bool res = xobj->getChild(i, xchildData);
+ if (res) {
+ res = xchildData.getType(objectType);
+ if (res) {
+ if (xchildData.isReference()) {
+ Common::String materialReference;
+ xchildData.getName(materialReference);
+ for (uint32 j = 0; j < materialReferences.size(); j++) {
+ if (materialReferences[j]._name == materialReference) {
+ _mesh->_materials.add(materialReferences[j]._material);
+ break;
+ }
+ }
+ } else if (objectType == kXClassMaterial) {
+ Material *mat = new Material(inGame);
+ mat->loadFromX(&xchildData, filename);
+ _mesh->_materials.add(mat);
+ MaterialReference materialReference;
+ materialReference._material = mat;
+ materialReferences.push_back(materialReference);
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+bool XSkinMeshLoader::parseSkinWeights(XFileData *xobj) {
+ XSkinWeightsObject *skinWeights = xobj->getXSkinWeightsObject();
+ if (!skinWeights)
+ return false;
+
+ _skinWeightsList.resize(_skinWeightsList.size() + 1);
+ SkinWeights &currSkinWeights = _skinWeightsList.back();
+
+ currSkinWeights._boneName = skinWeights->_transformNodeName;
+
+ int weightCount = skinWeights->_numWeights;
+ currSkinWeights._vertexIndices.resize(weightCount);
+ currSkinWeights._vertexWeights.resize(weightCount);
+
+ for (int i = 0; i < weightCount; ++i) {
+ currSkinWeights._vertexIndices[i] = skinWeights->_vertexIndices[i];
+ }
+
+ for (int i = 0; i < weightCount; ++i) {
+ currSkinWeights._vertexWeights[i] = skinWeights->_weights[i];
+ }
+
+ for (int r = 0; r < 4; ++r) {
+ for (int c = 0; c < 4; ++c) {
+ currSkinWeights._offsetMatrix(c, r) = skinWeights->_matrixOffset[r * 4 + c];
+ }
+ }
+
+ // mirror at orign
+ currSkinWeights._offsetMatrix(2, 3) *= -1.0f;
+
+ // mirror base vectors
+ currSkinWeights._offsetMatrix(2, 0) *= -1.0f;
+ currSkinWeights._offsetMatrix(2, 1) *= -1.0f;
+
+ // change handedness
+ currSkinWeights._offsetMatrix(0, 2) *= -1.0f;
+ currSkinWeights._offsetMatrix(1, 2) *= -1.0f;
+
+ return true;
+}
+
+bool XSkinMeshLoader::parseVertexDeclaration(XFileData *xobj) {
+ XDeclDataObject *declData = xobj->getXDeclDataObject();
+ if (!declData)
+ return false;
+
+ int vertexElementCount = declData->_numElements;
+
+ // size of a vertex measured in four byte blocks
+ int vertexSize = 0;
+ int normalOffset = -1;
+ int textureOffset = -1;
+
+ for (int i = 0; i < vertexElementCount; ++i) {
+ int type = declData->_elements[i]._type;
+ int method = declData->_elements[i]._method;
+ int usage = declData->_elements[i]._usage;
+ int usageIndex = declData->_elements[i]._usageIndex;
+
+ debug(2, "Vertex Element: Type: %i, Method: %i, Usage: %i, Usage index: %i", type, method, usage, usageIndex);
+
+ // we only care about normal vectors and texture coords
+ switch (usage) {
+ case 3:
+ normalOffset = vertexSize;
+ break;
+ case 5:
+ textureOffset = vertexSize;
+ break;
+ }
+
+ // This is a first guess, based on
+ // https://docs.microsoft.com/en-us/windows/win32/direct3d9/vertexelement
+ switch (type) {
+ case 0:
+ vertexSize += 1;
+ warning("D3DDECLTYPE_FLOAT1 encountered in .X model");
+ break;
+ case 1:
+ vertexSize += 2;
+ break;
+ case 2:
+ vertexSize += 3;
+ break;
+ case 3:
+ vertexSize += 4;
+ warning("D3DDECLTYPE_FLOAT4 encountered in .X model");
+ break;
+ case 4:
+ vertexSize += 1;
+ warning("D3DDECLTYPE_D3DCOLOR encountered in .X model");
+ break;
+ case 5:
+ vertexSize += 1;
+ warning("D3DDECLTYPE_UBYTE4 encountered in .X model");
+ break;
+ case 6:
+ vertexSize += 2;
+ warning("D3DDECLTYPE_SHORT2 encountered in .X model");
+ break;
+ case 7:
+ vertexSize += 4;
+ warning("D3DDECLTYPE_SHORT4 encountered in .X model");
+ break;
+ case 8:
+ vertexSize += 1;
+ warning("D3DDECLTYPE_UBYTE4N encountered in .X model");
+ break;
+ case 9:
+ vertexSize += 2;
+ warning("D3DDECLTYPE_SHORT2N encountered in .X model");
+ break;
+ case 10:
+ vertexSize += 4;
+ warning("D3DDECLTYPE_SHORT4N encountered in .X model");
+ break;
+ case 11:
+ vertexSize += 2;
+ warning("D3DDECLTYPE_USHORT2N encountered in .X model");
+ break;
+ case 12:
+ vertexSize += 4;
+ warning("D3DDECLTYPE_USHORT4N encountered in .X model");
+ break;
+ case 13:
+ vertexSize += 3;
+ warning("D3DDECLTYPE_UDEC3 encountered in .X model");
+ break;
+ case 14:
+ vertexSize += 3;
+ warning("D3DDECLTYPE_DEC3N encountered in .X model");
+ break;
+ case 15:
+ vertexSize += 2;
+ warning("D3DDECLTYPE_FLOAT16_2 encountered in .X model");
+ break;
+ case 16:
+ vertexSize += 4;
+ warning("D3DDECLTYPE_FLOAT16_4 encountered in .X model");
+ break;
+ default:
+ warning("Unknown type in vertex declaration encountered");
+ break;
+ }
+ }
+
+ int dataSize = declData->_numData;
+ Common::Array<uint32> data;
+ data.reserve(dataSize);
+
+ for (int i = 0; i < dataSize; ++i) {
+ data.push_back(declData->_data[i]);
+ }
+
+ assert(dataSize % vertexSize == 0);
+ assert(dataSize / vertexSize == static_cast<int>(_vertexCount));
+
+ for (uint i = 0; i < _vertexCount; ++i) {
+ if (normalOffset != -1) {
+ float *vertexNormalData = reinterpret_cast<float *>(data.data() + vertexSize * i + normalOffset);
+
+ for (int j = 0; j < 3; ++j) {
+ _vertexNormalData[3 * i + j] = vertexNormalData[j];
+ _vertexData[kVertexComponentCount * i + kNormalOffset + j] = vertexNormalData[j];
+ }
+ }
+
+ if (textureOffset != -1) {
+ float *vertexTextureCoordsData = reinterpret_cast<float *>(data.data() + vertexSize * i + textureOffset);
+
+ _vertexData[kVertexComponentCount * i + kTextureCoordOffset + 0] = vertexTextureCoordsData[0];
+ _vertexData[kVertexComponentCount * i + kTextureCoordOffset + 1] = vertexTextureCoordsData[1];
+ }
+ }
+
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool XSkinMeshLoader::generateAdjacency(Common::Array<uint32> &adjacency) {
+ adjacency = Common::Array<uint32>(_indexData.size(), XSkinMeshLoader::kNullIndex);
+
+ for (uint32 i = 0; i < _indexData.size() / 3; ++i) {
+ for (uint32 j = i + 1; j < _indexData.size() / 3; ++j) {
+ for (int edge1 = 0; edge1 < 3; ++edge1) {
+ uint16 index1 = _indexData[i * 3 + edge1];
+ uint16 index2 = _indexData[i * 3 + (edge1 + 1) % 3];
+
+ for (int edge2 = 0; edge2 < 3; ++edge2) {
+ uint16 index3 = _indexData[j * 3 + edge2];
+ uint16 index4 = _indexData[j * 3 + (edge2 + 1) % 3];
+
+ if (adjacency[i * 3 + edge1] == XSkinMeshLoader::kNullIndex && adjacency[j * 3 + edge2] == XSkinMeshLoader::kNullIndex && adjacentEdge(index1, index2, index3, index4)) {
+ adjacency[i * 3 + edge1] = j;
+ adjacency[j * 3 + edge2] = i;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+bool XSkinMeshLoader::adjacentEdge(uint16 index1, uint16 index2, uint16 index3, uint16 index4) {
+ Math::Vector3d vertex1(_vertexPositionData + 3 * index1);
+ Math::Vector3d vertex2(_vertexPositionData + 3 * index2);
+ Math::Vector3d vertex3(_vertexPositionData + 3 * index3);
+ Math::Vector3d vertex4(_vertexPositionData + 3 * index4);
+
+ // wme uses a function from the D3DX library, which takes in an epsilon for floating point comparison
+ // wme passes in zero, so we just do a direct comparison
+ if (vertex1 == vertex3 && vertex2 == vertex4) {
+ return true;
+ } else if (vertex1 == vertex4 && vertex2 == vertex3) {
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace Wintermute
diff --git a/engines/wintermute/base/gfx/xskinmesh_loader.h b/engines/wintermute/base/gfx/xskinmesh_loader.h
new file mode 100644
index 00000000000..5beea158374
--- /dev/null
+++ b/engines/wintermute/base/gfx/xskinmesh_loader.h
@@ -0,0 +1,96 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef WINTERMUTE_XSKINMESH_LOADER_H
+#define WINTERMUTE_XSKINMESH_LOADER_H
+
+#include "engines/wintermute/base/gfx/xmodel.h"
+
+#include "math/matrix4.h"
+#include "math/vector3d.h"
+
+namespace Wintermute {
+
+class Material;
+class XModel;
+class XMesh;
+class ShadowVolume;
+class VideoTheoraPlayer;
+struct XMeshObject;
+
+struct SkinWeights {
+ Common::String _boneName;
+ Math::Matrix4 _offsetMatrix;
+ BaseArray<uint32> _vertexIndices;
+ BaseArray<float> _vertexWeights;
+};
+
+class XSkinMeshLoader {
+ friend class XMesh;
+ friend class XMeshOpenGL;
+ friend class XMeshOpenGLShader;
+
+public:
+ XSkinMeshLoader(XMesh *mesh);
+ virtual ~XSkinMeshLoader();
+
+protected:
+ static const int kVertexComponentCount = 8;
+ static const int kPositionOffset = 5;
+ static const int kTextureCoordOffset = 0;
+ static const int kNormalOffset = 2;
+
+ // anything which does not fit into 16 bits would we fine
+ static const uint32 kNullIndex = 0xFFFFFFFF;
+
+ bool generateAdjacency(Common::Array<uint32> &adjacency);
+ bool adjacentEdge(uint16 index1, uint16 index2, uint16 index3, uint16 index4);
+
+public:
+ bool parsePositionCoords(XMeshObject *mesh);
+ bool parseFaces(XMeshObject *mesh, int faceCount, Common::Array<int> &indexCountPerFace);
+ bool parseTextureCoords(XFileData *xobj);
+ bool parseNormalCoords(XFileData *xobj);
+ bool parseMaterials(XFileData *xobj, BaseGame *inGame, int faceCount, const Common::String &filename,
+ Common::Array<MaterialReference> &materialReferences, const Common::Array<int> &indexCountPerFace);
+ bool parseSkinWeights(XFileData *xobj);
+ bool parseVertexDeclaration(XFileData *xobj);
+
+protected:
+
+ float *_vertexData;
+ float *_vertexPositionData;
+ float *_vertexNormalData;
+ uint32 _vertexCount;
+ Common::Array<uint16> _indexData;
+
+ BaseArray<Math::Matrix4 *> _boneMatrices;
+ BaseArray<SkinWeights> _skinWeightsList;
+
+ BaseArray<int> _indexRanges;
+ BaseArray<int> _materialIndices;
+
+ XMesh *_mesh;
+};
+
+} // namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/module.mk b/engines/wintermute/module.mk
index 2e378d266c0..903fbe0a31d 100644
--- a/engines/wintermute/module.mk
+++ b/engines/wintermute/module.mk
@@ -165,6 +165,7 @@ MODULE_OBJS += \
base/gfx/3dmesh.o \
base/gfx/3dshadow_volume.o \
base/gfx/base_renderer3d.o \
+ base/gfx/skin_mesh_helper.o \
base/gfx/xactive_animation.o \
base/gfx/xanimation.o \
base/gfx/xanimation_channel.o \
@@ -175,6 +176,7 @@ MODULE_OBJS += \
base/gfx/xmaterial.o \
base/gfx/xmesh.o \
base/gfx/xmodel.o \
+ base/gfx/xskinmesh_loader.o \
base/gfx/opengl/base_surface_opengl3d.o \
base/gfx/opengl/base_render_opengl3d.o \
base/gfx/opengl/base_render_opengl3d_shader.o \
More information about the Scummvm-git-logs
mailing list