Skip to content

Commit abe6262

Browse files
committed
ecere/gfx3D/models/E3D: Initial support for reading bone skins and animations
1 parent 4f7e0f6 commit abe6262

File tree

2 files changed

+246
-2
lines changed

2 files changed

+246
-2
lines changed

ecere/src/gfx/3D/models/e3d/e3dDefs.ec

+2
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,8 @@ class E3DContext : struct
253253
Map<uint, bool> meshOwned { };
254254

255255
void (*saveCompressedCallback)(void * context, const String name, int width, int height, Bitmap bitmap);
256+
257+
Map<uint, Object> nodesByID { };
256258
}
257259

258260
class E3DWriteContext : struct

ecere/src/gfx/3D/models/e3d/e3dRead.ec

+244-2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,82 @@ static String readString(File f)
5050
return s;
5151
}
5252

53+
static void readMatrix(File f, Matrix matrix)
54+
{
55+
int i;
56+
57+
for(i = 0; i < 16; i++)
58+
{
59+
float v;
60+
f.Read(&v, sizeof(float), 1);
61+
matrix.array[i] = (double)v;
62+
}
63+
}
64+
65+
static void readTCBEase(File f, FrameTrack track)
66+
{
67+
int i;
68+
69+
for(i = 0; i < track.numKeys; i++)
70+
{
71+
f.Read(&track.keys[i].tension, sizeof(float), 1);
72+
f.Read(&track.keys[i].continuity, sizeof(float), 1);
73+
f.Read(&track.keys[i].bias, sizeof(float), 1);
74+
f.Read(&track.keys[i].easeFrom, sizeof(float), 1);
75+
f.Read(&track.keys[i].easeTo, sizeof(float), 1);
76+
}
77+
}
78+
79+
static void readFTKVector3Df(File f, FrameTrack track)
80+
{
81+
int i;
82+
83+
for(i = 0; i < track.numKeys; i++)
84+
f.Read(&track.keys[i].scaling.x, sizeof(float), 3);
85+
}
86+
87+
static void readFTKQuaternionf(File f, FrameTrack track)
88+
{
89+
int i;
90+
91+
for(i = 0; i < track.numKeys; i++)
92+
{
93+
Quaternion qd = track.keys[i].orientation;
94+
float q[4] = { (float)qd.w, (float)qd.x, (float)qd.y, (float)qd.z };
95+
f.Read(q, sizeof(float), 4);
96+
}
97+
}
98+
99+
static void readFTKFloat(File f, FrameTrack track)
100+
{
101+
int i;
102+
103+
for(i = 0; i < track.numKeys; i++)
104+
f.Read(&track.keys[i].roll, sizeof(float), 1);
105+
}
106+
107+
static void readFTKBool(File f, FrameTrack track)
108+
{
109+
int i;
110+
111+
for(i = 0; i < track.numKeys; i++)
112+
{
113+
byte hide = bool::false;
114+
f.Read(&hide, sizeof(byte), 1);
115+
// track.keys[i].hide = hide; // TODO: no hide keys yet?
116+
}
117+
}
118+
119+
static void readFTKMorph(File f, FrameTrack track)
120+
{
121+
int i;
122+
123+
for(i = 0; i < track.numKeys; i++)
124+
{
125+
// TODO:
126+
}
127+
}
128+
53129
#if defined(__GNOSIS3__)
54130
TempFile downloadFile(const String url);
55131
#else
@@ -170,6 +246,38 @@ static void readBlocks(E3DContext ctx, File f, DisplaySystem displaySystem, E3DB
170246
readSubBlocks = true;
171247
break;
172248
}
249+
case nodeID:
250+
{
251+
uint id = 0;
252+
f.Read(&id, sizeof(uint), 1);
253+
if(containerType == animationTrack)
254+
{
255+
FrameTrack track = (FrameTrack)data;
256+
Object object = ctx.nodesByID[id];
257+
if(object)
258+
object.tracks->Add(track);
259+
else
260+
{
261+
PrintLn("WARNING: Node not found for animation track");
262+
// delete track; // TODO: How to free this?
263+
}
264+
}
265+
else if(object)
266+
ctx.nodesByID[id] = object;
267+
break;
268+
}
269+
case nodeName:
270+
{
271+
Object p = object.parent;
272+
String name = readString(f);
273+
if(p)
274+
{
275+
p.Remove(object);
276+
p.AddName(object, name);
277+
}
278+
delete name;
279+
break;
280+
}
173281
case scaling:
174282
{
175283
Vector3Df v;
@@ -479,12 +587,21 @@ static void readBlocks(E3DContext ctx, File f, DisplaySystem displaySystem, E3DB
479587
int nVertices = mesh.nVertices;
480588
// bool qVerts = false;
481589
uint vSize = 0;
482-
uint vOffset = 0, nOffset = 0, t1Offset = 0, t2Offset = 0, tnOffset = 0, cOffset = 0;
590+
uint vOffset = 0, nOffset = 0, t1Offset = 0, t2Offset = 0, tnOffset = 0, cOffset = 0, bOffset = 0;
483591
bool signBitan = false;
592+
bool lastWasBones = false;
593+
uint maxBones = 0;
594+
MeshSkin skin = null;
595+
484596
while(pos < bEnd && f.Read(&type, sizeof(E3DBlockType), 1))
485597
{
486598
uint16 offset = 0;
487599
f.Read(&offset, sizeof(uint16), 1);
600+
if(lastWasBones)
601+
{
602+
maxBones = (offset - bOffset) / 2;
603+
lastWasBones = false;
604+
}
488605
pos += 4;
489606
if(!type)
490607
{
@@ -501,8 +618,16 @@ static void readBlocks(E3DContext ctx, File f, DisplaySystem displaySystem, E3DB
501618
case attrColors: features.colors = true; cOffset = offset; break;
502619
case attrTangentsSign: features.tangents = true; tnOffset = offset; signBitan = true; break;
503620
case attrTangentsBT: features.tangents = true; tnOffset = offset; break;
621+
case attrBoneWeights:
622+
// features.bones = true;
623+
bOffset = offset;
624+
lastWasBones = true;
625+
skin = { };
626+
skin.skinVerts.size = nVertices;
627+
break;
504628
}
505629
}
630+
mesh.skin = skin;
506631
allocedFeatures = features;
507632
allocedFeatures.vertices = true;
508633
if(allocedFeatures == { vertices = true, normals = true, texCoords1 = true })
@@ -514,6 +639,7 @@ static void readBlocks(E3DContext ctx, File f, DisplaySystem displaySystem, E3DB
514639
Vector3Df * vertex = null, * normal = null, * tangent = null, * bitangent = null;
515640
Pointf * texCoord = null, * texCoord2 = null;
516641
ColorRGBAf * color = null;
642+
SkinVert * bones = null;
517643
int i;
518644

519645
if(allocedFeatures.interleaved)
@@ -533,7 +659,8 @@ static void readBlocks(E3DContext ctx, File f, DisplaySystem displaySystem, E3DB
533659
if(!signBitan && features.tangents) bitangent = mesh.tangents+1;
534660
if(features.texCoords1) texCoord = (Pointf*)((byte *)mesh.texCoords);
535661
// if(features.texCoords2) texCoord2 = (Pointf*)((byte *)mesh.texCoords2);
536-
if(features.colors) color = (ColorRGBAf*)((byte *)mesh.colors + cOffset);
662+
if(features.colors) color = (ColorRGBAf*)((byte *)mesh.colors /*+ cOffset*/); // REVIEW: cOffset here?
663+
if(skin /*features.bones*/) bones = skin.skinVerts.array;
537664
}
538665

539666
for(i = 0; i < nVertices; i++)
@@ -561,6 +688,12 @@ static void readBlocks(E3DContext ctx, File f, DisplaySystem displaySystem, E3DB
561688
f.Seek(vStart + cOffset, start), f.Read(&c, sizeof(uint32), 1);
562689
*color = { c.r/255.0f, c.g/255.0f, c.b/255.0f, c.a/255.0f };
563690
}
691+
if(skin) //features.bones)
692+
{
693+
f.Seek(vStart + bOffset, start);
694+
f.Read(bones->bones, sizeof(byte), maxBones); // Asuming maxBones is 10 for now
695+
f.Read(bones->weights, sizeof(byte), maxBones);
696+
}
564697
if(tangent)
565698
{
566699
uint32 t, bt;
@@ -578,6 +711,7 @@ static void readBlocks(E3DContext ctx, File f, DisplaySystem displaySystem, E3DB
578711
if(texCoord2)texCoord2= (void *)((byte *)texCoord2+ (loadIL ? 32 : 8));
579712
if(tangent) tangent = (void *)((byte *)tangent + (loadIL ? 32 : signBitan ? 12 : 24));
580713
if(bitangent)bitangent= (void *)((byte *)bitangent+ (loadIL ? 32 : 24));
714+
if(bones) bones = bones + 1;
581715
}
582716
}
583717
break;
@@ -719,6 +853,93 @@ static void readBlocks(E3DContext ctx, File f, DisplaySystem displaySystem, E3DB
719853
mesh.FreePrimitiveGroup(group);
720854
break;
721855
}
856+
case meshDuplVerts:
857+
{
858+
// PrintLn("Duplicate Vertices!");
859+
break;
860+
}
861+
case skin:
862+
readSubBlocks = true;
863+
break;
864+
case skinBindMatrix:
865+
{
866+
MeshSkin skin = mesh.skin;
867+
868+
readMatrix(f, skin.bindShapeMatrix);
869+
skin.bsIsIdentity = skin.bindShapeMatrix.isIdentity();
870+
if(skin.bsIsIdentity)
871+
skin.invShape.Identity();
872+
else
873+
skin.invShape.Inverse(skin.bindShapeMatrix);
874+
break;
875+
}
876+
case skinBones:
877+
{
878+
byte count;
879+
int i;
880+
MeshSkin skin = mesh.skin;
881+
Array<SkinBone> bones = skin.bones;
882+
883+
f.Read(&count, sizeof(byte), 1);
884+
bones.size = count;
885+
886+
for(i = 0; i < count; i++)
887+
{
888+
bones[i].name = readString(f); // Could also be nodeID
889+
readMatrix(f, bones[i].invBindMatrix);
890+
bones[i].bsInvBindMatrix.Multiply(skin.bindShapeMatrix, bones[i].invBindMatrix);
891+
}
892+
break;
893+
}
894+
case animations: readSubBlocks = true; break;
895+
case animation: readSubBlocks = true; break;
896+
case animationName:
897+
break;
898+
case animationFrames:
899+
{
900+
int frame;
901+
f.Read(&frame, sizeof(int), 1);
902+
object.startFrame = frame;
903+
f.Read(&frame, sizeof(int), 1);
904+
object.endFrame = frame;
905+
f.Read(&frame, sizeof(int), 1);
906+
object.frame = frame;
907+
break;
908+
}
909+
case animationTrack:
910+
{
911+
uint loop;
912+
FrameTrack track { };
913+
int i;
914+
915+
f.Read(&track.numKeys, sizeof(uint), 1);
916+
pos += 4;
917+
f.Read(&loop, sizeof(byte), 1);
918+
pos ++;
919+
track.type.loop = loop != 0;
920+
track.keys = new0 FrameKey[track.numKeys];
921+
for(i = 0; i < track.numKeys; i++)
922+
f.Read(&track.keys[i].frame, sizeof(uint), 1);
923+
pos += sizeof(uint) * track.numKeys;
924+
925+
readSubBlocks = true;
926+
subData = track;
927+
break;
928+
}
929+
case frameTCBEase: { FrameTrack track = (FrameTrack) data; readTCBEase(f, track); break; }
930+
case ftkPosition: { FrameTrack track = (FrameTrack) data; track.type.type = position; readFTKVector3Df(f, track); break; }
931+
case ftkScaling: { FrameTrack track = (FrameTrack) data; track.type.type = scaling; readFTKVector3Df(f, track); break; }
932+
case ftkRotation: { FrameTrack track = (FrameTrack) data; track.type.type = rotation; readFTKQuaternionf(f, track); break; }
933+
case ftkYaw: { FrameTrack track = (FrameTrack) data; track.type.type = rYaw; readFTKFloat(f, track); break; }
934+
case ftkPitch: { FrameTrack track = (FrameTrack) data; track.type.type = rPitch; readFTKFloat(f, track); break; }
935+
case ftkRoll: { FrameTrack track = (FrameTrack) data; track.type.type = rRoll; readFTKFloat(f, track); break; }
936+
case ftkCameraFieldOfView: { FrameTrack track = (FrameTrack) data; track.type.type = fov; readFTKFloat(f, track); break; }
937+
case ftkCameraRoll: { FrameTrack track = (FrameTrack) data; track.type.type = roll; readFTKFloat(f, track); break; }
938+
case ftkLightHotSpot: { FrameTrack track = (FrameTrack) data; track.type.type = hotSpot; readFTKFloat(f, track); break; }
939+
case ftkLightFallOff: { FrameTrack track = (FrameTrack) data; track.type.type = fallOff; readFTKFloat(f, track); break; }
940+
case ftkLightColor: { FrameTrack track = (FrameTrack) data; track.type.type = colorChange; readFTKVector3Df(f, track); break; }
941+
case ftkHide: { FrameTrack track = (FrameTrack) data; track.type.type = hide; readFTKBool(f, track); break; }
942+
case ftkMorph: { FrameTrack track = (FrameTrack) data; track.type.type = morph; readFTKMorph(f, track); break; }
722943
case parts:
723944
{
724945
uint nParts = (uint)((bEnd - pos) / sizeof(MeshPart));
@@ -955,6 +1176,26 @@ void listTexturesReadBlocks(E3DContext ctx, File f, E3DBlockType containerType,
9551176
indent--;
9561177
}
9571178

1179+
static void resolveBones(Object root, Object object)
1180+
{
1181+
Object c;
1182+
if(object.mesh && object.mesh.skin)
1183+
{
1184+
int i;
1185+
1186+
for(i = 0; i < object.mesh.skin.bones.count; i++)
1187+
{
1188+
SkinBone * bone = &object.mesh.skin.bones[i];
1189+
String name = bone->name;
1190+
Object o = root.Find(name);
1191+
bone->object = o;
1192+
}
1193+
}
1194+
1195+
for(c = object.firstChild; c; c = c.next)
1196+
resolveBones(root, c);
1197+
}
1198+
9581199
void readE3D(File f, const String fileName, Object object, DisplaySystem displaySystem, E3DOptions options)
9591200
{
9601201
char path[MAX_LOCATION];
@@ -983,6 +1224,7 @@ void readE3D(File f, const String fileName, Object object, DisplaySystem display
9831224

9841225
StripLastDirectory(fileName, path);
9851226
readBlocks(ctx, f, displaySystem, 0, 0, f.GetSize(), object);
1227+
resolveBones(object, object);
9861228

9871229
if(freeTexturesByID)
9881230
delete ctx.texturesByID;

0 commit comments

Comments
 (0)