mirror of
https://github.com/mwpenny/portal64-still-alive.git
synced 2024-11-26 22:00:25 +00:00
Fixup skeletal animation
This commit is contained in:
parent
ec0c6a79dc
commit
18a879d7fa
1
Makefile
1
Makefile
@ -161,6 +161,7 @@ build/src/scene/elevator.o: build/assets/models/props/round_elevator_collision.h
|
||||
|
||||
MODEL_LIST = assets/models/cube/cube.blend \
|
||||
assets/models/portal_gun/v_portalgun.blend \
|
||||
assets/models/portal_gun/w_portalgun.blend \
|
||||
assets/models/props/button.blend \
|
||||
assets/models/props/door_01.blend \
|
||||
assets/models/props/cylinder_test.blend \
|
||||
|
@ -127,9 +127,30 @@ materials:
|
||||
color: ["PRIMITIVE", "0", "SHADE", "0"]
|
||||
|
||||
blue_glow:
|
||||
gDPSetPrimColor:
|
||||
r: 89
|
||||
g: 197
|
||||
b: 240
|
||||
gDPSetCombineMode:
|
||||
color: ["0", "0", "0", "PRIMITIVE"]
|
||||
|
||||
solid_black_two_sided:
|
||||
gDPSetPrimColor:
|
||||
r: 32
|
||||
g: 32
|
||||
b: 32
|
||||
gSPGeometryMode:
|
||||
set: [G_LIGHTING, G_SHADE]
|
||||
clear: [G_CULL_BACK]
|
||||
gDPSetCombineMode:
|
||||
color: ["0", "0", "0", "PRIMITIVE"]
|
||||
color: ["PRIMITIVE", "0", "SHADE", "0"]
|
||||
|
||||
blue_glow_two_sided:
|
||||
gDPSetPrimColor:
|
||||
r: 89
|
||||
g: 197
|
||||
b: 240
|
||||
gSPGeometryMode:
|
||||
clear: [G_CULL_BACK]
|
||||
gDPSetCombineMode:
|
||||
color: ["0", "0", "0", "PRIMITIVE"]
|
Binary file not shown.
@ -1 +1 @@
|
||||
-r 90,0,0 -m assets/materials/static.skm.yaml -m assets/materials/objects.skm.yaml --default-material default
|
||||
-r 0,0,0 -m assets/materials/static.skm.yaml -m assets/materials/objects.skm.yaml --default-material default
|
BIN
assets/models/portal_gun/w_portalgun.blend
Normal file
BIN
assets/models/portal_gun/w_portalgun.blend
Normal file
Binary file not shown.
1
assets/models/portal_gun/w_portalgun.flags
Normal file
1
assets/models/portal_gun/w_portalgun.flags
Normal file
@ -0,0 +1 @@
|
||||
-m assets/materials/objects.skm.yaml
|
@ -93,7 +93,7 @@ int Bone::GetBoneIndex(Bone* a) {
|
||||
}
|
||||
}
|
||||
|
||||
void BoneHierarchy::PopulateWithAnimationNodeInfo(const NodeAnimationInfo& animInfo, float fixedPointScale) {
|
||||
void BoneHierarchy::PopulateWithAnimationNodeInfo(const NodeAnimationInfo& animInfo, float fixedPointScale, aiQuaternion& rotation) {
|
||||
for (auto& node : animInfo.nodesWithAnimation) {
|
||||
Bone* parent = nullptr;
|
||||
|
||||
|
@ -65,7 +65,7 @@ public:
|
||||
void SearchForBones(aiNode* node, Bone* currentBoneParent, std::set<std::string>& knownBones, bool parentIsBone, float fixedPointScale);
|
||||
void SearchForBonesInScene(const aiScene* scene, float fixedPointScale);
|
||||
|
||||
void PopulateWithAnimationNodeInfo(const NodeAnimationInfo& animInfo, float fixedPointScale);
|
||||
void PopulateWithAnimationNodeInfo(const NodeAnimationInfo& animInfo, float fixedPointScale, aiQuaternion& rotation);
|
||||
|
||||
Bone* BoneByIndex(unsigned index);
|
||||
Bone* BoneForName(std::string name);
|
||||
|
@ -61,12 +61,10 @@ unsigned convertByteRange(float value) {
|
||||
|
||||
aiVector3D pos = mTargetMesh->mMesh->mVertices[i];
|
||||
|
||||
pos = pos * modelScale;
|
||||
|
||||
if (mTargetMesh->mPointInverseTransform[i]) {
|
||||
pos = (*mTargetMesh->mPointInverseTransform[i]) * pos;
|
||||
if (mTargetMesh->mPointInverseTransform.size()) {
|
||||
pos = mTargetMesh->mPointInverseTransform[i] * pos;
|
||||
} else {
|
||||
pos = rotate.Rotate(pos);
|
||||
pos = rotate.Rotate(pos) * modelScale;
|
||||
}
|
||||
|
||||
pos = pos * fixedPointScale;
|
||||
@ -151,9 +149,9 @@ unsigned convertByteRange(float value) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (mTargetMesh->mPointInverseTransform[i]) {
|
||||
normal = (*mTargetMesh->mNormalInverseTransform[i]) * normal;
|
||||
normal.Normalize();
|
||||
if (mTargetMesh->mPointInverseTransform.size()) {
|
||||
normal = mTargetMesh->mNormalInverseTransform[i] * normal;
|
||||
normal.NormalizeSafe();
|
||||
} else {
|
||||
normal = rotate.Rotate(normal);
|
||||
}
|
||||
|
@ -134,19 +134,16 @@ ExtendedMesh::ExtendedMesh(const ExtendedMesh& other):
|
||||
|
||||
mBoneSpanningFaces[it.first] = faces;
|
||||
}
|
||||
|
||||
for (auto& it : mNormalInverseTransform) {
|
||||
if (it) {
|
||||
it = new aiMatrix3x3(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ExtendedMesh::ExtendedMesh(aiMesh* mesh, BoneHierarchy& boneHierarchy) :
|
||||
mMesh(mesh) {
|
||||
mVertexBones.resize(mMesh->mNumVertices);
|
||||
mPointInverseTransform.resize(mMesh->mNumVertices);
|
||||
mNormalInverseTransform.resize(mMesh->mNumVertices);
|
||||
|
||||
if (mesh->mNumBones) {
|
||||
mPointInverseTransform.resize(mMesh->mNumVertices);
|
||||
mNormalInverseTransform.resize(mMesh->mNumVertices);
|
||||
}
|
||||
|
||||
std::set<Bone*> bonesAsSet;
|
||||
|
||||
@ -154,15 +151,15 @@ ExtendedMesh::ExtendedMesh(aiMesh* mesh, BoneHierarchy& boneHierarchy) :
|
||||
aiBone* bone = mMesh->mBones[boneIndex];
|
||||
Bone* hierarchyBone = boneHierarchy.BoneForName(bone->mName.C_Str());
|
||||
bonesAsSet.insert(hierarchyBone);
|
||||
|
||||
|
||||
aiMatrix3x3 normalTransform(bone->mOffsetMatrix);
|
||||
normalTransform = normalTransform.Transpose().Inverse();
|
||||
|
||||
for (unsigned int vertexIndex = 0; vertexIndex < bone->mNumWeights; ++vertexIndex) {
|
||||
unsigned int vertexId = bone->mWeights[vertexIndex].mVertexId;
|
||||
mVertexBones[vertexId] = hierarchyBone;
|
||||
mPointInverseTransform[vertexId] = &bone->mOffsetMatrix;
|
||||
mNormalInverseTransform[vertexId] = new aiMatrix3x3(normalTransform);
|
||||
mPointInverseTransform[vertexId] = bone->mOffsetMatrix;
|
||||
mNormalInverseTransform[vertexId] = normalTransform;
|
||||
}
|
||||
}
|
||||
|
||||
@ -171,11 +168,7 @@ ExtendedMesh::ExtendedMesh(aiMesh* mesh, BoneHierarchy& boneHierarchy) :
|
||||
}
|
||||
|
||||
ExtendedMesh::~ExtendedMesh() {
|
||||
for (unsigned int i = 0; i < mNormalInverseTransform.size(); ++i) {
|
||||
if (mNormalInverseTransform[i]) {
|
||||
delete mNormalInverseTransform[i];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ExtendedMesh::RecalcBB() {
|
||||
@ -234,6 +227,10 @@ std::shared_ptr<ExtendedMesh> ExtendedMesh::Transform(const aiMatrix4x4& transfo
|
||||
std::shared_ptr<ExtendedMesh> result(new ExtendedMesh(*this));
|
||||
|
||||
aiMatrix3x3 rotationOnly(transform);
|
||||
|
||||
aiMatrix4x4 inverseTransform = transform;
|
||||
inverseTransform.Inverse();
|
||||
|
||||
for (unsigned i = 0; i < result->mMesh->mNumVertices; ++i) {
|
||||
result->mMesh->mVertices[i] = transform * result->mMesh->mVertices[i];
|
||||
|
||||
@ -241,7 +238,12 @@ std::shared_ptr<ExtendedMesh> ExtendedMesh::Transform(const aiMatrix4x4& transfo
|
||||
result->mMesh->mNormals[i] = rotationOnly * result->mMesh->mNormals[i];
|
||||
result->mMesh->mNormals[i].NormalizeSafe();
|
||||
}
|
||||
|
||||
if (result->mPointInverseTransform.size()) {
|
||||
result->mPointInverseTransform[i] = result->mPointInverseTransform[i] * inverseTransform;
|
||||
}
|
||||
}
|
||||
|
||||
result->RecalcBB();
|
||||
|
||||
return result;
|
||||
|
@ -22,8 +22,8 @@ public:
|
||||
ExtendedMesh(aiMesh* mesh, BoneHierarchy& boneHierarchy);
|
||||
~ExtendedMesh();
|
||||
aiMesh* mMesh;
|
||||
std::vector<aiMatrix4x4*> mPointInverseTransform;
|
||||
std::vector<aiMatrix3x3*> mNormalInverseTransform;
|
||||
std::vector<aiMatrix4x4> mPointInverseTransform;
|
||||
std::vector<aiMatrix3x3> mNormalInverseTransform;
|
||||
std::vector<Bone*> mVertexBones;
|
||||
std::map<Bone*, std::vector<aiFace*>> mFacesForBone;
|
||||
// first bone in pair is always the parent of the second
|
||||
|
@ -71,7 +71,7 @@ void generateMeshIntoDLWithMaterials(const aiScene* scene, CFileDefinition& file
|
||||
|
||||
for (auto chunk = renderChunks.begin(); chunk != renderChunks.end(); ++chunk) {
|
||||
if (materials) {
|
||||
std::string materialName = ExtendedMesh::GetMaterialName(scene->mMaterials[chunk->mMesh->mMesh->mMaterialIndex], settings.mForceMaterialName);
|
||||
std::string materialName = chunk->mMesh ? ExtendedMesh::GetMaterialName(scene->mMaterials[chunk->mMesh->mMesh->mMaterialIndex], settings.mForceMaterialName) : settings.mDefaultMaterialName;
|
||||
displayList.AddCommand(std::unique_ptr<DisplayListCommand>(new CommentCommand("Material " + materialName)));
|
||||
auto mappedMaterialName = materials->mMaterialNameMapping.find(materialName);
|
||||
|
||||
@ -98,14 +98,20 @@ void generateMeshIntoDLWithMaterials(const aiScene* scene, CFileDefinition& file
|
||||
displayList.AddCommand(std::unique_ptr<DisplayListCommand>(new CommentCommand("End Material " + materialName)));
|
||||
}
|
||||
|
||||
std::string vertexBuffer = fileDefinition.GetVertexBuffer(
|
||||
chunk->mMesh,
|
||||
Material::GetVertexType(chunk->mMaterial),
|
||||
Material::TextureWidth(chunk->mMaterial),
|
||||
Material::TextureHeight(chunk->mMaterial),
|
||||
modelSuffix
|
||||
);
|
||||
generateGeometry(*chunk, rcpState, vertexBuffer, displayList, settings.mHasTri2);
|
||||
if (chunk->mMesh) {
|
||||
std::string vertexBuffer = fileDefinition.GetVertexBuffer(
|
||||
chunk->mMesh,
|
||||
Material::GetVertexType(chunk->mMaterial),
|
||||
Material::TextureWidth(chunk->mMaterial),
|
||||
Material::TextureHeight(chunk->mMaterial),
|
||||
modelSuffix
|
||||
);
|
||||
generateGeometry(*chunk, rcpState, vertexBuffer, displayList, settings.mHasTri2);
|
||||
} else if (chunk->mAttachedDLIndex != -1) {
|
||||
rcpState.TraverseToBone(chunk->mBonePair.first, displayList);
|
||||
displayList.AddCommand(std::unique_ptr<DisplayListCommand>(new CallDisplayListByNameCommand(std::string("(Gfx*)BONE_ATTACHMENT_SEGMENT_ADDRESS + " + std::to_string(chunk->mAttachedDLIndex)))));
|
||||
}
|
||||
|
||||
}
|
||||
rcpState.TraverseToBone(nullptr, displayList);
|
||||
|
||||
|
@ -2,9 +2,20 @@
|
||||
#include "RenderChunk.h"
|
||||
#include <algorithm>
|
||||
|
||||
RenderChunk::RenderChunk(std::pair<Bone*, Bone*> bonePair, std::shared_ptr<ExtendedMesh> mesh, Material* material):
|
||||
RenderChunk::RenderChunk(std::pair<Bone*, Bone*> bonePair, std::shared_ptr<ExtendedMesh> mesh, aiNode* meshRoot, Material* material):
|
||||
mBonePair(bonePair),
|
||||
mMesh(mesh),
|
||||
mMeshRoot(meshRoot),
|
||||
mAttachedDLIndex(-1),
|
||||
mMaterial(material) {
|
||||
|
||||
}
|
||||
|
||||
RenderChunk::RenderChunk(std::pair<Bone*, Bone*> bonePair, int attachedDLIndex, Material* material):
|
||||
mBonePair(bonePair),
|
||||
mMesh(NULL),
|
||||
mMeshRoot(nullptr),
|
||||
mAttachedDLIndex(attachedDLIndex),
|
||||
mMaterial(material) {
|
||||
|
||||
}
|
||||
@ -45,12 +56,13 @@ void extractChunks(const aiScene* scene, std::vector<std::shared_ptr<ExtendedMes
|
||||
result.push_back(RenderChunk(
|
||||
std::make_pair(boneSegment->first, boneSegment->first),
|
||||
*it,
|
||||
nullptr,
|
||||
materialPtr
|
||||
));
|
||||
}
|
||||
|
||||
for (auto pairSegment = (*it)->mBoneSpanningFaces.begin(); pairSegment != (*it)->mBoneSpanningFaces.end(); ++pairSegment) {
|
||||
result.push_back(RenderChunk(pairSegment->first, *it, materialPtr));
|
||||
result.push_back(RenderChunk(pairSegment->first, *it, nullptr, materialPtr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,11 +13,14 @@
|
||||
|
||||
class RenderChunk {
|
||||
public:
|
||||
RenderChunk(std::pair<Bone*, Bone*> bonePair, std::shared_ptr<ExtendedMesh> mesh, Material* material);
|
||||
RenderChunk(std::pair<Bone*, Bone*> bonePair, std::shared_ptr<ExtendedMesh> mesh, aiNode* meshRoot, Material* material);
|
||||
RenderChunk(std::pair<Bone*, Bone*> bonePair, int attachedDLIndex, Material* material);
|
||||
// if bones are the same, chunk cooresponds to a single bone
|
||||
// the bones can be null
|
||||
std::pair<Bone*, Bone*> mBonePair;
|
||||
std::shared_ptr<ExtendedMesh> mMesh;
|
||||
aiNode* mMeshRoot;
|
||||
int mAttachedDLIndex;
|
||||
Material* mMaterial;
|
||||
|
||||
VertexType GetVertexType();
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
std::shared_ptr<NodeAnimationInfo> findNodesForWithAnimation(const aiScene* scene, const std::vector<aiNode*>& usedNodes, const aiMatrix4x4& baseTransform) {
|
||||
std::shared_ptr<NodeAnimationInfo> findNodesForWithAnimation(const aiScene* scene, const std::vector<aiNode*>& usedNodes, float modelScale) {
|
||||
std::set<std::string> animatedNodeNames;
|
||||
|
||||
for (unsigned animIndex = 0; animIndex < scene->mNumAnimations; ++animIndex) {
|
||||
@ -56,7 +56,7 @@ std::shared_ptr<NodeAnimationInfo> findNodesForWithAnimation(const aiScene* scen
|
||||
}
|
||||
|
||||
if (!currentNode->mParent) {
|
||||
nodeInfo->relativeTransform = baseTransform * nodeInfo->relativeTransform;
|
||||
nodeInfo->relativeTransform = aiMatrix4x4(aiVector3D(1, 1, 1) * modelScale, aiQuaternion(), aiVector3D()) * nodeInfo->relativeTransform;
|
||||
}
|
||||
|
||||
nodeInfo->node = node;
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "../DisplayListSettings.h"
|
||||
#include "../Animation.h"
|
||||
|
||||
std::shared_ptr<NodeAnimationInfo> findNodesForWithAnimation(const aiScene* scene, const std::vector<aiNode*>& usedNodes, const aiMatrix4x4& baseTransform);
|
||||
std::shared_ptr<NodeAnimationInfo> findNodesForWithAnimation(const aiScene* scene, const std::vector<aiNode*>& usedNodes, float modelScale);
|
||||
|
||||
std::vector<SKAnimationHeader> generateAnimationData(const aiScene* scene, BoneHierarchy& bones, CFileDefinition& fileDef, float modelScale, unsigned short targetTicksPerSecond, aiQuaternion rotate);
|
||||
void generateAnimationForScene(const aiScene* scene, CFileDefinition &fileDefinition, DisplayListSettings& settings);
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "../RenderChunk.h"
|
||||
#include "../MeshWriter.h"
|
||||
#include "AnimationGenerator.h"
|
||||
#include "../StringUtils.h"
|
||||
|
||||
bool extractMaterialAutoTileParameters(Material* material, double& sTile, double& tTile) {
|
||||
if (!material) {
|
||||
@ -64,21 +65,38 @@ void MeshDefinitionGenerator::AppendRenderChunks(const aiScene* scene, aiNode* n
|
||||
renderChunks.push_back(RenderChunk(
|
||||
std::make_pair(boneSegment->first, boneSegment->first),
|
||||
mesh,
|
||||
node,
|
||||
materialPtr
|
||||
));
|
||||
}
|
||||
|
||||
for (auto pairSegment = mesh->mBoneSpanningFaces.begin(); pairSegment != mesh->mBoneSpanningFaces.end(); ++pairSegment) {
|
||||
renderChunks.push_back(RenderChunk(pairSegment->first, mesh, materialPtr));
|
||||
renderChunks.push_back(RenderChunk(pairSegment->first, mesh, node, materialPtr));
|
||||
}
|
||||
}
|
||||
|
||||
BoneHierarchy& bones = fileDefinition.GetBoneHierarchy();
|
||||
|
||||
int attachmentCount = 0;
|
||||
|
||||
for (unsigned i = 0; i < bones.GetBoneCount(); ++i) {
|
||||
Bone* bone = bones.BoneByIndex(i);
|
||||
|
||||
if (StartsWith(bone->GetName(), "attachment ")) {
|
||||
fileDefinition.AddMacro(fileDefinition.GetMacroName(std::string("ATTACHMENT_") + bone->GetName().substr(strlen("attachment "))), std::to_string(attachmentCount));
|
||||
renderChunks.push_back(RenderChunk(std::make_pair(bone, bone), attachmentCount, NULL));
|
||||
++attachmentCount;
|
||||
}
|
||||
}
|
||||
|
||||
fileDefinition.AddMacro(fileDefinition.GetMacroName("ATTACHMENT_COUNT"), std::to_string(attachmentCount));
|
||||
}
|
||||
|
||||
void MeshDefinitionGenerator::GenerateDefinitions(const aiScene* scene, CFileDefinition& fileDefinition) {
|
||||
std::vector<RenderChunk> renderChunks;
|
||||
|
||||
auto animInfo = findNodesForWithAnimation(scene, mIncludedNodes, mSettings.CreateCollisionTransform());
|
||||
fileDefinition.GetBoneHierarchy().PopulateWithAnimationNodeInfo(*animInfo, mSettings.mFixedPointScale);
|
||||
auto animInfo = findNodesForWithAnimation(scene, mIncludedNodes, mSettings.mModelScale);
|
||||
fileDefinition.GetBoneHierarchy().PopulateWithAnimationNodeInfo(*animInfo, mSettings.mFixedPointScale, mSettings.mRotateModel);
|
||||
|
||||
for (auto node = mIncludedNodes.begin(); node != mIncludedNodes.end(); ++node) {
|
||||
AppendRenderChunks(scene, *node, fileDefinition, mSettings, renderChunks);
|
||||
|
@ -149,7 +149,7 @@ static void gameProc(void* arg) {
|
||||
|
||||
dynamicSceneInit();
|
||||
contactSolverInit(&gContactSolver);
|
||||
levelLoad(0);
|
||||
levelLoad(1);
|
||||
controllersInit();
|
||||
initAudio();
|
||||
soundPlayerInit();
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "sk64/skelatool_animator.h"
|
||||
|
||||
#include "../../build/assets/models/portal_gun/v_portalgun.h"
|
||||
#include "../../build/assets/models/portal_gun/w_portalgun.h"
|
||||
#include "../../build/assets/materials/static.h"
|
||||
#include "../../build/assets/models/props/button.h"
|
||||
#include "../../build/assets/models/props/door_01.h"
|
||||
@ -10,6 +11,8 @@
|
||||
|
||||
Gfx* v_portal_gun_gfx = &portal_gun_v_portalgun_model_gfx[0];
|
||||
|
||||
Gfx* w_portal_gun_gfx = &portal_gun_w_portalgun_model_gfx[0];
|
||||
|
||||
Gfx* button_gfx = &props_button_model_gfx[0];
|
||||
short button_material_index = BUTTON_INDEX;
|
||||
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
extern Gfx* v_portal_gun_gfx;
|
||||
|
||||
extern Gfx* w_portal_gun_gfx;
|
||||
|
||||
extern Gfx* button_gfx;
|
||||
extern short button_material_index;
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
#include "../scene/dynamic_scene.h"
|
||||
#include "../defs.h"
|
||||
#include "../models/models.h"
|
||||
#include "../util/time.h"
|
||||
|
||||
#include "../build/assets/materials/static.h"
|
||||
#include "../build/assets/models/pedestal.h"
|
||||
@ -9,6 +11,8 @@
|
||||
void pedestalRender(void* data, struct RenderScene* renderScene) {
|
||||
struct Pedestal* pedestal = (struct Pedestal*)data;
|
||||
|
||||
quatAxisAngle(&gUp, gTimePassed, &pedestal->armature.boneTransforms[PEDESTAL_HOLDER_BONE].rotation);
|
||||
|
||||
Mtx* matrix = renderStateRequestMatrices(renderScene->renderState, 1);
|
||||
transformToMatrixL(&pedestal->transform, matrix, SCENE_SCALE);
|
||||
|
||||
@ -16,13 +20,25 @@ void pedestalRender(void* data, struct RenderScene* renderScene) {
|
||||
|
||||
skCalculateTransforms(&pedestal->armature, armature);
|
||||
|
||||
Gfx* attachments = skBuildAttachments(&pedestal->armature, &w_portal_gun_gfx, renderScene->renderState);
|
||||
|
||||
Gfx* objectRender = renderStateAllocateDLChunk(renderScene->renderState, 4);
|
||||
Gfx* dl = objectRender;
|
||||
|
||||
if (attachments) {
|
||||
gSPSegment(dl++, BONE_ATTACHMENT_SEGMENT, osVirtualToPhysical(attachments));
|
||||
}
|
||||
gSPSegment(dl++, MATRIX_TRANSFORM_SEGMENT, osVirtualToPhysical(armature));
|
||||
gSPDisplayList(dl++, pedestal_model_gfx);
|
||||
gSPEndDisplayList(dl++);
|
||||
|
||||
renderSceneAdd(
|
||||
renderScene,
|
||||
pedestal->armature.displayList,
|
||||
objectRender,
|
||||
matrix,
|
||||
DEFAULT_INDEX,
|
||||
&pedestal->transform.position,
|
||||
armature
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
@ -37,7 +53,8 @@ void pedestalInit(struct Pedestal* pedestal, struct PedestalDefinition* definiti
|
||||
pedestal_model_gfx,
|
||||
PEDESTAL_DEFAULT_BONES_COUNT,
|
||||
pedestal_default_bones,
|
||||
pedestal_bone_parent
|
||||
pedestal_bone_parent,
|
||||
PEDESTAL_ATTACHMENT_COUNT
|
||||
);
|
||||
|
||||
pedestal->dynamicId = dynamicSceneAdd(pedestal, pedestalRender, &pedestal->transform, 0.8f);
|
||||
|
@ -4,9 +4,10 @@
|
||||
#include "util/memory.h"
|
||||
#include "util/rom.h"
|
||||
|
||||
void skArmatureInit(struct SKArmature* object, Gfx* displayList, u32 numberOfBones, struct Transform* initialPose, unsigned short* boneParentIndex) {
|
||||
void skArmatureInit(struct SKArmature* object, Gfx* displayList, u32 numberOfBones, struct Transform* initialPose, unsigned short* boneParentIndex, u32 numberOfAttachments) {
|
||||
object->displayList = displayList;
|
||||
object->numberOfBones = numberOfBones;
|
||||
object->numberOfAttachments = numberOfAttachments;
|
||||
|
||||
unsigned transformSize = sizeof(Mtx) * numberOfBones;
|
||||
|
||||
@ -27,18 +28,53 @@ void skCleanupObject(struct SKArmature* object) {
|
||||
object->numberOfBones = 0;
|
||||
}
|
||||
|
||||
void skRenderObject(struct SKArmature* object, struct RenderState* intoState) {
|
||||
Gfx* skBuildAttachments(struct SKArmature* object, Gfx** attachments, struct RenderState* renderState) {
|
||||
if (object->numberOfAttachments == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (object->numberOfAttachments == 1 && attachments) {
|
||||
return *attachments;
|
||||
}
|
||||
|
||||
Gfx* jumpTable = renderStateAllocateDLChunk(renderState, object->numberOfAttachments);
|
||||
Gfx* dl = jumpTable;
|
||||
|
||||
for (unsigned i = 0; i < object->numberOfAttachments; ++i) {
|
||||
if (attachments && attachments[i]) {
|
||||
gSPBranchList(dl++, attachments[i]);
|
||||
} else {
|
||||
gSPEndDisplayList(dl++);
|
||||
}
|
||||
}
|
||||
|
||||
return jumpTable;
|
||||
}
|
||||
|
||||
void skRenderObject(struct SKArmature* object, Gfx** attachements, struct RenderState* intoState) {
|
||||
if (!object->displayList) {
|
||||
return;
|
||||
}
|
||||
|
||||
Mtx* boneMatrices = renderStateRequestMatrices(intoState, object->numberOfBones);
|
||||
|
||||
if (boneMatrices) {
|
||||
skCalculateTransforms(object, boneMatrices);
|
||||
gSPSegment(intoState->dl++, MATRIX_TRANSFORM_SEGMENT, osVirtualToPhysical(boneMatrices));
|
||||
gSPDisplayList(intoState->dl++, object->displayList);
|
||||
if (!boneMatrices) {
|
||||
return;
|
||||
}
|
||||
|
||||
Gfx* jumpTable = skBuildAttachments(object, attachements, intoState);
|
||||
|
||||
if (!jumpTable && object->numberOfAttachments) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (jumpTable) {
|
||||
gSPSegment(intoState->dl++, BONE_ATTACHMENT_SEGMENT, osVirtualToPhysical(jumpTable));
|
||||
}
|
||||
|
||||
skCalculateTransforms(object, boneMatrices);
|
||||
gSPSegment(intoState->dl++, MATRIX_TRANSFORM_SEGMENT, osVirtualToPhysical(boneMatrices));
|
||||
gSPDisplayList(intoState->dl++, object->displayList);
|
||||
}
|
||||
|
||||
void skCalculateTransforms(struct SKArmature* object, Mtx* into) {
|
||||
|
@ -10,12 +10,14 @@
|
||||
struct SKArmature {
|
||||
Gfx* displayList;
|
||||
struct Transform* boneTransforms;
|
||||
u32 numberOfBones;
|
||||
u16 numberOfBones;
|
||||
u16 numberOfAttachments;
|
||||
unsigned short* boneParentIndex;
|
||||
};
|
||||
|
||||
void skArmatureInit(struct SKArmature* object, Gfx* displayList, u32 numberOfBones, struct Transform* initialPose, unsigned short* boneParentIndex);
|
||||
void skRenderObject(struct SKArmature* object, struct RenderState* intoState);
|
||||
void skArmatureInit(struct SKArmature* object, Gfx* displayList, u32 numberOfBones, struct Transform* initialPose, unsigned short* boneParentIndex, u32 numberOfAttachments);
|
||||
Gfx* skBuildAttachments(struct SKArmature* object, Gfx** attachments, struct RenderState* renderState);
|
||||
void skRenderObject(struct SKArmature* object, Gfx** attachements, struct RenderState* intoState);
|
||||
void skCalculateTransforms(struct SKArmature* object, Mtx* into);
|
||||
void skCleanupObject(struct SKArmature* object);
|
||||
void skCalculateBonePosition(struct SKArmature* object, unsigned short boneIndex, struct Vector3* bonePosition, struct Vector3* out);
|
||||
|
@ -5,4 +5,7 @@
|
||||
#define CHARACTER_ANIMATION_SEGMENT 0xD
|
||||
#define CHARACTER_ANIMATION_SEGMENT_ADDRESS (CHARACTER_ANIMATION_SEGMENT << 24)
|
||||
|
||||
#define BONE_ATTACHMENT_SEGMENT 0xE
|
||||
#define BONE_ATTACHMENT_SEGMENT_ADDRESS (BONE_ATTACHMENT_SEGMENT << 24)
|
||||
|
||||
#define ANIM_DATA_ROM_ADDRESS(segmentStart, segmentedAddress) ((void*)((u32)(segmentedAddress) - CHARACTER_ANIMATION_SEGMENT_ADDRESS + (u32)segmentStart))
|
Loading…
Reference in New Issue
Block a user