Read Danglymesh header and AABB tree from MDL
This commit is contained in:
parent
100f318c81
commit
ac55ac6a8d
6 changed files with 150 additions and 42 deletions
|
@ -175,6 +175,7 @@ set(RENDER_HEADERS
|
||||||
src/render/materials.h
|
src/render/materials.h
|
||||||
src/render/mesh.h
|
src/render/mesh.h
|
||||||
src/render/meshes.h
|
src/render/meshes.h
|
||||||
|
src/render/model/aabbnode.h
|
||||||
src/render/model/animation.h
|
src/render/model/animation.h
|
||||||
src/render/model/emitter.h
|
src/render/model/emitter.h
|
||||||
src/render/model/mdlreader.h
|
src/render/model/mdlreader.h
|
||||||
|
@ -215,6 +216,7 @@ set(RENDER_SOURCES
|
||||||
src/render/materials.cpp
|
src/render/materials.cpp
|
||||||
src/render/mesh.cpp
|
src/render/mesh.cpp
|
||||||
src/render/meshes.cpp
|
src/render/meshes.cpp
|
||||||
|
src/render/model/aabbnode.cpp
|
||||||
src/render/model/animation.cpp
|
src/render/model/animation.cpp
|
||||||
src/render/model/mdlreader.cpp
|
src/render/model/mdlreader.cpp
|
||||||
src/render/model/model.cpp
|
src/render/model/model.cpp
|
||||||
|
|
0
src/render/model/aabbnode.cpp
Normal file
0
src/render/model/aabbnode.cpp
Normal file
45
src/render/model/aabbnode.h
Normal file
45
src/render/model/aabbnode.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020-2021 The reone project contributors
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "../aabb.h"
|
||||||
|
|
||||||
|
namespace reone {
|
||||||
|
|
||||||
|
namespace render {
|
||||||
|
|
||||||
|
struct AABBNode {
|
||||||
|
enum class Plane {
|
||||||
|
None = 0,
|
||||||
|
PositiveX = 1,
|
||||||
|
PositiveY = 2,
|
||||||
|
PositiveZ = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
int faceIndex { 0 };
|
||||||
|
Plane mostSignificantPlane { Plane::None };
|
||||||
|
AABB aabb;
|
||||||
|
std::shared_ptr<AABBNode> leftChild;
|
||||||
|
std::shared_ptr<AABBNode> rightChild;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace render
|
||||||
|
|
||||||
|
} // namespace reone
|
|
@ -30,9 +30,10 @@
|
||||||
#include "../../resource/gameidutil.h"
|
#include "../../resource/gameidutil.h"
|
||||||
#include "../../resource/resources.h"
|
#include "../../resource/resources.h"
|
||||||
|
|
||||||
#include "../model/models.h"
|
|
||||||
#include "../textures.h"
|
#include "../textures.h"
|
||||||
|
|
||||||
|
#include "models.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
using namespace reone::resource;
|
using namespace reone::resource;
|
||||||
|
@ -591,9 +592,6 @@ unique_ptr<ModelNode> MdlReader::readNode(uint32_t offset, ModelNode *parent) {
|
||||||
if (header.flags & NodeFlags::skin) {
|
if (header.flags & NodeFlags::skin) {
|
||||||
node->_skin = make_shared<ModelNode::Skin>();
|
node->_skin = make_shared<ModelNode::Skin>();
|
||||||
}
|
}
|
||||||
if (header.flags & NodeFlags::aabb) {
|
|
||||||
node->_aabb = true;
|
|
||||||
}
|
|
||||||
if (header.flags & NodeFlags::saber) {
|
if (header.flags & NodeFlags::saber) {
|
||||||
node->_saber = true;
|
node->_saber = true;
|
||||||
}
|
}
|
||||||
|
@ -610,15 +608,18 @@ unique_ptr<ModelNode> MdlReader::readNode(uint32_t offset, ModelNode *parent) {
|
||||||
if (header.flags & NodeFlags::reference) {
|
if (header.flags & NodeFlags::reference) {
|
||||||
readReference(*node);
|
readReference(*node);
|
||||||
}
|
}
|
||||||
// Mesh will be loaded by either readMesh here, or readSaber
|
// Mesh will be loaded by either readMesh here, or readSaber below
|
||||||
if ((header.flags & NodeFlags::mesh) && !(header.flags & NodeFlags::saber)) {
|
if ((header.flags & NodeFlags::mesh) && !(header.flags & NodeFlags::saber)) {
|
||||||
readMesh(*node);
|
readMesh(*node);
|
||||||
}
|
}
|
||||||
if (header.flags & NodeFlags::skin) {
|
if (header.flags & NodeFlags::skin) {
|
||||||
readSkin(*node);
|
readSkin(*node);
|
||||||
}
|
}
|
||||||
|
if (header.flags & NodeFlags::dangly) {
|
||||||
|
readDanglymesh(*node);
|
||||||
|
}
|
||||||
if (header.flags & NodeFlags::aabb) {
|
if (header.flags & NodeFlags::aabb) {
|
||||||
// TODO: read AABB tree
|
readAABB(*node);
|
||||||
}
|
}
|
||||||
if (header.flags & NodeFlags::saber) {
|
if (header.flags & NodeFlags::saber) {
|
||||||
readSaber(*node);
|
readSaber(*node);
|
||||||
|
@ -777,6 +778,38 @@ void MdlReader::readMesh(ModelNode &node) {
|
||||||
loadMesh(header, header.numVertices, move(vertices), move(indices), move(offsets), node);
|
loadMesh(header, header.numVertices, move(vertices), move(indices), move(offsets), node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MdlReader::loadMesh(const MeshHeader &header, int numVertices, vector<float> &&vertices, vector<uint16_t> &&indices, Mesh::VertexOffsets &&offsets, ModelNode &node) {
|
||||||
|
auto mesh = make_unique<Mesh>(numVertices, vertices, indices, offsets);
|
||||||
|
mesh->computeAABB();
|
||||||
|
|
||||||
|
node._mesh = make_unique<ModelMesh>(move(mesh));
|
||||||
|
node._mesh->setRender(static_cast<bool>(header.render));
|
||||||
|
node._mesh->setTransparency(static_cast<int>(header.transparencyHint));
|
||||||
|
node._mesh->setShadow(static_cast<bool>(header.shadow));
|
||||||
|
node._mesh->setBackgroundGeometry(static_cast<bool>(header.backgroundGeometry) != 0);
|
||||||
|
node._mesh->setDiffuseColor(glm::make_vec3(header.diffuse));
|
||||||
|
node._mesh->setAmbientColor(glm::make_vec3(header.ambient));
|
||||||
|
|
||||||
|
string tex1ResRef(getStringLower(header.texture1, 32));
|
||||||
|
string tex2ResRef(getStringLower(header.texture2, 32));
|
||||||
|
string tex3ResRef(getStringLower(header.texture3, 12));
|
||||||
|
string tex4ResRef(getStringLower(header.texture4, 12));
|
||||||
|
|
||||||
|
if (!tex1ResRef.empty() && tex1ResRef != "null") {
|
||||||
|
node._mesh->_diffuse = Textures::instance().get(tex1ResRef, TextureUsage::Diffuse);
|
||||||
|
}
|
||||||
|
if (!tex2ResRef.empty()) {
|
||||||
|
node._mesh->_lightmap = Textures::instance().get(tex2ResRef, TextureUsage::Lightmap);
|
||||||
|
}
|
||||||
|
if (header.animateUV) {
|
||||||
|
node._mesh->_uvAnimation.animated = true;
|
||||||
|
node._mesh->_uvAnimation.directionX = header.uvDirectionX;
|
||||||
|
node._mesh->_uvAnimation.directionY = header.uvDirectionY;
|
||||||
|
node._mesh->_uvAnimation.jitter = header.uvJitter;
|
||||||
|
node._mesh->_uvAnimation.jitterSpeed = header.uvJitterSpeed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MdlReader::readSkin(ModelNode &node) {
|
void MdlReader::readSkin(ModelNode &node) {
|
||||||
SkinHeader header(readStruct<SkinHeader>());
|
SkinHeader header(readStruct<SkinHeader>());
|
||||||
|
|
||||||
|
@ -871,36 +904,37 @@ void MdlReader::readSaber(ModelNode &node) {
|
||||||
loadMesh(meshHeader, numVertices, move(vertices), move(indices), move(offsets), node);
|
loadMesh(meshHeader, numVertices, move(vertices), move(indices), move(offsets), node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MdlReader::loadMesh(const MeshHeader &header, int numVertices, vector<float> &&vertices, vector<uint16_t> &&indices, Mesh::VertexOffsets &&offsets, ModelNode &node) {
|
void MdlReader::readDanglymesh(ModelNode &node) {
|
||||||
auto mesh = make_unique<Mesh>(numVertices, vertices, indices, offsets);
|
DanglymeshHeader header(readStruct<DanglymeshHeader>());
|
||||||
mesh->computeAABB();
|
// TODO: fill ModelNode
|
||||||
|
}
|
||||||
|
|
||||||
node._mesh = make_unique<ModelMesh>(move(mesh));
|
void MdlReader::readAABB(ModelNode &node) {
|
||||||
node._mesh->setRender(static_cast<bool>(header.render));
|
uint32_t offTree = readUint32();
|
||||||
node._mesh->setTransparency(static_cast<int>(header.transparencyHint));
|
size_t pos = tell();
|
||||||
node._mesh->setShadow(static_cast<bool>(header.shadow));
|
|
||||||
node._mesh->setBackgroundGeometry(static_cast<bool>(header.backgroundGeometry) != 0);
|
|
||||||
node._mesh->setDiffuseColor(glm::make_vec3(header.diffuse));
|
|
||||||
node._mesh->setAmbientColor(glm::make_vec3(header.ambient));
|
|
||||||
|
|
||||||
string tex1ResRef(getStringLower(header.texture1, 32));
|
node._aabb = readAABBNode(offTree);
|
||||||
string tex2ResRef(getStringLower(header.texture2, 32));
|
|
||||||
string tex3ResRef(getStringLower(header.texture3, 12));
|
|
||||||
string tex4ResRef(getStringLower(header.texture4, 12));
|
|
||||||
|
|
||||||
if (!tex1ResRef.empty() && tex1ResRef != "null") {
|
seek(pos);
|
||||||
node._mesh->_diffuse = Textures::instance().get(tex1ResRef, TextureUsage::Diffuse);
|
}
|
||||||
}
|
|
||||||
if (!tex2ResRef.empty()) {
|
shared_ptr<AABBNode> MdlReader::readAABBNode(uint32_t offset) {
|
||||||
node._mesh->_lightmap = Textures::instance().get(tex2ResRef, TextureUsage::Lightmap);
|
auto node = make_shared<AABBNode>();
|
||||||
}
|
|
||||||
if (header.animateUV) {
|
seek(kMdlDataOffset + offset);
|
||||||
node._mesh->_uvAnimation.animated = true;
|
AABBNodeHeader header(readStruct<AABBNodeHeader>());
|
||||||
node._mesh->_uvAnimation.directionX = header.uvDirectionX;
|
|
||||||
node._mesh->_uvAnimation.directionY = header.uvDirectionY;
|
node->faceIndex = header.faceIndex;
|
||||||
node._mesh->_uvAnimation.jitter = header.uvJitter;
|
node->mostSignificantPlane = static_cast<AABBNode::Plane>(header.mostSignificantPlane);
|
||||||
node._mesh->_uvAnimation.jitterSpeed = header.uvJitterSpeed;
|
node->aabb.expand(glm::make_vec3(header.bbMin));
|
||||||
|
node->aabb.expand(glm::make_vec3(header.bbMax));
|
||||||
|
|
||||||
|
if (header.faceIndex == -1) {
|
||||||
|
node->leftChild = readAABBNode(header.offChildLeft);
|
||||||
|
node->rightChild = readAABBNode(header.offChildRight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return move(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<shared_ptr<Animation>> MdlReader::readAnimations(const vector<uint32_t> &offsets) {
|
vector<shared_ptr<Animation>> MdlReader::readAnimations(const vector<uint32_t> &offsets) {
|
||||||
|
@ -940,12 +974,15 @@ unique_ptr<Animation> MdlReader::readAnimation(uint32_t offset) {
|
||||||
shared_ptr<Model> MdlModelLoader::loadModel(GameID gameId, const string &resRef) {
|
shared_ptr<Model> MdlModelLoader::loadModel(GameID gameId, const string &resRef) {
|
||||||
shared_ptr<ByteArray> mdlData(Resources::instance().get(resRef, ResourceType::Mdl));
|
shared_ptr<ByteArray> mdlData(Resources::instance().get(resRef, ResourceType::Mdl));
|
||||||
shared_ptr<ByteArray> mdxData(Resources::instance().get(resRef, ResourceType::Mdx));
|
shared_ptr<ByteArray> mdxData(Resources::instance().get(resRef, ResourceType::Mdx));
|
||||||
|
shared_ptr<Model> model;
|
||||||
|
|
||||||
if (mdlData && mdxData) {
|
if (mdlData && mdxData) {
|
||||||
MdlReader mdl(gameId);
|
MdlReader mdl(gameId);
|
||||||
mdl.load(wrap(mdlData), wrap(mdxData));
|
mdl.load(wrap(mdlData), wrap(mdxData));
|
||||||
return mdl.model();
|
model = mdl.model();
|
||||||
}
|
}
|
||||||
return nullptr;
|
|
||||||
|
return move(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace render
|
} // namespace render
|
||||||
|
|
|
@ -20,8 +20,9 @@
|
||||||
#include "../../resource/format/binreader.h"
|
#include "../../resource/format/binreader.h"
|
||||||
#include "../../resource/types.h"
|
#include "../../resource/types.h"
|
||||||
|
|
||||||
#include "../model/model.h"
|
#include "aabbnode.h"
|
||||||
#include "../model/modelloader.h"
|
#include "model.h"
|
||||||
|
#include "modelloader.h"
|
||||||
|
|
||||||
namespace reone {
|
namespace reone {
|
||||||
|
|
||||||
|
@ -211,6 +212,23 @@ private:
|
||||||
uint8_t unknown[72]; // QBones, TBones, etc.
|
uint8_t unknown[72]; // QBones, TBones, etc.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DanglymeshHeader {
|
||||||
|
ArrayHeader constraints;
|
||||||
|
float displacement { 0.0f };
|
||||||
|
float tightness { 0.0f };
|
||||||
|
float period { 0.0f };
|
||||||
|
uint32_t unknown1 { 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AABBNodeHeader {
|
||||||
|
float bbMin[3];
|
||||||
|
float bbMax[3];
|
||||||
|
uint32_t offChildLeft { 0 };
|
||||||
|
uint32_t offChildRight { 0 };
|
||||||
|
int faceIndex { 0 };
|
||||||
|
uint32_t mostSignificantPlane { 0 };
|
||||||
|
};
|
||||||
|
|
||||||
struct SaberHeader {
|
struct SaberHeader {
|
||||||
uint32_t offVertices { 0 };
|
uint32_t offVertices { 0 };
|
||||||
uint32_t offTexCoords { 0 };
|
uint32_t offTexCoords { 0 };
|
||||||
|
@ -243,8 +261,12 @@ private:
|
||||||
void readReference(render::ModelNode &node);
|
void readReference(render::ModelNode &node);
|
||||||
void readMesh(render::ModelNode &node);
|
void readMesh(render::ModelNode &node);
|
||||||
void readSkin(render::ModelNode &node);
|
void readSkin(render::ModelNode &node);
|
||||||
|
void readDanglymesh(render::ModelNode &node);
|
||||||
|
void readAABB(render::ModelNode &node);
|
||||||
void readSaber(render::ModelNode &node);
|
void readSaber(render::ModelNode &node);
|
||||||
|
|
||||||
void loadMesh(const MeshHeader &header, int numVertices, std::vector<float> &&vertices, std::vector<uint16_t> &&indices, Mesh::VertexOffsets &&offsets, render::ModelNode &node);
|
void loadMesh(const MeshHeader &header, int numVertices, std::vector<float> &&vertices, std::vector<uint16_t> &&indices, Mesh::VertexOffsets &&offsets, render::ModelNode &node);
|
||||||
|
std::shared_ptr<AABBNode> readAABBNode(uint32_t offset);
|
||||||
};
|
};
|
||||||
|
|
||||||
class MdlModelLoader : public IModelLoader {
|
class MdlModelLoader : public IModelLoader {
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include "glm/gtx/quaternion.hpp"
|
#include "glm/gtx/quaternion.hpp"
|
||||||
|
|
||||||
|
#include "aabbnode.h"
|
||||||
#include "emitter.h"
|
#include "emitter.h"
|
||||||
#include "modelmesh.h"
|
#include "modelmesh.h"
|
||||||
|
|
||||||
|
@ -110,7 +111,7 @@ public:
|
||||||
void addAlphaKeyframe(Keyframe keyframe);
|
void addAlphaKeyframe(Keyframe keyframe);
|
||||||
void addSelfIllumColorKeyframe(Keyframe keyframe);
|
void addSelfIllumColorKeyframe(Keyframe keyframe);
|
||||||
|
|
||||||
bool isAABB() const { return _aabb; }
|
bool isAABB() const { return static_cast<bool>(_aabb); }
|
||||||
bool isSaber() const { return _saber; }
|
bool isSaber() const { return _saber; }
|
||||||
|
|
||||||
bool getTranslation(float time, glm::vec3 &translation, float scale = 1.0f) const;
|
bool getTranslation(float time, glm::vec3 &translation, float scale = 1.0f) const;
|
||||||
|
@ -151,10 +152,11 @@ public:
|
||||||
// Components
|
// Components
|
||||||
|
|
||||||
std::shared_ptr<Light> light() const { return _light; }
|
std::shared_ptr<Light> light() const { return _light; }
|
||||||
std::shared_ptr<ModelMesh> mesh() const { return _mesh; }
|
|
||||||
std::shared_ptr<Skin> skin() const { return _skin; }
|
|
||||||
std::shared_ptr<Emitter> emitter() const { return _emitter; }
|
std::shared_ptr<Emitter> emitter() const { return _emitter; }
|
||||||
std::shared_ptr<Reference> reference() const { return _reference; }
|
std::shared_ptr<Reference> reference() const { return _reference; }
|
||||||
|
std::shared_ptr<ModelMesh> mesh() const { return _mesh; }
|
||||||
|
std::shared_ptr<Skin> skin() const { return _skin; }
|
||||||
|
std::shared_ptr<AABBNode> aabb() const { return _aabb; }
|
||||||
|
|
||||||
// END Components
|
// END Components
|
||||||
|
|
||||||
|
@ -167,7 +169,6 @@ private:
|
||||||
glm::vec3 _color { 0.0f };
|
glm::vec3 _color { 0.0f };
|
||||||
glm::vec3 _selfIllumColor { 0.0f };
|
glm::vec3 _selfIllumColor { 0.0f };
|
||||||
float _alpha { 1.0f };
|
float _alpha { 1.0f };
|
||||||
bool _aabb { false };
|
|
||||||
bool _saber { false };
|
bool _saber { false };
|
||||||
|
|
||||||
std::vector<std::shared_ptr<ModelNode>> _children;
|
std::vector<std::shared_ptr<ModelNode>> _children;
|
||||||
|
@ -184,11 +185,12 @@ private:
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
|
|
||||||
std::shared_ptr<ModelMesh> _mesh;
|
|
||||||
std::shared_ptr<Skin> _skin;
|
|
||||||
std::shared_ptr<Light> _light;
|
std::shared_ptr<Light> _light;
|
||||||
std::shared_ptr<Emitter> _emitter;
|
std::shared_ptr<Emitter> _emitter;
|
||||||
std::shared_ptr<Reference> _reference;
|
std::shared_ptr<Reference> _reference;
|
||||||
|
std::shared_ptr<ModelMesh> _mesh;
|
||||||
|
std::shared_ptr<Skin> _skin;
|
||||||
|
std::shared_ptr<AABBNode> _aabb;
|
||||||
|
|
||||||
// END Components
|
// END Components
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue