There are several parts of the source code that handle CAR files.
This code loads CAR files.
void LoadCharacterInfo(TCharacterInfo &chinfo, char* FName)
{
ReleaseCharacterInfo(chinfo);
HANDLE hfile = CreateFile(FName,
GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hfile==INVALID_HANDLE_VALUE) {
char sz[512];
wsprintf( sz, "Error opening character file:\n%s.", FName );
DoHalt(sz);
}
ReadFile(hfile, chinfo.ModelName, 32, &l, NULL);
ReadFile(hfile, &chinfo.AniCount, 4, &l, NULL);
ReadFile(hfile, &chinfo.SfxCount, 4, &l, NULL);
//============= read model =================//
chinfo.mptr = (TModel*) _HeapAlloc(Heap, 0, sizeof(TModel));
ReadFile( hfile, &chinfo.mptr->VCount, 4, &l, NULL );
ReadFile( hfile, &chinfo.mptr->FCount, 4, &l, NULL );
ReadFile( hfile, &chinfo.mptr->TextureSize, 4, &l, NULL );
ReadFile( hfile, chinfo.mptr->gFace, chinfo.mptr->FCount<<6, &l, NULL );
ReadFile( hfile, chinfo.mptr->gVertex, chinfo.mptr->VCount<<4, &l, NULL );
int ts = chinfo.mptr->TextureSize;
if (HARD3D) chinfo.mptr->TextureHeight = 256;
else chinfo.mptr->TextureHeight = chinfo.mptr->TextureSize>>9;
chinfo.mptr->TextureSize = chinfo.mptr->TextureHeight*512;
chinfo.mptr->lpTexture = (WORD*) _HeapAlloc(Heap, 0, chinfo.mptr->TextureSize);
ReadFile(hfile, chinfo.mptr->lpTexture, ts, &l, NULL);
DATASHIFT(chinfo.mptr->lpTexture, chinfo.mptr->TextureSize);
GenerateModelMipMaps(chinfo.mptr);
GenerateAlphaFlags(chinfo.mptr);
//ApplyAlphaFlags(chinfo.mptr->lpTexture, 256*256);
//ApplyAlphaFlags(chinfo.mptr->lpTexture2, 128*128);
//============= read animations =============//
for (int a=0; a<chinfo.AniCount; a++) {
ReadFile(hfile, chinfo.Animation[a].aniName, 32, &l, NULL);
ReadFile(hfile, &chinfo.Animation[a].aniKPS, 4, &l, NULL);
ReadFile(hfile, &chinfo.Animation[a].FramesCount, 4, &l, NULL);
chinfo.Animation[a].AniTime = (chinfo.Animation[a].FramesCount * 1000) / chinfo.Animation[a].aniKPS;
chinfo.Animation[a].aniData = (short int*)
_HeapAlloc(Heap, 0, (chinfo.mptr->VCount*chinfo.Animation[a].FramesCount*6) );
ReadFile(hfile, chinfo.Animation[a].aniData, (chinfo.mptr->VCount*chinfo.Animation[a].FramesCount*6), &l, NULL);
}
//============= read sound fx ==============//
BYTE tmp[32];
for (int s=0; s<chinfo.SfxCount; s++) {
ReadFile(hfile, tmp, 32, &l, NULL);
ReadFile(hfile, &chinfo.SoundFX[s].length, 4, &l, NULL);
chinfo.SoundFX[s].lpData = (short int*) _HeapAlloc(Heap, 0, chinfo.SoundFX[s].length);
ReadFile(hfile, chinfo.SoundFX[s].lpData, chinfo.SoundFX[s].length, &l, NULL);
}
for (int v=0; v<chinfo.mptr->VCount; v++) {
chinfo.mptr->gVertex[v].x*=2.f;
chinfo.mptr->gVertex[v].y*=2.f;
chinfo.mptr->gVertex[v].z*=-2.f;
}
CorrectModel(chinfo.mptr);
ReadFile(hfile, chinfo.Anifx, 64*4, &l, NULL);
if (l!=256)
for (l=0; l<64; l++) chinfo.Anifx[l] = -1;
CloseHandle(hfile);
}
byte
texture
16-bit TGA-style encoding in BGRA5551 format, always 256 pixels wide
--(c) RexHunter99 2009
utility GeomExp "Carnivores MAXScript"
(
group "Import"
(
button carImport "Import CAR" toolTip: "Import the entire scene"
)
group "Export"
(
button x3dfExport "Export 3DF" toolTip: "Export the entire scene"
button vtlExport "Export VTL" toolTip: "Export the animated scene"
)
group "About"
(
label lab1 "Carnivores MAXScript"
label lab2 "Version 1.2"
label lab3 "Made by Rexhunter99"
)
fn ReadCAR fname =
(
--Define some variables
cname = "NULL"
msc = "msc: 0"
num_tris = 0
num_verts = 0
num_anims = 0
num_sounds = 0
num_bones = 0
tri_list = #()
vert_list = #()
tex_list = #()
tc_x = #()
tc_y = #()
tex_size = 256*256*2
--Read the damned file >_<
f = fopen fname "rb"
--Read the header
cname = ReadString f
fseek f 24 #seek_set
msc = ReadString f
fseek f 32 #seek_set
num_anims = ReadLong f #signed
num_sounds = ReadLong f #signed
num_verts = ReadLong f #signed
num_tris = ReadLong f #signed
tex_size = ReadLong f #signed
for t=1 to num_tris do (
v1 = ReadLong f --Vert 1
v2 = ReadLong f --Vert 2
v3 = ReadLong f --Vert 3
tx1 = ReadLong f --U1
tx2 = ReadLong f --U2
tx3 = ReadLong f --U3
ty1 = ReadLong f --V1
ty2 = ReadLong f --V2
ty3 = ReadLong f --V3
flags = ReadLong f --Flags
fseek f 4 #seek_cur
par = ReadLong f --Parent
fseek f 4 #seek_cur
fseek f 4 #seek_cur
fseek f 4 #seek_cur
fseek f 4 #seek_cur
append tri_list ([v1+1,v2+1,v3+1])
append tc_x ((tx1/256.0) as float)
append tc_x ((tx2/256.0) as float)
append tc_x ((tx3/256.0) as float)
append tc_y ((ty1/256.0) as float)
append tc_y ((ty2/256.0) as float)
append tc_y ((ty3/256.0) as float)
)
for v=1 to num_verts do (
x = ReadFloat f --X
y = ReadFloat f --Z
z = ReadFloat f --Y
b = ReadLong f --Bone
if b>num_bones then
num_bones = b
append vert_list ([-x,z,y])
)
fclose f
mat = multiMaterial numsubs:1 name:cname
m = mesh name:cname position:[0, 0, 0] scale:[1, 1, 1] \
faces:tri_list vertices:vert_list material:mat
setNumTVerts m (num_tris * 3)
for f = 1 to (num_tris * 3) do
(
setTVert m (f+0) tc_x[f+0] tc_y[f+0] 0
)
-- Create our texture vertice faces
buildTVFaces m
for f = 1 to (num_tris-1) do
(
v1 = ((f - 1) * 3) + 1
v2 = ((f - 1) * 3) + 2
v3 = ((f - 1) * 3) + 3
setTVFace m f [v1,v2,v3]
)
)
fn Save3DF fname =
(
if fname == undefined then exit
obj = 0
obones = #()
numbones = 0
format "$objects.count = %\n" $objects.count
for o=1 to $objects.count do
(
if $objects[o].name[1]=="#" then
(
append obones $objects[o]
numbones += 1
format " % %\n" $objects[o].name $objects[o].parent
)
else
obj = $objects[o]
)
if $selection[1] == undefined then
(
obj = $objects[1]
)
else
(
obj = $selection[1]
)
format "BoneCount = %\n" numbones
numbones = 0
fp = fopen fname "wb"
WriteLong fp obj.numverts #unsigned
WriteLong fp obj.numfaces #unsigned
WriteLong fp numbones #unsigned
WriteLong fp (256*512) #unsigned
for i=1 to obj.numfaces do
(
f = getface obj i
t = gettvface obj i
tx = gettvert obj t.x
ty = gettvert obj t.y
tz = gettvert obj t.z
WriteLong fp (f.z-1) #unsigned
WriteLong fp (f.y-1) #unsigned
WriteLong fp (f.x-1) #unsigned
WriteLong fp (tz.x * 256) #unsigned
WriteLong fp (ty.x * 256) #unsigned
WriteLong fp (tx.x * 256) #unsigned
WriteLong fp (tz.y * 256) #unsigned
WriteLong fp (ty.y * 256) #unsigned
WriteLong fp (tx.y * 256) #unsigned
WriteLong fp 0
WriteLong fp 0
WriteLong fp -1
WriteLong fp 0
WriteLong fp 0
WriteLong fp 0
WriteLong fp 0
)
for i=1 to obj.numverts do
(
v = getvert obj i
WriteFloat fp (-v.x)
WriteFloat fp v.z
WriteFloat fp v.y
--Get the bone if the mesh is Skinned
WriteLong fp 0
)
for i=1 to numbones do
(
for c=1 to 32 do
(
if c >= obones[i].name.length then
WriteByte fp 0
else
WriteByte fp obones[i].name[c]
)
WriteFloat fp obones[i].x
WriteFloat fp obones[i].y
WriteFloat fp obones[i].z
WriteShort fp -1
WriteShort fp 0
)
texfp = fopen obj.material.diffuseMap.fileName "rb"
fseek texfp 18 #seek_set
for i=1 to 256*256 do
(
pixel = ReadShort texfp #unsigned
WriteShort fp pixel #unsigned
)
fclose texfp
fclose fp
)
fn SaveVTL fname =
(
if $selection[1] == undefined then
(
obj = $objects[1]
)
else
(
obj = $selection[1]
)
if fname == undefined then exit
num_frames = ( 1 + animationRange.end - animationRange.start )
fp = fopen fname "wb"
WriteLong fp obj.numverts #unsigned
WriteLong fp 20 #unsigned
WriteLong fp num_frames #unsigned
--Animation
sliderTime = animationRange.start
for i=animationRange.start to animationRange.end do
(
for j=1 to obj.numverts do
(
v = getvert obj j
WriteShort fp ((-v.x*16) as integer)
WriteShort fp ((v.z*16) as integer)
WriteShort fp ((v.y*16) as integer)
)
sliderTime+=1f
)
sliderTime = animationRange.start
fclose fp
)
on carImport pressed do
(
clearListener()
--Find a file
fname = getOpenFileName "Open a CAR file" \
types:"CAR (.car)|*.car|"
ReadCAR fname
)
on x3dfExport pressed do
(
clearListener()
--Find a file
fname = getSaveFileName "Save a 3DF file" \
types:"3D File (.3DF)|*.3DF|"
Save3DF fname
)
on vtlExport pressed do
(
clearListener()
--Find a file
fname = getSaveFileName "Save a VTL file" \
types:"Vertex Transformation List (.VTL)|*.VTL|"
SaveVTL fname
)
)