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/mesh.h
|
||||
src/render/meshes.h
|
||||
src/render/model/aabbnode.h
|
||||
src/render/model/animation.h
|
||||
src/render/model/emitter.h
|
||||
src/render/model/mdlreader.h
|
||||
|
@ -215,6 +216,7 @@ set(RENDER_SOURCES
|
|||
src/render/materials.cpp
|
||||
src/render/mesh.cpp
|
||||
src/render/meshes.cpp
|
||||
src/render/model/aabbnode.cpp
|
||||
src/render/model/animation.cpp
|
||||
src/render/model/mdlreader.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/resources.h"
|
||||
|
||||
#include "../model/models.h"
|
||||
#include "../textures.h"
|
||||
|
||||
#include "models.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
using namespace reone::resource;
|
||||
|
@ -591,9 +592,6 @@ unique_ptr<ModelNode> MdlReader::readNode(uint32_t offset, ModelNode *parent) {
|
|||
if (header.flags & NodeFlags::skin) {
|
||||
node->_skin = make_shared<ModelNode::Skin>();
|
||||
}
|
||||
if (header.flags & NodeFlags::aabb) {
|
||||
node->_aabb = true;
|
||||
}
|
||||
if (header.flags & NodeFlags::saber) {
|
||||
node->_saber = true;
|
||||
}
|
||||
|
@ -610,15 +608,18 @@ unique_ptr<ModelNode> MdlReader::readNode(uint32_t offset, ModelNode *parent) {
|
|||
if (header.flags & NodeFlags::reference) {
|
||||
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)) {
|
||||
readMesh(*node);
|
||||
}
|
||||
if (header.flags & NodeFlags::skin) {
|
||||
readSkin(*node);
|
||||
}
|
||||
if (header.flags & NodeFlags::dangly) {
|
||||
readDanglymesh(*node);
|
||||
}
|
||||
if (header.flags & NodeFlags::aabb) {
|
||||
// TODO: read AABB tree
|
||||
readAABB(*node);
|
||||
}
|
||||
if (header.flags & NodeFlags::saber) {
|
||||
readSaber(*node);
|
||||
|
@ -777,6 +778,38 @@ void MdlReader::readMesh(ModelNode &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) {
|
||||
SkinHeader header(readStruct<SkinHeader>());
|
||||
|
||||
|
@ -871,36 +904,37 @@ void MdlReader::readSaber(ModelNode &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) {
|
||||
auto mesh = make_unique<Mesh>(numVertices, vertices, indices, offsets);
|
||||
mesh->computeAABB();
|
||||
void MdlReader::readDanglymesh(ModelNode &node) {
|
||||
DanglymeshHeader header(readStruct<DanglymeshHeader>());
|
||||
// TODO: fill ModelNode
|
||||
}
|
||||
|
||||
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));
|
||||
void MdlReader::readAABB(ModelNode &node) {
|
||||
uint32_t offTree = readUint32();
|
||||
size_t pos = tell();
|
||||
|
||||
string tex1ResRef(getStringLower(header.texture1, 32));
|
||||
string tex2ResRef(getStringLower(header.texture2, 32));
|
||||
string tex3ResRef(getStringLower(header.texture3, 12));
|
||||
string tex4ResRef(getStringLower(header.texture4, 12));
|
||||
node._aabb = readAABBNode(offTree);
|
||||
|
||||
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;
|
||||
seek(pos);
|
||||
}
|
||||
|
||||
shared_ptr<AABBNode> MdlReader::readAABBNode(uint32_t offset) {
|
||||
auto node = make_shared<AABBNode>();
|
||||
|
||||
seek(kMdlDataOffset + offset);
|
||||
AABBNodeHeader header(readStruct<AABBNodeHeader>());
|
||||
|
||||
node->faceIndex = header.faceIndex;
|
||||
node->mostSignificantPlane = static_cast<AABBNode::Plane>(header.mostSignificantPlane);
|
||||
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) {
|
||||
|
@ -940,12 +974,15 @@ unique_ptr<Animation> MdlReader::readAnimation(uint32_t offset) {
|
|||
shared_ptr<Model> MdlModelLoader::loadModel(GameID gameId, const string &resRef) {
|
||||
shared_ptr<ByteArray> mdlData(Resources::instance().get(resRef, ResourceType::Mdl));
|
||||
shared_ptr<ByteArray> mdxData(Resources::instance().get(resRef, ResourceType::Mdx));
|
||||
shared_ptr<Model> model;
|
||||
|
||||
if (mdlData && mdxData) {
|
||||
MdlReader mdl(gameId);
|
||||
mdl.load(wrap(mdlData), wrap(mdxData));
|
||||
return mdl.model();
|
||||
model = mdl.model();
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
return move(model);
|
||||
}
|
||||
|
||||
} // namespace render
|
||||
|
|
|
@ -20,8 +20,9 @@
|
|||
#include "../../resource/format/binreader.h"
|
||||
#include "../../resource/types.h"
|
||||
|
||||
#include "../model/model.h"
|
||||
#include "../model/modelloader.h"
|
||||
#include "aabbnode.h"
|
||||
#include "model.h"
|
||||
#include "modelloader.h"
|
||||
|
||||
namespace reone {
|
||||
|
||||
|
@ -211,6 +212,23 @@ private:
|
|||
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 {
|
||||
uint32_t offVertices { 0 };
|
||||
uint32_t offTexCoords { 0 };
|
||||
|
@ -243,8 +261,12 @@ private:
|
|||
void readReference(render::ModelNode &node);
|
||||
void readMesh(render::ModelNode &node);
|
||||
void readSkin(render::ModelNode &node);
|
||||
void readDanglymesh(render::ModelNode &node);
|
||||
void readAABB(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);
|
||||
std::shared_ptr<AABBNode> readAABBNode(uint32_t offset);
|
||||
};
|
||||
|
||||
class MdlModelLoader : public IModelLoader {
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "glm/gtx/quaternion.hpp"
|
||||
|
||||
#include "aabbnode.h"
|
||||
#include "emitter.h"
|
||||
#include "modelmesh.h"
|
||||
|
||||
|
@ -110,7 +111,7 @@ public:
|
|||
void addAlphaKeyframe(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 getTranslation(float time, glm::vec3 &translation, float scale = 1.0f) const;
|
||||
|
@ -151,10 +152,11 @@ public:
|
|||
// Components
|
||||
|
||||
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<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
|
||||
|
||||
|
@ -167,7 +169,6 @@ private:
|
|||
glm::vec3 _color { 0.0f };
|
||||
glm::vec3 _selfIllumColor { 0.0f };
|
||||
float _alpha { 1.0f };
|
||||
bool _aabb { false };
|
||||
bool _saber { false };
|
||||
|
||||
std::vector<std::shared_ptr<ModelNode>> _children;
|
||||
|
@ -184,11 +185,12 @@ private:
|
|||
|
||||
// Components
|
||||
|
||||
std::shared_ptr<ModelMesh> _mesh;
|
||||
std::shared_ptr<Skin> _skin;
|
||||
std::shared_ptr<Light> _light;
|
||||
std::shared_ptr<Emitter> _emitter;
|
||||
std::shared_ptr<Reference> _reference;
|
||||
std::shared_ptr<ModelMesh> _mesh;
|
||||
std::shared_ptr<Skin> _skin;
|
||||
std::shared_ptr<AABBNode> _aabb;
|
||||
|
||||
// END Components
|
||||
|
||||
|
|
Loading…
Reference in a new issue