Skip to content
This repository has been archived by the owner on Jan 5, 2024. It is now read-only.

Commit

Permalink
NUNOv35 update, v34 fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Joschuka committed Mar 8, 2023
1 parent b76a971 commit 08a8de7
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 38 deletions.
81 changes: 47 additions & 34 deletions Source/Private/Source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -796,24 +796,21 @@ noesisModel_t* ProcessModel(BYTE* fileBuffer, int bufferLen, int& numMdl, noeRAP
modelBone_t* joint = joints + jointIndex;
RichMat43 jointMatrix = RichQuat().ToMat43().GetInverse().m;
if (parentID == 0xFFFFFFFF)
{
parentID = nunParentJointID;
g_mfn->Math_VecCopy(p.v, jointMatrix.m.o);
}
else
{
parentID += jointStart;
RichMat43 mat1 = RichMat43(joints[nunParentJointID].mat);
RichMat43 mat2 = RichMat43(joints[parentID].mat);
jointMatrix = mat1 * mat2.GetInverse();
if (bIsNUNO5Global && link.P5 == 0)
jointMatrix = mat1;
p = jointMatrix.TransformPoint(p);
g_mfn->Math_VecCopy(p.v, jointMatrix.m.o);
}

RichMat43 mat1 = RichMat43(joints[nunParentJointID].mat);
RichMat43 mat2 = RichMat43(joints[parentID].mat);
jointMatrix = mat1 * mat2.GetInverse();
if (bIsNUNO5Global && link.P5 == 0)
jointMatrix = mat1;
p = jointMatrix.TransformPoint(p);
g_mfn->Math_VecCopy(p.v, jointMatrix.m.o);

RichMat43 mat3 = RichMat43(joints[parentID].mat);
joint->mat = (jointMatrix * mat3).m;
if(bIsNUNO5Global && link.P5 == 0)//Model space coords if P5 is null, see 79d40f50
if(bIsNUNO5Global && link.P5 == 0)//Model space coords if P5 is null, see 79d40f50 from SoP, 7c68948e from WoLong
joint->mat = jointMatrix.m;
if(!bIsNUNO5Global)
snprintf(joint->name, 128, "nuno3_p_%d_bone_%d", nunParentJointID,jointIndex);
Expand Down Expand Up @@ -1744,8 +1741,8 @@ noesisModel_t* ProcessModel(BYTE* fileBuffer, int bufferLen, int& numMdl, noeRAP
//The depth buffer gives the distance from the driver, a is the "base position".
float depth = *(float*)(depthFromDriver + index + 12);
//Assume that NUNO normals and tangents always have float semantics, always the case so far. If it changes I'll implement half float support.
RichVec3 normalCoords = RichVec3((float*)(depthFromDriver + index));
RichVec3 tanCoords = RichVec3((float*)(physTanBuffer + index));
RichVec3 normalCoords = depthFromDriver ? RichVec3((float*)(depthFromDriver + index)) : RichVec3();
RichVec3 tanCoords = physTanBuffer ? RichVec3((float*)(physTanBuffer + index)) : RichVec3();
if (bBigEndian)
{
LITTLE_BIG_SWAP(depth);
Expand All @@ -1766,21 +1763,30 @@ noesisModel_t* ProcessModel(BYTE* fileBuffer, int bufferLen, int& numMdl, noeRAP
}

//normal coords
float tmp[3];
g_mfn->Math_TransformPointByMatrixNoTrans(&(joints + nunMapJointIndex[smIdx])->eData.parent->mat, normalCoords.v, tmp);
g_mfn->Math_VecCopy(tmp, normalCoords.v);
if (bBigEndian) {
normalCoords.ChangeEndian();
if (depthFromDriver)
{
float tmp[3];
g_mfn->Math_TransformPointByMatrixNoTrans(&(joints + nunMapJointIndex[smIdx])->eData.parent->mat, normalCoords.v, tmp);
g_mfn->Math_VecCopy(tmp, normalCoords.v);
if (bBigEndian) {
normalCoords.ChangeEndian();
}
g_mfn->Math_VecCopy(normalCoords.v, (float*)(depthFromDriver + index));
}
g_mfn->Math_VecCopy(normalCoords.v, (float*)(depthFromDriver + index));
}
else
{
RichVec3 d = b.Cross(c);
normalCoords = b * normalCoords.v[1] + c * normalCoords.v[0] + d * normalCoords.v[2];
normalCoords.Normalize();
tanCoords = b * tanCoords.v[1] + c * tanCoords.v[0] + d * tanCoords.v[2];
tanCoords.Normalize();
if (depthFromDriver)
{
normalCoords = b * normalCoords.v[1] + c * normalCoords.v[0] + d * normalCoords.v[2];
normalCoords.Normalize();
}
if (physTanBuffer)
{
tanCoords = b * tanCoords.v[1] + c * tanCoords.v[0] + d * tanCoords.v[2];
tanCoords.Normalize();
}

if (bIsNUNO5Global)
d = d.Normalized();
Expand All @@ -1791,14 +1797,18 @@ noesisModel_t* ProcessModel(BYTE* fileBuffer, int bufferLen, int& numMdl, noeRAP
normalCoords.ChangeEndian();
tanCoords.ChangeEndian();
}
g_mfn->Math_VecCopy(c.v, (float*)(controlPointsWeightsSet1 + index));
g_mfn->Math_VecCopy(normalCoords.v, (float*)(depthFromDriver + index));
g_mfn->Math_VecCopy(tanCoords.v, (float*)(physTanBuffer + index));
g_mfn->Math_VecCopy(c.v, (float*)(controlPointsWeightsSet1 + index));
if(depthFromDriver)
g_mfn->Math_VecCopy(normalCoords.v, (float*)(depthFromDriver + index));
if(physTanBuffer)
g_mfn->Math_VecCopy(tanCoords.v, (float*)(physTanBuffer + index));
}
}
rapi->rpgBindPositionBuffer(controlPointsWeightsSet1, RPGEODATA_FLOAT, phys1Stride);
rapi->rpgBindNormalBuffer(depthFromDriver, RPGEODATA_FLOAT, phys1Stride);
rapi->rpgBindTangentBuffer(physTanBuffer, RPGEODATA_FLOAT, phys1Stride);
if (depthFromDriver)
rapi->rpgBindNormalBuffer(depthFromDriver, RPGEODATA_FLOAT, phys1Stride);
if (physTanBuffer)
rapi->rpgBindTangentBuffer(physTanBuffer, RPGEODATA_FLOAT, phys1Stride);
if (bHasSkinnedParts && !bNUNO5HasSubsets) //temporary hack to disable anchored cloth for now when NUNO5 has subsets, treat it like the others
{
rapi->rpgBindBoneIndexBuffer(jointIBFinal, cPIdx1Type == EG1MGVADatatype::VADataType_UByte_x4 ? RPGEODATA_UBYTE : RPGEODATA_USHORT, cPIdx1Type == EG1MGVADatatype::VADataType_UByte_x4 ? 4 : 8, 4);
Expand Down Expand Up @@ -1831,10 +1841,13 @@ noesisModel_t* ProcessModel(BYTE* fileBuffer, int bufferLen, int& numMdl, noeRAP
}

bPID /= 3;
uint32_t jID = g1mg.jointPalettes[submesh.bonePaletteIndex].entries[bPID].physicsIndex &0x7FFFFFFF;
modelMatrix_t matrix = joints[jID].mat;
//Here we assume that the first internal skel has the physics joint's parent (which is always the case on all the samples)
transformPosF<bBigEndian>(posB + j*jStride, 1, jStride, &joints[jID].mat);
if (bPID < g1mg.jointPalettes[submesh.bonePaletteIndex].entries.size()) //See 0xb2e220c4/0x7c68948e from wolong. Implicit parenting to another internal skel or unneeded transformation?
{
uint32_t jID = g1mg.jointPalettes[submesh.bonePaletteIndex].entries[bPID].physicsIndex & 0x7FFFFFFF;
modelMatrix_t matrix = joints[jID].mat;
//Here we assume that the first internal skel has the physics joint's parent (which is always the case on all the samples)
transformPosF<bBigEndian>(posB + j * jStride, 1, jStride, &joints[jID].mat);
}
}
rapi->rpgBindPositionBuffer(posB, RPGEODATA_FLOAT, jStride);
}
Expand Down
32 changes: 28 additions & 4 deletions Source/Public/G1M/NUNO.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
#define NUNO4_MAGIC 0x00030004
#define NUNO5_MAGIC 0x00030005

#define NUNO5FLAG_SKIP0 (1<<0)
#define NUNO5FLAG_SKIP1 (1<<1)
#define NUNO5FLAG_SKIP2 (1<<2)

struct NunInfluence
{
int P1;
Expand Down Expand Up @@ -202,8 +206,11 @@ struct NUNO3
offset += 0x24;
for (auto l = 0; l < lodCount; l++)
{
uint32_t skip10Size = 0;
uint32_t skip10Count = 0;

uint32_t controlPointCount = *reinterpret_cast<uint32_t*>(buffer + offset);
uint32_t cpSectionRelatedCount = *reinterpret_cast<uint32_t*>(buffer + offset + 4);
uint32_t flags = *reinterpret_cast<uint32_t*>(buffer + offset + 4);
uint32_t skip1 = *reinterpret_cast<uint32_t*>(buffer + offset + 8);
uint32_t skip2 = *reinterpret_cast<uint32_t*>(buffer + offset + 12);
uint32_t skip3 = *reinterpret_cast<uint32_t*>(buffer + offset + 16);
Expand All @@ -213,12 +220,18 @@ struct NUNO3
uint32_t skip7 = *reinterpret_cast<uint32_t*>(buffer + offset + 32);
uint32_t skip8 = *reinterpret_cast<uint32_t*>(buffer + offset + 36);
uint32_t skip9 = *reinterpret_cast<uint32_t*>(buffer + offset + 40);
uint32_t bUseSkip10 = *reinterpret_cast<uint32_t*>(buffer + offset + 44);
if (bUseSkip10)
{
skip10Size = *reinterpret_cast<uint32_t*>(buffer + offset + 48);
skip10Count = *reinterpret_cast<uint32_t*>(buffer + offset + 52);
}

if (bBigEndian)
{
LITTLE_BIG_SWAP(lodCount);
LITTLE_BIG_SWAP(controlPointCount);
LITTLE_BIG_SWAP(cpSectionRelatedCount);
LITTLE_BIG_SWAP(flags);
LITTLE_BIG_SWAP(skip1);
LITTLE_BIG_SWAP(skip2);
LITTLE_BIG_SWAP(skip3);
Expand All @@ -228,8 +241,12 @@ struct NUNO3
LITTLE_BIG_SWAP(skip7);
LITTLE_BIG_SWAP(skip8);
LITTLE_BIG_SWAP(skip9);
LITTLE_BIG_SWAP(skip10Count);
LITTLE_BIG_SWAP(skip10Size);
}
offset += 0x30;
if (bUseSkip10)
offset += 8;
uint32_t cpOffset = *reinterpret_cast<uint32_t*>(buffer + offset);
if (bBigEndian)
LITTLE_BIG_SWAP(cpOffset);
Expand Down Expand Up @@ -264,15 +281,20 @@ struct NUNO3
offset += controlPointCount * 0x2C;

//Skipping the other parts, that define physics parameters and other info that we don't need
offset += 0x20 * controlPointCount;
if (cpSectionRelatedCount == 3)
if (flags & NUNO5FLAG_SKIP0)
offset += 0x20 * controlPointCount;
if (flags & NUNO5FLAG_SKIP1)
offset += 0x18 * controlPointCount;
offset += (skip1 * 4 + skip2 * 12 + skip3 * 16 + skip4 * 12 + skip5 * 8 + skip6 * 0x30 + skip7 * 0x48 + skip8*0x20);
if (flags & NUNO5FLAG_SKIP2)
offset += 0x4 * controlPointCount;
for (auto u = 0; u < skip9; u++)
{
uint32_t tempCount = *reinterpret_cast<uint32_t*>(buffer + offset);
offset += (tempCount * 4 + 0x10);
}
offset += skip10Count * skip10Size;

}
}
entrySize = offset - startOffset;
Expand Down Expand Up @@ -324,6 +346,8 @@ struct NUNO
break;
case NUNO5_MAGIC:
{
if (header.chunkVersion >= 0x30303335)
offset += 4;
checkpoint = 0;
bIsNUNO5Global = true; //Set the NUNO5 boolean to true for cloth processing. If I ever see NUNO3 and NUNO5 in the same model I'll change the logic.
std::map<uint32_t, uint32_t> entryIDToNunoID;
Expand Down

0 comments on commit 08a8de7

Please sign in to comment.