This commit is contained in:
parent
3d74ef38c3
commit
aeb95010d3
24 changed files with 7743 additions and 12 deletions
37
Utils/GinExp/ASCIIEXP.DSW
Normal file
37
Utils/GinExp/ASCIIEXP.DSW
Normal file
|
@ -0,0 +1,37 @@
|
|||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "asciiexp"=.\asciiexp.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
begin source code control
|
||||
"$/TP2psx/utils/GinExp", ZDXAAAAA
|
||||
.
|
||||
end source code control
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
begin source code control
|
||||
"$/TP2psx/utils/GinExp", HFXAAAAA
|
||||
.
|
||||
end source code control
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
BIN
Utils/GinExp/ASCIIEXP.opt
Normal file
BIN
Utils/GinExp/ASCIIEXP.opt
Normal file
Binary file not shown.
753
Utils/GinExp/ExpAnimKeys.cpp
Normal file
753
Utils/GinExp/ExpAnimKeys.cpp
Normal file
|
@ -0,0 +1,753 @@
|
|||
//**************************************************************************
|
||||
//* Animout.cpp - Ascii File Exporter
|
||||
//*
|
||||
//* By Christer Janson
|
||||
//* Kinetix Development
|
||||
//*
|
||||
//* January 20, 1997 CCJ Initial coding
|
||||
//*
|
||||
//* This module handles controller key output and controller sampling.
|
||||
//*
|
||||
//* Copyright (c) 1997, All Rights Reserved.
|
||||
//***************************************************************************
|
||||
|
||||
#include "asciiexp.h"
|
||||
|
||||
#define ALMOST_ZERO 1.0e-3f
|
||||
BOOL EqualPoint3(Point3 p1, Point3 p2);
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
TM Animation output
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
// Get hold of the transform controllers for the node...
|
||||
void AsciiExp::ExportAnimKeys( INode* node )
|
||||
{
|
||||
BOOL bPosAnim;
|
||||
BOOL bRotAnim;
|
||||
BOOL bScaleAnim;
|
||||
BOOL bDoKeys = FALSE;
|
||||
|
||||
// We can only export keys if all TM controllers are "known" to us.
|
||||
// The reason for that is that some controllers control more than what
|
||||
// they should. Consider a path position controller, if you turn on
|
||||
// follow and banking, this position controller will also control
|
||||
// rotation. If a node that had a path position controller also had a
|
||||
// TCB rotation controller, the TCB keys would not describe the whole
|
||||
// rotation of the node.
|
||||
// For that reason we will only export keys if all controllers
|
||||
// position, rotation and scale are linear, hybrid (bezier) or tcb.
|
||||
|
||||
/* if (!GetAlwaysSample())
|
||||
{
|
||||
Control* pC = node->GetTMController()->GetPositionController();
|
||||
Control* rC = node->GetTMController()->GetRotationController();
|
||||
Control* sC = node->GetTMController()->GetScaleController();
|
||||
|
||||
if (IsKnownController(pC) && IsKnownController(rC) && IsKnownController(sC))
|
||||
{
|
||||
bDoKeys = TRUE;
|
||||
}
|
||||
}
|
||||
*/
|
||||
if (bDoKeys)
|
||||
{
|
||||
// Only dump the track header if any of the controllers have keys
|
||||
if (node->GetTMController()->GetPositionController()->NumKeys() ||
|
||||
node->GetTMController()->GetRotationController()->NumKeys() ||
|
||||
node->GetTMController()->GetScaleController()->NumKeys())
|
||||
{
|
||||
// fprintf(pStream,"%s\t%s {\n", indent.data(), ID_TM_ANIMATION);
|
||||
// fprintf(pStream,"%s\t\t%s \"%s\"\n", indent.data(), ID_NODE_NAME, FixupName(node->GetName()));
|
||||
|
||||
DumpPosKeys(node->GetTMController()->GetPositionController());
|
||||
DumpRotKeys(node->GetTMController()->GetRotationController());
|
||||
DumpScaleKeys(node->GetTMController()->GetScaleController());
|
||||
|
||||
// fprintf(pStream,"%s\t}\n", indent.data());
|
||||
}
|
||||
}
|
||||
else if (CheckForAnimation(node, bPosAnim, bRotAnim, bScaleAnim))
|
||||
{
|
||||
// fprintf(pStream,"%s\t%s {\n", indent.data(), ID_TM_ANIMATION);
|
||||
// fprintf(pStream,"%s\t\t%s \"%s\"\n", indent.data(), ID_NODE_NAME, FixupName(node->GetName()));
|
||||
|
||||
if (bPosAnim) DumpPosSample(node);
|
||||
if (bRotAnim) DumpRotSample(node);
|
||||
if (bScaleAnim) DumpScaleSample(node);
|
||||
|
||||
// fprintf(pStream,"%s\t}\n", indent.data());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// To really see if a node is animated we can step through the animation range
|
||||
// and decompose the TM matrix for every frame and examine the components.
|
||||
// This way we can identify position, rotation and scale animation separately.
|
||||
//
|
||||
// Some controllers makes it problematic to examine the TMContollers instead of
|
||||
// the actual TMMatrix. For example, a path controller is a position controller,
|
||||
// but if you turn on follow and banking, it will also affect the rotation component.
|
||||
// If we want to, we can examine the position, rotation and scale controllers and
|
||||
// if they all are Linear, Hybrid (bezier) or TCB, then we could export the actual keys.
|
||||
// This is not at all difficult, but the importer has to know the exact interpolation
|
||||
// algorithm in order to use it. The source code to the interpolation routines are available
|
||||
// to ADN members.
|
||||
//
|
||||
// For an example of how to export actual keys, look at DumpPoint3Keys() below.
|
||||
// This method will check the actual controller to determine if the controller is known.
|
||||
// If we know how to work this controller, its actual keys will be exported,
|
||||
// otherwise the controller will be sampled using the user specified sampling frequency.
|
||||
|
||||
BOOL AsciiExp::CheckForAnimation(INode* node, BOOL& bPos, BOOL& bRot, BOOL& bScale)
|
||||
{
|
||||
TimeValue start = ip->GetAnimRange().Start();
|
||||
TimeValue end = ip->GetAnimRange().End();
|
||||
TimeValue t;
|
||||
int delta = GetTicksPerFrame();
|
||||
Matrix3 tm;
|
||||
AffineParts ap;
|
||||
Point3 firstPos;
|
||||
float rotAngle, firstRotAngle;
|
||||
Point3 rotAxis;
|
||||
Point3 firstScaleFactor;
|
||||
|
||||
bPos = bRot = bScale = FALSE;
|
||||
|
||||
for (t=start; t<=end; t+=delta)
|
||||
{
|
||||
tm = node->GetNodeTM(t) * Inverse(node->GetParentTM(t));
|
||||
|
||||
decomp_affine(tm, &ap);
|
||||
|
||||
AngAxisFromQ(ap.q, &rotAngle, rotAxis);
|
||||
|
||||
if (t != start)
|
||||
{
|
||||
// We examine the rotation angle to see if the rotation component
|
||||
// has changed.
|
||||
// Although not entierly true, it should work.
|
||||
// It is rare that the rotation axis is animated without
|
||||
// the rotation angle being somewhat affected.
|
||||
bPos = TRUE;
|
||||
bRot = TRUE;
|
||||
bScale = TRUE;
|
||||
// if (!EqualPoint3(ap.t, firstPos)) bPos = TRUE;
|
||||
// if (fabs(rotAngle - firstRotAngle) > ALMOST_ZERO) bRot = TRUE;
|
||||
// if (!EqualPoint3(ap.k, firstScaleFactor)) bScale = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
firstPos = ap.t;
|
||||
firstRotAngle = rotAngle;
|
||||
firstScaleFactor = ap.k;
|
||||
}
|
||||
|
||||
// No need to continue looping if all components are animated
|
||||
if (bPos && bRot && bScale) break;
|
||||
}
|
||||
|
||||
return bPos || bRot || bScale;
|
||||
}
|
||||
|
||||
|
||||
void AsciiExp::DumpPosQuatSample(INode* node)
|
||||
{
|
||||
// fprintf(pStream,"%s\t\t%s {\n", indent.data(), ID_POS_TRACK);
|
||||
|
||||
TimeValue start = ip->GetAnimRange().Start();
|
||||
TimeValue end = ip->GetAnimRange().End();
|
||||
TimeValue t;
|
||||
int delta = GetTicksPerFrame();
|
||||
Matrix3 tm;
|
||||
AffineParts ap;
|
||||
Point3 prevPos;
|
||||
Quat prevQ;
|
||||
Quat q;
|
||||
char name[256];
|
||||
|
||||
|
||||
sprintf( name, "%s", node->GetName() );
|
||||
fprintf( tempStream, "OUTPUTTING - %s\n", name ); // DEBUG FILE
|
||||
// fwrite( &name, sizeof(char), NAME_LENGTH, boneStream ); // WRITE BONE NAME
|
||||
|
||||
prevQ.Identity();
|
||||
|
||||
for (t=start; t<=end; t+=delta)
|
||||
{
|
||||
// TRANSLATION
|
||||
tm = node->GetNodeTM(t);// * Inverse(node->GetParentTM(t));
|
||||
decomp_affine(tm, &ap);
|
||||
|
||||
fwrite( &ap.t.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||||
fwrite( &ap.t.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||||
fwrite( &ap.t.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
|
||||
fwrite( &ap.q.x, sizeof(float), 1, expStream ); // WRITE BONE ROT X-AXIS
|
||||
fwrite( &ap.q.z, sizeof(float), 1, expStream ); // WRITE BONE ROT Y-AXIS
|
||||
fwrite( &ap.q.y, sizeof(float), 1, expStream ); // WRITE BONE ROT Z-AXIS
|
||||
fwrite( &ap.q.w, sizeof(float), 1, expStream ); // WRITE BONE ROT W ANGLE
|
||||
}
|
||||
}
|
||||
|
||||
void AsciiExp::DumpPosSample(INode* node)
|
||||
{
|
||||
// fprintf(pStream,"%s\t\t%s {\n", indent.data(), ID_POS_TRACK);
|
||||
|
||||
TimeValue start = ip->GetAnimRange().Start();
|
||||
TimeValue end = ip->GetAnimRange().End();
|
||||
TimeValue t;
|
||||
int delta = GetTicksPerFrame();
|
||||
Matrix3 tm;
|
||||
AffineParts ap;
|
||||
Point3 prevPos;
|
||||
Quat prevQ;
|
||||
Quat q;
|
||||
char name[256];
|
||||
|
||||
|
||||
sprintf( name, "%s", node->GetName() );
|
||||
fprintf( tempStream, "OUTPUTTING - %s\n", name ); // DEBUG FILE
|
||||
// fwrite( &name, sizeof(char), NAME_LENGTH, boneStream ); // WRITE BONE NAME
|
||||
|
||||
prevQ.Identity();
|
||||
|
||||
for (t=start; t<=end; t+=delta)
|
||||
{
|
||||
// TRANSLATION
|
||||
tm = node->GetNodeTM(t);// * Inverse(node->GetParentTM(t));
|
||||
decomp_affine(tm, &ap);
|
||||
|
||||
Point3 fpos;
|
||||
Point3 pos = ap.t;
|
||||
|
||||
prevPos = pos;
|
||||
|
||||
fpos.x = pos.x;
|
||||
fpos.y = pos.z;
|
||||
fpos.z = -pos.y;
|
||||
|
||||
fprintf( tempStream, " POS = %f %f %f\n", pos.x, pos.z, -pos.y );
|
||||
// fwrite( &fpos.x, sizeof(float), 1, boneStream ); // WRITE BONE X-POS
|
||||
// fwrite( &fpos.y, sizeof(float), 1, boneStream ); // WRITE BONE Y-POS
|
||||
// fwrite( &fpos.z, sizeof(float), 1, boneStream ); // WRITE BONE Z-POS
|
||||
|
||||
|
||||
// ROTATION
|
||||
tm = node->GetNodeTM(t);// * Inverse(node->GetParentTM(t));
|
||||
|
||||
decomp_affine(tm, &ap);
|
||||
|
||||
if (t == start)
|
||||
{
|
||||
q = ap.q;
|
||||
prevQ = ap.q; // SAVE BASE ROTATION, THEN USE THIS AS ROTATION ORIGIN
|
||||
}
|
||||
else
|
||||
{
|
||||
q = ap.q / prevQ;
|
||||
}
|
||||
|
||||
fprintf( tempStream, " QUAT = %f %f %f %f\n", q.x, q.y, q.z, q.w );
|
||||
// fwrite( &q.x, sizeof(float), 1, boneStream ); // WRITE BONE ROT X-AXIS
|
||||
// fwrite( &q.y, sizeof(float), 1, boneStream ); // WRITE BONE ROT Y-AXIS
|
||||
// fwrite( &q.z, sizeof(float), 1, boneStream ); // WRITE BONE ROT Z-AXIS
|
||||
// fwrite( &q.w, sizeof(float), 1, boneStream ); // WRITE BONE ROT W ANGLE
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AsciiExp::DumpRotSample(INode* node)
|
||||
{
|
||||
// fprintf(pStream,"%s\t\t%s {\n", indent.data(), ID_ROT_TRACK);
|
||||
|
||||
TimeValue start = ip->GetAnimRange().Start();
|
||||
TimeValue end = ip->GetAnimRange().End();
|
||||
TimeValue t;
|
||||
int delta = GetTicksPerFrame();
|
||||
Matrix3 tm;
|
||||
AffineParts ap;
|
||||
Quat prevQ;
|
||||
|
||||
prevQ.Identity();
|
||||
|
||||
for (t=start; t<=end; t+=delta)
|
||||
{
|
||||
tm = node->GetNodeTM(t) * Inverse(node->GetParentTM(t));
|
||||
|
||||
decomp_affine(tm, &ap);
|
||||
|
||||
// Rotation keys should be relative, so we need to convert these
|
||||
// absolute samples to relative values.
|
||||
|
||||
Quat q = ap.q / prevQ;
|
||||
prevQ = ap.q;
|
||||
|
||||
// No point in exporting null keys...
|
||||
// if (q.IsIdentity()) continue;
|
||||
|
||||
// Output the sample
|
||||
fprintf( tempStream, " QUAT = %f %f %f %f\n", q.x, q.y, q.z, q.w );
|
||||
// fprintf(pStream, "%s\t\t\t%s %d\t%s\n", indent.data(), ID_ROT_SAMPLE, t, Format(q));
|
||||
}
|
||||
|
||||
// fprintf(pStream,"%s\t\t}\n", indent.data());
|
||||
}
|
||||
|
||||
|
||||
void AsciiExp::DumpScaleSample(INode* node)
|
||||
{
|
||||
// fprintf(pStream,"%s\t\t%s {\n", indent.data(), ID_SCALE_TRACK);
|
||||
|
||||
TimeValue start = ip->GetAnimRange().Start();
|
||||
TimeValue end = ip->GetAnimRange().End();
|
||||
TimeValue t;
|
||||
int delta = GetTicksPerFrame();
|
||||
Matrix3 tm;
|
||||
AffineParts ap;
|
||||
Point3 prevFac;
|
||||
|
||||
for (t=start; t<=end; t+=delta)
|
||||
{
|
||||
tm = node->GetNodeTM(t) * Inverse(node->GetParentTM(t));
|
||||
decomp_affine(tm, &ap);
|
||||
|
||||
// Skip identical keys
|
||||
if (t!= start && EqualPoint3(ap.k, prevFac)) continue;
|
||||
|
||||
prevFac = ap.k;
|
||||
|
||||
// Output the sample
|
||||
// fprintf(pStream, "%s\t\t\t%s %d\t%s %s\n", indent.data(), ID_SCALE_SAMPLE, t, Format(ap.k), Format(ap.u));
|
||||
}
|
||||
|
||||
// fprintf(pStream,"%s\t\t}\n", indent.data());
|
||||
}
|
||||
|
||||
|
||||
// Output point3 keys if this is a known point3 controller that
|
||||
// supports key operations. Otherwise we will sample the controller
|
||||
// once for each frame to get the value.
|
||||
// Point3 controllers can control, for example, color.
|
||||
void AsciiExp::DumpPoint3Keys(Control* cont)
|
||||
{
|
||||
// Bug out if no controller.
|
||||
if (!cont) return;
|
||||
|
||||
int i;
|
||||
IKeyControl *ikc = NULL;
|
||||
|
||||
// If the user wants us to always sample, we will ignore the KeyControlInterface
|
||||
// if (!GetAlwaysSample()) ikc = GetKeyControlInterface(cont);
|
||||
|
||||
// TCB point3
|
||||
if (ikc && cont->ClassID() == Class_ID(TCBINTERP_POINT3_CLASS_ID, 0))
|
||||
{
|
||||
// fprintf(pStream,"%s\t\t%s {\n", indent.data(), ID_CONTROL_POINT3_TCB);
|
||||
for (i=0; i<ikc->GetNumKeys(); i++)
|
||||
{
|
||||
ITCBPoint3Key key;
|
||||
ikc->GetKey(i, &key);
|
||||
fprintf( tempStream, " KEYPOS = %f %f %f\n", key.val.x, key.val.y, key.val.z );
|
||||
// fprintf(pStream, "%s\t\t\t%s %d\t%s", indent.data(), ID_TCB_POINT3_KEY, key.time, Format(key.val));
|
||||
// Add TCB specific data
|
||||
// fprintf(pStream, "\t%s\t%s\t%s\t%s\t%s\n", Format(key.tens), Format(key.cont), Format(key.bias), Format(key.easeIn), Format(key.easeOut));
|
||||
}
|
||||
// fprintf(pStream,"%s\t\t}\n", indent.data());
|
||||
}
|
||||
// Bezier point3
|
||||
else if (ikc && cont->ClassID() == Class_ID(HYBRIDINTERP_POINT3_CLASS_ID, 0))
|
||||
{
|
||||
// fprintf(pStream,"%s\t\t%s {\n", indent.data(), ID_CONTROL_POINT3_BEZIER);
|
||||
for (i=0; i<ikc->GetNumKeys(); i++)
|
||||
{
|
||||
IBezPoint3Key key;
|
||||
ikc->GetKey(i, &key);
|
||||
fprintf( tempStream, " KEYPOS = %f %f %f\n", key.val.x, key.val.y, key.val.z );
|
||||
// fprintf(pStream, "%s\t\t\t%s %d\t%s", indent.data(), ID_BEZIER_POINT3_KEY, key.time, Format(key.val));
|
||||
// fprintf(pStream, "\t%s\t%s\t%d\n", Format(key.intan), Format(key.outtan), key.flags);
|
||||
}
|
||||
// fprintf(pStream,"%s\t\t}\n", indent.data());
|
||||
}
|
||||
// Bezier color
|
||||
else if (ikc && cont->ClassID() == Class_ID(HYBRIDINTERP_COLOR_CLASS_ID, 0))
|
||||
{
|
||||
// fprintf(pStream,"%s\t\t%s {\n", indent.data(), ID_CONTROL_COLOR_BEZIER);
|
||||
for (i=0; i<ikc->GetNumKeys(); i++)
|
||||
{
|
||||
IBezPoint3Key key;
|
||||
ikc->GetKey(i, &key);
|
||||
fprintf( tempStream, " KEYPOS = %f %f %f\n", key.val.x, key.val.y, key.val.z );
|
||||
// fprintf(pStream, "%s\t\t\t%s %d\t%s", indent.data(), ID_BEZIER_POINT3_KEY, key.time, Format(key.val));
|
||||
// fprintf(pStream, "\t%s\t%s\t%d\n", Format(key.intan), Format(key.outtan), key.flags);
|
||||
}
|
||||
// fprintf(pStream,"%s\t\t}\n", indent.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unknown controller, no key interface or sample on demand -
|
||||
// This might be a procedural controller or something else we
|
||||
// don't know about. The last resort is to get the value from the
|
||||
// controller at every n frames.
|
||||
|
||||
TSTR name;
|
||||
cont->GetClassName(name);
|
||||
// fprintf(pStream,"%s\t\t%s \"%s\" {\n", indent.data(), ID_CONTROL_POINT3_SAMPLE, FixupName(name));
|
||||
|
||||
// If it is animated at all...
|
||||
if (cont->IsAnimated())
|
||||
{
|
||||
// Get the range of the controller animation
|
||||
Interval range;
|
||||
// Get range of full animation
|
||||
Interval animRange = ip->GetAnimRange();
|
||||
TimeValue t = cont->GetTimeRange(TIMERANGE_ALL).Start();
|
||||
Point3 value;
|
||||
|
||||
// While we are inside the animation...
|
||||
while (animRange.InInterval(t))
|
||||
{
|
||||
// Sample the controller
|
||||
range = FOREVER;
|
||||
cont->GetValue(t, &value, range);
|
||||
|
||||
// Set time to start of controller validity interval
|
||||
t = range.Start();
|
||||
|
||||
// Output the sample
|
||||
fprintf( tempStream, " KEYPOS = %f %f %f\n", value.x, value.y, value.z );
|
||||
// fprintf(pStream, "%s\t\t\t%s %d\t%s\n", indent.data(), ID_POINT3_KEY, t, Format(value));
|
||||
|
||||
// If the end of the controller validity is beyond the
|
||||
// range of the animation
|
||||
if (range.End() > cont->GetTimeRange(TIMERANGE_ALL).End())
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
t = (range.End()/GetTicksPerFrame()+1) * GetTicksPerFrame();
|
||||
}
|
||||
}
|
||||
}
|
||||
// fprintf(pStream,"%s\t\t}\n", indent.data());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Output float keys if this is a known float controller that
|
||||
// supports key operations. Otherwise we will sample the controller
|
||||
// once for each frame to get the value.
|
||||
void AsciiExp::DumpFloatKeys(Control* cont)
|
||||
{
|
||||
if (!cont) return;
|
||||
|
||||
int i;
|
||||
IKeyControl *ikc = NULL;
|
||||
|
||||
// If the user wants us to always sample, we will ignore the KeyControlInterface
|
||||
// if (!GetAlwaysSample()) ikc = GetKeyControlInterface(cont);
|
||||
|
||||
// TCB float
|
||||
if (ikc && cont->ClassID() == Class_ID(TCBINTERP_FLOAT_CLASS_ID, 0))
|
||||
{
|
||||
// fprintf(pStream,"%s\t\t%s {\n", indent.data(), ID_CONTROL_FLOAT_TCB);
|
||||
for (i=0; i<ikc->GetNumKeys(); i++)
|
||||
{
|
||||
ITCBFloatKey key;
|
||||
ikc->GetKey(i, &key);
|
||||
// fprintf(pStream, "%s\t\t\t%s %d\t%s", indent.data(), ID_TCB_FLOAT_KEY, key.time, Format(key.val));
|
||||
// fprintf(pStream, "\t%s\t%s\t%s\t%s\t%s\n", Format(key.tens), Format(key.cont), Format(key.bias), Format(key.easeIn), Format(key.easeOut));
|
||||
}
|
||||
// fprintf(pStream,"%s\t\t}\n", indent.data());
|
||||
}
|
||||
// Bezier float
|
||||
else if (ikc && cont->ClassID() == Class_ID(HYBRIDINTERP_FLOAT_CLASS_ID, 0))
|
||||
{
|
||||
// fprintf(pStream,"%s\t\t%s {\n", indent.data(), ID_CONTROL_FLOAT_BEZIER);
|
||||
for (i=0; i<ikc->GetNumKeys(); i++)
|
||||
{
|
||||
IBezFloatKey key;
|
||||
ikc->GetKey(i, &key);
|
||||
// fprintf(pStream, "%s\t\t\t%s %d\t%s", indent.data(), ID_BEZIER_FLOAT_KEY, key.time, Format(key.val));
|
||||
// fprintf(pStream, "\t%s\t%s\t%d\n", Format(key.intan), Format(key.outtan), key.flags);
|
||||
}
|
||||
// fprintf(pStream,"%s\t\t}\n", indent.data());
|
||||
}
|
||||
else if (ikc && cont->ClassID() == Class_ID(LININTERP_FLOAT_CLASS_ID, 0))
|
||||
{
|
||||
// fprintf(pStream,"%s\t\t%s {\n", indent.data(), ID_CONTROL_FLOAT_LINEAR);
|
||||
for (i=0; i<ikc->GetNumKeys(); i++)
|
||||
{
|
||||
ILinFloatKey key;
|
||||
ikc->GetKey(i, &key);
|
||||
// fprintf(pStream, "%s\t\t\t%s %d\t%s\n", indent.data(), ID_FLOAT_KEY, key.time, Format(key.val));
|
||||
}
|
||||
// fprintf(pStream,"%s\t\t}\n", indent.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unknown controller, no key interface or sample on demand -
|
||||
// This might be a procedural controller or something else we
|
||||
// don't know about. The last resort is to get the value from the
|
||||
// controller at every n frames.
|
||||
|
||||
TSTR name;
|
||||
cont->GetClassName(name);
|
||||
// fprintf(pStream,"%s\t\t%s \"%s\" {\n", indent.data(), ID_CONTROL_FLOAT_SAMPLE, FixupName(name));
|
||||
|
||||
// If it is animated at all...
|
||||
if (cont->IsAnimated())
|
||||
{
|
||||
// Get the range of the controller animation
|
||||
Interval range;
|
||||
// Get range of full animation
|
||||
Interval animRange = ip->GetAnimRange();
|
||||
TimeValue t = cont->GetTimeRange(TIMERANGE_ALL).Start();
|
||||
float value;
|
||||
|
||||
// While we are inside the animation...
|
||||
while (animRange.InInterval(t))
|
||||
{
|
||||
// Sample the controller
|
||||
range = FOREVER;
|
||||
cont->GetValue(t, &value, range);
|
||||
|
||||
// Set time to start of controller validity interval
|
||||
t = range.Start();
|
||||
|
||||
// Output the sample
|
||||
// fprintf(pStream, "%s\t\t\t%s %d\t%s\n", indent.data(), ID_FLOAT_KEY, t, Format(value));
|
||||
|
||||
// If the end of the controller validity is beyond the
|
||||
// range of the animation
|
||||
if (range.End() > cont->GetTimeRange(TIMERANGE_ALL).End())
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
t = (range.End()/GetTicksPerFrame()+1) * GetTicksPerFrame();
|
||||
}
|
||||
}
|
||||
}
|
||||
// fprintf(pStream,"%s\t\t}\n", indent.data());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AsciiExp::DumpPosKeys(Control* cont)
|
||||
{
|
||||
if (!cont) return;
|
||||
|
||||
int i;
|
||||
IKeyControl *ikc = GetKeyControlInterface(cont);
|
||||
|
||||
// TCB position
|
||||
if (ikc && cont->ClassID() == Class_ID(TCBINTERP_POSITION_CLASS_ID, 0))
|
||||
{
|
||||
int numKeys;
|
||||
if (numKeys = ikc->GetNumKeys())
|
||||
{
|
||||
// fprintf(pStream,"%s\t\t%s {\n", indent.data(), ID_CONTROL_POS_TCB);
|
||||
for (i=0; i<numKeys; i++)
|
||||
{
|
||||
ITCBPoint3Key key;
|
||||
ikc->GetKey(i, &key);
|
||||
// fprintf(pStream, "%s\t\t\t%s %d\t%s", indent.data(), ID_TCB_POS_KEY, key.time, Format(key.val));
|
||||
// fprintf(pStream, "\t%s\t%s\t%s\t%s\t%s\n", Format(key.tens), Format(key.cont), Format(key.bias), Format(key.easeIn), Format(key.easeOut));
|
||||
}
|
||||
// fprintf(pStream,"%s\t\t}\n", indent.data());
|
||||
}
|
||||
}
|
||||
// Bezier position
|
||||
else if (ikc && cont->ClassID() == Class_ID(HYBRIDINTERP_POSITION_CLASS_ID, 0))
|
||||
{
|
||||
int numKeys;
|
||||
if(numKeys = ikc->GetNumKeys())
|
||||
{
|
||||
// fprintf(pStream,"%s\t\t%s {\n", indent.data(), ID_CONTROL_POS_BEZIER);
|
||||
for (i=0; i<numKeys; i++)
|
||||
{
|
||||
IBezPoint3Key key;
|
||||
ikc->GetKey(i, &key);
|
||||
// fprintf(pStream, "%s\t\t\t%s %d\t%s", indent.data(), ID_BEZIER_POS_KEY, key.time, Format(key.val));
|
||||
// fprintf(pStream, "\t%s\t%s\t%d\n", Format(key.intan), Format(key.outtan), key.flags);
|
||||
}
|
||||
// fprintf(pStream,"%s\t\t}\n", indent.data());
|
||||
}
|
||||
}
|
||||
// Linear position
|
||||
else if (ikc && cont->ClassID() == Class_ID(LININTERP_POSITION_CLASS_ID, 0))
|
||||
{
|
||||
int numKeys;
|
||||
if(numKeys = ikc->GetNumKeys())
|
||||
{
|
||||
// fprintf(pStream,"%s\t\t%s {\n", indent.data(), ID_CONTROL_POS_LINEAR);
|
||||
for (i=0; i<numKeys; i++)
|
||||
{
|
||||
ILinPoint3Key key;
|
||||
ikc->GetKey(i, &key);
|
||||
// fprintf(pStream, "%s\t\t\t%s %d\t%s\n", indent.data(), ID_POS_KEY, key.time, Format(key.val));
|
||||
}
|
||||
// fprintf(pStream,"%s\t\t}\n", indent.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AsciiExp::DumpRotKeys(Control* cont)
|
||||
{
|
||||
if (!cont) return;
|
||||
|
||||
int i;
|
||||
IKeyControl *ikc = GetKeyControlInterface(cont);
|
||||
|
||||
if (ikc && cont->ClassID() == Class_ID(TCBINTERP_ROTATION_CLASS_ID, 0))
|
||||
{
|
||||
int numKeys;
|
||||
if (numKeys = ikc->GetNumKeys())
|
||||
{
|
||||
// fprintf(pStream,"%s\t\t%s {\n", indent.data(), ID_CONTROL_ROT_TCB);
|
||||
for (i=0; i<numKeys; i++)
|
||||
{
|
||||
ITCBRotKey key;
|
||||
ikc->GetKey(i, &key);
|
||||
// fprintf(pStream, "%s\t\t\t%s %d\t%s", indent.data(), ID_TCB_ROT_KEY, key.time, Format(key.val));
|
||||
// fprintf(pStream, "\t%s\t%s\t%s\t%s\t%s\n", Format(key.tens), Format(key.cont), Format(key.bias), Format(key.easeIn), Format(key.easeOut));
|
||||
}
|
||||
// fprintf(pStream,"%s\t\t}\n", indent.data());
|
||||
}
|
||||
}
|
||||
else if (ikc && cont->ClassID() == Class_ID(HYBRIDINTERP_ROTATION_CLASS_ID, 0))
|
||||
{
|
||||
int numKeys;
|
||||
if (numKeys = ikc->GetNumKeys())
|
||||
{
|
||||
// fprintf(pStream,"%s\t\t%s {\n", indent.data(), ID_CONTROL_ROT_BEZIER);
|
||||
for (i=0; i<numKeys; i++)
|
||||
{
|
||||
IBezQuatKey key;
|
||||
ikc->GetKey(i, &key);
|
||||
// Quaternions are converted to AngAxis when written to file
|
||||
// There is no intan/outtan for Quat Rotations
|
||||
// fprintf(pStream, "%s\t\t\t%s %d\t%s\n", indent.data(), ID_ROT_KEY, key.time, Format(key.val));
|
||||
}
|
||||
// fprintf(pStream,"%s\t\t}\n", indent.data());
|
||||
}
|
||||
}
|
||||
else if (ikc && cont->ClassID() == Class_ID(LININTERP_ROTATION_CLASS_ID, 0))
|
||||
{
|
||||
int numKeys;
|
||||
if (numKeys = ikc->GetNumKeys())
|
||||
{
|
||||
// fprintf(pStream,"%s\t\t%s {\n", indent.data(), ID_CONTROL_ROT_LINEAR);
|
||||
for (i=0; i<numKeys; i++)
|
||||
{
|
||||
ILinRotKey key;
|
||||
ikc->GetKey(i, &key);
|
||||
// Quaternions are converted to AngAxis when written to file
|
||||
// fprintf(pStream, "%s\t\t\t%s %d\t%s\n", indent.data(), ID_ROT_KEY, key.time, Format(key.val));
|
||||
}
|
||||
// fprintf(pStream,"%s\t\t}\n", indent.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AsciiExp::DumpScaleKeys(Control* cont)
|
||||
{
|
||||
if (!cont) return;
|
||||
|
||||
int i;
|
||||
IKeyControl *ikc = GetKeyControlInterface(cont);
|
||||
|
||||
if (ikc && cont->ClassID() == Class_ID(TCBINTERP_SCALE_CLASS_ID, 0))
|
||||
{
|
||||
int numKeys;
|
||||
if (numKeys = ikc->GetNumKeys())
|
||||
{
|
||||
// fprintf(pStream,"%s\t\t%s {\n", indent.data(), ID_CONTROL_SCALE_TCB);
|
||||
for (i=0; i<numKeys; i++)
|
||||
{
|
||||
ITCBScaleKey key;
|
||||
ikc->GetKey(i, &key);
|
||||
// fprintf(pStream, "%s\t\t\t%s %d\t%s", indent.data(), ID_TCB_SCALE_KEY, key.time, Format(key.val));
|
||||
// fprintf(pStream, "\t%s\t%s\t%s\t%s\t%s\n", Format(key.tens), Format(key.cont), Format(key.bias), Format(key.easeIn), Format(key.easeOut));
|
||||
}
|
||||
// fprintf(pStream,"%s\t\t}\n", indent.data());
|
||||
}
|
||||
}
|
||||
else if (ikc && cont->ClassID() == Class_ID(HYBRIDINTERP_SCALE_CLASS_ID, 0))
|
||||
{
|
||||
int numKeys;
|
||||
if (numKeys = ikc->GetNumKeys())
|
||||
{
|
||||
// fprintf(pStream,"%s\t\t%s {\n", indent.data(), ID_CONTROL_SCALE_BEZIER);
|
||||
for (i=0; i<numKeys; i++)
|
||||
{
|
||||
IBezScaleKey key;
|
||||
ikc->GetKey(i, &key);
|
||||
// fprintf(pStream, "%s\t\t\t%s %d\t%s", indent.data(), ID_BEZIER_SCALE_KEY, key.time, Format(key.val));
|
||||
// fprintf(pStream, "\t%s\t%s\t%d\n", Format(key.intan), Format(key.outtan), key.flags);
|
||||
}
|
||||
// fprintf(pStream,"%s\t\t}\n", indent.data());
|
||||
}
|
||||
}
|
||||
else if (ikc && cont->ClassID() == Class_ID(LININTERP_SCALE_CLASS_ID, 0))
|
||||
{
|
||||
int numKeys;
|
||||
if (numKeys = ikc->GetNumKeys())
|
||||
{
|
||||
// fprintf(pStream,"%s\t\t%s {\n", indent.data(), ID_CONTROL_SCALE_LINEAR);
|
||||
for (i=0; i<numKeys; i++)
|
||||
{
|
||||
ILinScaleKey key;
|
||||
ikc->GetKey(i, &key);
|
||||
// fprintf(pStream, "%s\t\t\t%s %d\t%s\n", indent.data(), ID_SCALE_KEY, key.time, Format(key.val));
|
||||
}
|
||||
// fprintf(pStream,"%s\t\t}\n", indent.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Not truly the correct way to compare floats of arbitary magnitude...
|
||||
BOOL EqualPoint3(Point3 p1, Point3 p2)
|
||||
{
|
||||
if (fabs(p1.x - p2.x) > ALMOST_ZERO) return FALSE;
|
||||
if (fabs(p1.y - p2.y) > ALMOST_ZERO) return FALSE;
|
||||
if (fabs(p1.z - p2.z) > ALMOST_ZERO) return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
// Determine if a TM controller is known by the system.
|
||||
AsciiExp::IsKnownController(Control* cont)
|
||||
{
|
||||
ulong partA, partB;
|
||||
|
||||
if (!cont) return FALSE;
|
||||
|
||||
partA = cont->ClassID().PartA();
|
||||
partB = cont->ClassID().PartB();
|
||||
|
||||
if (partB != 0x00) return FALSE;
|
||||
|
||||
switch (partA)
|
||||
{
|
||||
case TCBINTERP_POSITION_CLASS_ID:
|
||||
case TCBINTERP_ROTATION_CLASS_ID:
|
||||
case TCBINTERP_SCALE_CLASS_ID:
|
||||
case HYBRIDINTERP_POSITION_CLASS_ID:
|
||||
case HYBRIDINTERP_ROTATION_CLASS_ID:
|
||||
case HYBRIDINTERP_SCALE_CLASS_ID:
|
||||
case LININTERP_POSITION_CLASS_ID:
|
||||
case LININTERP_ROTATION_CLASS_ID:
|
||||
case LININTERP_SCALE_CLASS_ID:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
991
Utils/GinExp/ExpBone.cpp
Normal file
991
Utils/GinExp/ExpBone.cpp
Normal file
|
@ -0,0 +1,991 @@
|
|||
/*=========================================================================
|
||||
|
||||
EXPBONE.CPP
|
||||
|
||||
Author: Tim Swann @ CLIMAX
|
||||
Created:
|
||||
Project:
|
||||
Purpose:
|
||||
|
||||
Copyright (c) 1998 Climax Development Ltd
|
||||
|
||||
===========================================================================*/
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Includes
|
||||
-------- */
|
||||
|
||||
#include "AsciiExp.h"
|
||||
|
||||
|
||||
/* Std Lib
|
||||
------- */
|
||||
|
||||
/* Glib
|
||||
---- */
|
||||
|
||||
/* Local
|
||||
----- */
|
||||
|
||||
/* Graphics
|
||||
-------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Tyepdefs && Defines
|
||||
------------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Structure defintions
|
||||
-------------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Positional Vars
|
||||
--------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function Prototypes
|
||||
------------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Vars
|
||||
---- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Data
|
||||
---- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
|
||||
void AsciiExp::ExportBones( INode* node )
|
||||
{
|
||||
|
||||
nbBones = 0;
|
||||
|
||||
WriteChunkHdr( (char*)BONE_ID, 0);
|
||||
fwrite( &nCurObj, sizeof( Uint32 ), 1, expStream );
|
||||
|
||||
ExportLimb( node );
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
static bool ThisIsABone( INode * node )
|
||||
{
|
||||
bool retval = false;
|
||||
char * nodeName;
|
||||
|
||||
nodeName = node->GetName();
|
||||
|
||||
// if (nodeName[0] == 'R' &&
|
||||
// nodeName[1] == 'O' &&
|
||||
// nodeName[2] == 'O' &&
|
||||
// nodeName[3] == 'T') retval = true;
|
||||
|
||||
retval = true;
|
||||
|
||||
return (retval);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
int AsciiExp::ValidateBoneKids( INode * node )
|
||||
{
|
||||
int nbChilds = node->NumberOfChildren();
|
||||
int childCnt = 0;
|
||||
|
||||
return nbChilds;
|
||||
}
|
||||
|
||||
|
||||
bool IsParent(INode *p, INode *c)
|
||||
{
|
||||
while (!c->IsRootNode()) {
|
||||
c=c->GetParentNode();
|
||||
if (c==p)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
void AsciiExp::ExportLimb( INode * node )
|
||||
{
|
||||
INode * ChildNode;
|
||||
ObjectState os = node->EvalWorldState( ip->GetAnimRange().Start() );
|
||||
Object * obj = node->EvalWorldState(ip->GetAnimRange().Start()).obj;
|
||||
long nbChilds;
|
||||
Matrix3 tm;
|
||||
AffineParts ap;
|
||||
|
||||
Quat q;
|
||||
char name[256];
|
||||
Point3 fpos;
|
||||
Point3 pos, p2;
|
||||
|
||||
// EXPORT BONE
|
||||
sprintf( name, "%s", node->GetName() );
|
||||
fprintf( tempStream, "OUTPUTTING - %s\n", name ); // DEBUG FILE
|
||||
fwrite( &name, sizeof(char), MAX_NAME_LENGTH, expStream ); // WRITE BONE NAME
|
||||
|
||||
// EXPORT WEIGHTS
|
||||
long nbVerts = 0;
|
||||
if (nbWeights)
|
||||
{
|
||||
fprintf( tempStream, "WEIGHTS:\n" );
|
||||
|
||||
for (int i=0;i<nbWeights;i++)
|
||||
{
|
||||
for (int n=0;n<Weights[i].nodecount;n++)
|
||||
{
|
||||
if (!strcmp(node->GetName(), Weights[i].names[n])) nbVerts++;
|
||||
}
|
||||
}
|
||||
fprintf( tempStream, " nbVerts = %d\n", nbVerts );
|
||||
fwrite( &nbVerts, sizeof(long), 1, expStream ); // WRITE BONE WEIGHT COUNT
|
||||
|
||||
if (nbVerts)
|
||||
{
|
||||
for (int i=0;i<nbWeights;i++)
|
||||
{
|
||||
for (int n=0;n<Weights[i].nodecount;n++)
|
||||
{
|
||||
if (!strcmp(node->GetName(), Weights[i].names[n]))
|
||||
{
|
||||
fwrite( &Weights[i].vertno, sizeof(long), 1, expStream );
|
||||
fwrite( &Weights[i].weights[n], sizeof(float), 1, expStream );
|
||||
fwrite( &Weights[i].Offsets[n].x, sizeof(float), 1, expStream);
|
||||
fwrite( &Weights[i].Offsets[n].z, sizeof(float), 1, expStream);
|
||||
fwrite( &Weights[i].Offsets[n].y, sizeof(float), 1, expStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fwrite( &nbVerts, sizeof(long), 1, expStream ); // WRITE BONE WEIGHT COUNT
|
||||
}
|
||||
|
||||
// EXPORT CHILDREN
|
||||
|
||||
nbBones++;
|
||||
nbChilds = node->NumberOfChildren();
|
||||
fwrite( &nbChilds, sizeof(int), 1, expStream);
|
||||
for (int c=0;c<nbChilds;c++) // RUN THROUGH ALL OF THE CHILDREN
|
||||
{
|
||||
ChildNode = node->GetChildNode(c);
|
||||
if (ChildNode) ExportLimb( ChildNode );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
void AsciiExp::ExportBoneAnim( INode* node )
|
||||
{
|
||||
TimeValue start = ip->GetAnimRange().Start();
|
||||
TimeValue end = ip->GetAnimRange().End();
|
||||
TimeValue t;
|
||||
int delta = GetTicksPerFrame();
|
||||
Matrix3 tm;
|
||||
AffineParts ap;
|
||||
Point3 prevPos;
|
||||
Point3 startScale;
|
||||
Quat prevQ;
|
||||
Quat scaleQ;
|
||||
Quat q;
|
||||
Quat InvQ;
|
||||
INode * ChildNode;
|
||||
ObjectState os = node->EvalWorldState( ip->GetAnimRange().Start() );
|
||||
Object * obj = node->EvalWorldState(ip->GetAnimRange().Start()).obj;
|
||||
long nbChilds;
|
||||
|
||||
|
||||
for (t=start; t<=end; t+=delta)
|
||||
{
|
||||
// TRANSLATION
|
||||
if (0)//node->IsRootNode())
|
||||
{
|
||||
tm = node->GetNodeTM( t );
|
||||
} else
|
||||
{
|
||||
tm = node->GetNodeTM(t) * Inverse(node->GetParentTM(t));
|
||||
}
|
||||
decomp_affine(tm, &ap);
|
||||
|
||||
fwrite( &ap.t.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||||
fwrite( &ap.t.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||||
fwrite( &ap.t.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
|
||||
fwrite( &ap.q.x, sizeof(float), 1, expStream ); // WRITE BONE ROT X-AXIS
|
||||
fwrite( &ap.q.z, sizeof(float), 1, expStream ); // WRITE BONE ROT Y-AXIS
|
||||
fwrite( &ap.q.y, sizeof(float), 1, expStream ); // WRITE BONE ROT Z-AXIS
|
||||
fwrite( &ap.q.w, sizeof(float), 1, expStream ); // WRITE BONE ROT W ANGLE
|
||||
|
||||
fwrite( &ap.k.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||||
fwrite( &ap.k.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||||
fwrite( &ap.k.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
|
||||
fwrite( &ap.u.x, sizeof(float), 1, expStream ); // WRITE BONE ROT X-AXIS
|
||||
fwrite( &ap.u.z, sizeof(float), 1, expStream ); // WRITE BONE ROT Y-AXIS
|
||||
fwrite( &ap.u.y, sizeof(float), 1, expStream ); // WRITE BONE ROT Z-AXIS
|
||||
fwrite( &ap.u.w, sizeof(float), 1, expStream ); // WRITE BONE ROT W ANGLE
|
||||
}
|
||||
|
||||
nbChilds = node->NumberOfChildren();
|
||||
for (int c=0;c<nbChilds;c++) // RUN THROUGH ALL OF THE CHILDREN
|
||||
{
|
||||
ChildNode = node->GetChildNode(c);
|
||||
if (ChildNode) ExportBoneAnim( ChildNode );
|
||||
}
|
||||
}
|
||||
|
||||
void AsciiExp::ExportBoneKeyAnim( INode* node)
|
||||
{
|
||||
TimeValue start = ip->GetAnimRange().Start();
|
||||
TimeValue end = ip->GetAnimRange().End();
|
||||
int delta = GetTicksPerFrame();
|
||||
Matrix3 tm;
|
||||
AffineParts ap, StartAp;
|
||||
Point3 prevPos;
|
||||
Point3 startScale;
|
||||
Quat prevQ;
|
||||
Quat scaleQ;
|
||||
Quat q;
|
||||
Quat InvQ;
|
||||
INode * ChildNode;
|
||||
ObjectState os = node->EvalWorldState( ip->GetAnimRange().Start() );
|
||||
Object * obj = node->EvalWorldState(ip->GetAnimRange().Start()).obj;
|
||||
long nbChilds;
|
||||
|
||||
int num;
|
||||
int i;
|
||||
int FrameN;
|
||||
Interval ivalid;
|
||||
IKey k;
|
||||
Control *c;
|
||||
IKeyControl *ikeys;
|
||||
ITCBPoint3Key tcbPosKey;
|
||||
ITCBRotKey tcbRotKey;
|
||||
ITCBScaleKey tcbSclKey;
|
||||
IBezPoint3Key bezPosKey;
|
||||
IBezQuatKey bezRotKey;
|
||||
IBezScaleKey bezSclKey;
|
||||
ILinPoint3Key linPosKey;
|
||||
ILinRotKey linRotKey;
|
||||
ILinScaleKey linSclKey;
|
||||
TimeValue time;
|
||||
|
||||
|
||||
if (node->EvalWorldState(ip->GetAnimRange().Start()).obj) {
|
||||
|
||||
TimeList tl;
|
||||
tl.Clear();
|
||||
INode *KeyNode = node;
|
||||
c = KeyNode->GetTMController();
|
||||
if (c) {
|
||||
c = c->GetPositionController();
|
||||
if (c) {
|
||||
ikeys = GetKeyControlInterface(c);
|
||||
if (ikeys) {
|
||||
|
||||
num = ikeys->GetNumKeys();
|
||||
if (num >0)
|
||||
{
|
||||
for (i = 0; i<num; i++) {
|
||||
if (c->ClassID() == Class_ID(TCBINTERP_POSITION_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(i, &tcbPosKey);
|
||||
time = tcbPosKey.time;
|
||||
} else
|
||||
if (c->ClassID() == Class_ID(HYBRIDINTERP_POSITION_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(i, &bezPosKey);
|
||||
time = bezPosKey.time;
|
||||
} else
|
||||
if (c->ClassID() == Class_ID(LININTERP_POSITION_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(i, &linPosKey);
|
||||
time = linPosKey.time;
|
||||
}
|
||||
tl.Add(time);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
c = KeyNode->GetTMController();
|
||||
if (c) {
|
||||
c = c->GetRotationController();
|
||||
if (c) {
|
||||
ikeys = GetKeyControlInterface(c);
|
||||
if (ikeys) {
|
||||
|
||||
num = ikeys->GetNumKeys();
|
||||
if (num >0)
|
||||
{
|
||||
|
||||
for (i = 0; i<num; i++) {
|
||||
if (c->ClassID() == Class_ID(TCBINTERP_ROTATION_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(i, &tcbRotKey);
|
||||
int rots;
|
||||
if (i)
|
||||
{
|
||||
ITCBRotKey oldtcbRotKey;
|
||||
ikeys->GetKey(i-1, &oldtcbRotKey);
|
||||
rots = fabs(tcbRotKey.val.angle - oldtcbRotKey.val.angle) / (0.6667 * PI) + 1;
|
||||
for (int k=1; k<rots; k++)
|
||||
{
|
||||
tl.Add(oldtcbRotKey.time+(int)((float)k*(tcbRotKey.time-oldtcbRotKey.time)/rots));
|
||||
}
|
||||
}
|
||||
time = tcbRotKey.time;
|
||||
} else
|
||||
if (c->ClassID() == Class_ID(HYBRIDINTERP_ROTATION_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(i, &bezRotKey);
|
||||
time = bezRotKey.time;
|
||||
} else
|
||||
if (c->ClassID() == Class_ID(LININTERP_ROTATION_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(i, &linRotKey);
|
||||
time = linRotKey.time;
|
||||
}
|
||||
tl.Add(time);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
c = KeyNode->GetTMController();
|
||||
if (c) {
|
||||
c = c->GetScaleController();
|
||||
if (c) {
|
||||
ikeys = GetKeyControlInterface(c);
|
||||
if (ikeys) {
|
||||
|
||||
num = ikeys->GetNumKeys();
|
||||
if (num >0)
|
||||
{
|
||||
for (i = 0; i<num; i++) {
|
||||
if (c->ClassID() == Class_ID(TCBINTERP_SCALE_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(i, &tcbSclKey);
|
||||
time = tcbSclKey.time;
|
||||
} else
|
||||
if (c->ClassID() == Class_ID(HYBRIDINTERP_SCALE_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(i, &bezSclKey);
|
||||
time = bezSclKey.time;
|
||||
} else
|
||||
if (c->ClassID() == Class_ID(LININTERP_SCALE_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(i, &linSclKey);
|
||||
time = linSclKey.time;
|
||||
}
|
||||
|
||||
tl.Add(time);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tl.Count()) {
|
||||
num = tl.Count();
|
||||
WriteChunkHdr( (char*)KEY_ID, 0);
|
||||
fwrite( &CHANNEL_TYPE_BONE, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &CHANNEL_INFO_ALL, sizeof( Uint32) , 1, expStream);
|
||||
fwrite( &nCurObj, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &CurBone, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &num, sizeof( Uint32 ), 1, expStream );
|
||||
|
||||
for (num = 0; num <tl.Count(); num++) {
|
||||
time = tl.Get(num);
|
||||
tm = node->GetNodeTM(time) * Inverse(node->GetParentTM(time));
|
||||
|
||||
FrameN = (int)((float)(time - start) / delta);
|
||||
|
||||
decomp_affine(tm, &ap);
|
||||
if (num == 0)
|
||||
StartAp = ap;
|
||||
|
||||
fwrite( &FrameN, sizeof(Uint32), 1, expStream);
|
||||
fwrite( &ap.t.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||||
fwrite( &ap.t.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||||
fwrite( &ap.t.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
|
||||
fwrite( &ap.q.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||||
fwrite( &ap.q.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||||
fwrite( &ap.q.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
fwrite( &ap.q.w, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
|
||||
fwrite( &ap.k.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||||
fwrite( &ap.k.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||||
fwrite( &ap.k.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
|
||||
fwrite( &ap.u.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||||
fwrite( &ap.u.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||||
fwrite( &ap.u.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
fwrite( &ap.u.w, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
CurBone++;
|
||||
nbChilds = node->NumberOfChildren();
|
||||
for (int cn=0;cn<nbChilds;cn++) // RUN THROUGH ALL OF THE CHILDREN
|
||||
{
|
||||
ChildNode = node->GetChildNode(cn);
|
||||
if (ChildNode) ExportBoneKeyAnim( ChildNode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AsciiExp::ExportBoneKeyAnimPos( INode* node)
|
||||
{
|
||||
TimeValue start = ip->GetAnimRange().Start();
|
||||
TimeValue end = ip->GetAnimRange().End();
|
||||
int delta = GetTicksPerFrame();
|
||||
Matrix3 tm;
|
||||
AffineParts ap;
|
||||
Point3 prevPos;
|
||||
Point3 startScale;
|
||||
Quat prevQ;
|
||||
Quat scaleQ;
|
||||
Quat q;
|
||||
Quat InvQ;
|
||||
INode * ChildNode;
|
||||
ObjectState os = node->EvalWorldState( ip->GetAnimRange().Start() );
|
||||
Object * obj = node->EvalWorldState(ip->GetAnimRange().Start()).obj;
|
||||
long nbChilds;
|
||||
|
||||
int num;
|
||||
int i;
|
||||
int FrameN;
|
||||
Interval ivalid;
|
||||
IKey k;
|
||||
Control *c;
|
||||
IKeyControl *ikeys;
|
||||
ITCBPoint3Key tcbPosKey;
|
||||
ITCBRotKey tcbRotKey;
|
||||
ITCBScaleKey tcbScaleKey;
|
||||
IBezPoint3Key bezPosKey;
|
||||
IBezQuatKey bezRotKey;
|
||||
IBezScaleKey bezScaleKey;
|
||||
ILinPoint3Key linPosKey;
|
||||
ILinRotKey linRotKey;
|
||||
ILinScaleKey linScaleKey;
|
||||
TimeValue time;
|
||||
|
||||
if (node->EvalWorldState(ip->GetAnimRange().Start()).obj) {
|
||||
TimeList tl;
|
||||
tl.Clear();
|
||||
INode *KeyNode = node;
|
||||
while (KeyNode) {
|
||||
c = KeyNode->GetTMController();
|
||||
if (c) {
|
||||
c = c->GetPositionController();
|
||||
if (c) {
|
||||
ikeys = GetKeyControlInterface(c);
|
||||
if (ikeys) {
|
||||
|
||||
num = ikeys->GetNumKeys();
|
||||
if (num >0)
|
||||
{
|
||||
for (i = 0; i<num; i++) {
|
||||
if (c->ClassID() == Class_ID(TCBINTERP_POSITION_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(i, &tcbPosKey);
|
||||
time = tcbPosKey.time;
|
||||
} else
|
||||
if (c->ClassID() == Class_ID(HYBRIDINTERP_POSITION_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(i, &bezPosKey);
|
||||
time = bezPosKey.time;
|
||||
} else
|
||||
if (c->ClassID() == Class_ID(LININTERP_POSITION_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(i, &linPosKey);
|
||||
time = linPosKey.time;
|
||||
}
|
||||
tl.Add(time);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (KeyNode->IsRootNode())
|
||||
break;
|
||||
KeyNode = KeyNode->GetParentNode();
|
||||
}
|
||||
if (tl.Count()) {
|
||||
num = tl.Count();
|
||||
WriteChunkHdr( (char*)KEY_ID, 0);
|
||||
fwrite( &CHANNEL_TYPE_BONE, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &CHANNEL_INFO_POSITION, sizeof( Uint32) , 1, expStream);
|
||||
fwrite( &nCurObj, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &CurBone, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &num, sizeof( Uint32 ), 1, expStream );
|
||||
|
||||
for (num = 0; num <tl.Count(); num++) {
|
||||
time = tl.Get(num);
|
||||
tm = node->GetNodeTM(time) * Inverse(node->GetParentTM(time));
|
||||
|
||||
FrameN = (int)((float)(time - start) / delta);
|
||||
|
||||
decomp_affine(tm, &ap);
|
||||
|
||||
fwrite( &FrameN, sizeof(Uint32), 1, expStream);
|
||||
fwrite( &ap.t.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||||
fwrite( &ap.t.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||||
fwrite( &ap.t.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
CurBone++;
|
||||
nbChilds = node->NumberOfChildren();
|
||||
for (int cn=0;cn<nbChilds;cn++) // RUN THROUGH ALL OF THE CHILDREN
|
||||
{
|
||||
ChildNode = node->GetChildNode(cn);
|
||||
if (ChildNode) ExportBoneKeyAnimPos( ChildNode);
|
||||
}
|
||||
}
|
||||
|
||||
void AsciiExp::ExportBoneKeyAnimRot( INode* node)
|
||||
{
|
||||
TimeValue start = ip->GetAnimRange().Start();
|
||||
TimeValue end = ip->GetAnimRange().End();
|
||||
int delta = GetTicksPerFrame();
|
||||
Matrix3 tm;
|
||||
AffineParts ap;
|
||||
Point3 prevPos;
|
||||
Point3 startScale;
|
||||
Quat prevQ;
|
||||
Quat scaleQ;
|
||||
Quat q;
|
||||
Quat InvQ;
|
||||
INode * ChildNode;
|
||||
ObjectState os = node->EvalWorldState( ip->GetAnimRange().Start() );
|
||||
Object * obj = node->EvalWorldState(ip->GetAnimRange().Start()).obj;
|
||||
long nbChilds;
|
||||
|
||||
|
||||
int num;
|
||||
int i;
|
||||
int FrameN;
|
||||
Interval ivalid;
|
||||
IKey k;
|
||||
Control *c;
|
||||
IKeyControl *ikeys;
|
||||
ITCBPoint3Key tcbPosKey;
|
||||
ITCBRotKey tcbRotKey;
|
||||
ITCBScaleKey tcbScaleKey;
|
||||
IBezPoint3Key bezPosKey;
|
||||
IBezQuatKey bezRotKey;
|
||||
IBezScaleKey bezScaleKey;
|
||||
ILinPoint3Key linPosKey;
|
||||
ILinRotKey linRotKey;
|
||||
ILinScaleKey linScaleKey;
|
||||
TimeValue time;
|
||||
|
||||
if (node->EvalWorldState(ip->GetAnimRange().Start()).obj) {
|
||||
TimeList tl;
|
||||
tl.Clear();
|
||||
INode *KeyNode = node;
|
||||
while (KeyNode) {
|
||||
c = KeyNode->GetTMController();
|
||||
if (c) {
|
||||
c = c->GetRotationController();
|
||||
if (c) {
|
||||
ikeys = GetKeyControlInterface(c);
|
||||
if (ikeys) {
|
||||
|
||||
num = ikeys->GetNumKeys();
|
||||
if (num >0)
|
||||
{
|
||||
|
||||
for (i = 0; i<num; i++) {
|
||||
if (c->ClassID() == Class_ID(TCBINTERP_ROTATION_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(i, &tcbRotKey);
|
||||
time = tcbRotKey.time;
|
||||
} else
|
||||
if (c->ClassID() == Class_ID(HYBRIDINTERP_ROTATION_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(i, &bezRotKey);
|
||||
time = bezRotKey.time;
|
||||
} else
|
||||
if (c->ClassID() == Class_ID(LININTERP_ROTATION_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(i, &linRotKey);
|
||||
time = linRotKey.time;
|
||||
}
|
||||
tl.Add(time);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (KeyNode->IsRootNode())
|
||||
break;
|
||||
KeyNode = KeyNode->GetParentNode();
|
||||
}
|
||||
|
||||
if (tl.Count()) {
|
||||
num = tl.Count();
|
||||
WriteChunkHdr( (char*)KEY_ID, 0);
|
||||
fwrite( &CHANNEL_TYPE_BONE, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &CHANNEL_INFO_ROTATION, sizeof( Uint32) , 1, expStream);
|
||||
fwrite( &nCurObj, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &CurBone, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &num, sizeof( Uint32 ), 1, expStream );
|
||||
for (num = 0; num <tl.Count(); num++) {
|
||||
time = tl.Get(num);
|
||||
tm = node->GetNodeTM(time) * Inverse(node->GetParentTM(time));
|
||||
|
||||
FrameN = (int)((float)(time - start) / delta);
|
||||
|
||||
decomp_affine(tm, &ap);
|
||||
|
||||
fwrite( &FrameN, sizeof(Uint32), 1, expStream);
|
||||
fwrite( &ap.q.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||||
fwrite( &ap.q.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||||
fwrite( &ap.q.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
fwrite( &ap.q.w, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CurBone++;
|
||||
|
||||
nbChilds = node->NumberOfChildren();
|
||||
for (int cn=0;cn<nbChilds;cn++) // RUN THROUGH ALL OF THE CHILDREN
|
||||
{
|
||||
ChildNode = node->GetChildNode(cn);
|
||||
if (ChildNode) ExportBoneKeyAnimRot( ChildNode);
|
||||
}
|
||||
}
|
||||
|
||||
void AsciiExp::ExportBoneKeyAnimScl( INode* node)
|
||||
{
|
||||
TimeValue start = ip->GetAnimRange().Start();
|
||||
TimeValue end = ip->GetAnimRange().End();
|
||||
int delta = GetTicksPerFrame();
|
||||
Matrix3 tm;
|
||||
AffineParts ap;
|
||||
Point3 prevPos;
|
||||
Point3 startScale;
|
||||
Quat prevQ;
|
||||
Quat scaleQ;
|
||||
Quat q;
|
||||
Quat InvQ;
|
||||
INode * ChildNode;
|
||||
ObjectState os = node->EvalWorldState( ip->GetAnimRange().Start() );
|
||||
Object * obj = node->EvalWorldState(ip->GetAnimRange().Start()).obj;
|
||||
long nbChilds;
|
||||
|
||||
int num;
|
||||
int i;
|
||||
int FrameN;
|
||||
Interval ivalid;
|
||||
IKey k;
|
||||
Control *c;
|
||||
IKeyControl *ikeys;
|
||||
ITCBPoint3Key tcbPosKey;
|
||||
ITCBRotKey tcbRotKey;
|
||||
ITCBScaleKey tcbSclKey;
|
||||
IBezPoint3Key bezPosKey;
|
||||
IBezQuatKey bezRotKey;
|
||||
IBezScaleKey bezSclKey;
|
||||
ILinPoint3Key linPosKey;
|
||||
ILinRotKey linRotKey;
|
||||
ILinScaleKey linSclKey;
|
||||
TimeValue time;
|
||||
|
||||
char text[200];
|
||||
sprintf(text, "%s", node->GetName());
|
||||
|
||||
if (node->EvalWorldState(ip->GetAnimRange().Start()).obj) {
|
||||
TimeList tl;
|
||||
tl.Clear();
|
||||
INode *KeyNode = node;
|
||||
while (KeyNode) {
|
||||
c = KeyNode->GetTMController();
|
||||
if (c) {
|
||||
c = c->GetScaleController();
|
||||
if (c) {
|
||||
ikeys = GetKeyControlInterface(c);
|
||||
if (ikeys) {
|
||||
|
||||
num = ikeys->GetNumKeys();
|
||||
if (num >0)
|
||||
{
|
||||
for (i = 0; i<num; i++) {
|
||||
if (c->ClassID() == Class_ID(TCBINTERP_SCALE_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(i, &tcbSclKey);
|
||||
time = tcbSclKey.time;
|
||||
} else
|
||||
if (c->ClassID() == Class_ID(HYBRIDINTERP_SCALE_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(i, &bezSclKey);
|
||||
time = bezSclKey.time;
|
||||
} else
|
||||
if (c->ClassID() == Class_ID(LININTERP_SCALE_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(i, &linSclKey);
|
||||
time = linSclKey.time;
|
||||
}
|
||||
|
||||
tl.Add(time);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (KeyNode->IsRootNode())
|
||||
break;
|
||||
KeyNode = KeyNode->GetParentNode();
|
||||
}
|
||||
|
||||
if (tl.Count()) {
|
||||
num = tl.Count();
|
||||
WriteChunkHdr( (char*)KEY_ID, 0);
|
||||
fwrite( &CHANNEL_TYPE_BONE, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &CHANNEL_INFO_SCALE, sizeof( Uint32) , 1, expStream);
|
||||
fwrite( &nCurObj, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &CurBone, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &num, sizeof( Uint32 ), 1, expStream );
|
||||
|
||||
for (num = 0; num <tl.Count(); num++) {
|
||||
time = tl.Get(num);
|
||||
tm = node->GetNodeTM(time) * Inverse(node->GetParentTM(time));
|
||||
|
||||
FrameN = (int)((float)(time - start) / delta);
|
||||
|
||||
decomp_affine(tm, &ap);
|
||||
|
||||
fwrite( &FrameN, sizeof(Uint32), 1, expStream);
|
||||
fwrite( &ap.k.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||||
fwrite( &ap.k.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||||
fwrite( &ap.k.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
|
||||
fwrite( &ap.u.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||||
fwrite( &ap.u.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||||
fwrite( &ap.u.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
fwrite( &ap.u.w, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
}
|
||||
}
|
||||
}
|
||||
CurBone++;
|
||||
nbChilds = node->NumberOfChildren();
|
||||
for (int cn=0;cn<nbChilds;cn++) // RUN THROUGH ALL OF THE CHILDREN
|
||||
{
|
||||
ChildNode = node->GetChildNode(cn);
|
||||
if (ChildNode) ExportBoneKeyAnimScl( ChildNode);
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
void AsciiExp::ExportWeights( INode* node )
|
||||
{
|
||||
Object * objPtr = NULL;
|
||||
Modifier * phyMod = NULL;
|
||||
IPhysiqueExport * phyExport = NULL;
|
||||
IPhyContextExport * contextExport = NULL;
|
||||
IPhyVertexExport * vtxExport = NULL;
|
||||
IPhyRigidVertex * rvtExport = NULL;
|
||||
IPhyBlendedRigidVertex * brvExport = NULL;
|
||||
Point3 offsetvector;
|
||||
INode * bonenode = NULL;
|
||||
float weight = 0.f;
|
||||
int nbNodes = 0;
|
||||
int vtype = 0;
|
||||
INode * RootNode = NULL;
|
||||
ModContext *mc;
|
||||
|
||||
|
||||
Weights = NULL;
|
||||
|
||||
phyMod = FindPhysiqueModifier (node, &mc);
|
||||
if (phyMod)
|
||||
{
|
||||
PhyMc = mc;
|
||||
phyExport = (IPhysiqueExport *)phyMod->GetInterface( I_PHYINTERFACE );
|
||||
if (phyExport)
|
||||
{
|
||||
contextExport = (IPhyContextExport *)phyExport->GetContextInterface( node );
|
||||
if (contextExport)
|
||||
{
|
||||
contextExport->ConvertToRigid( TRUE );
|
||||
contextExport->AllowBlending( TRUE );
|
||||
|
||||
nbWeights = contextExport->GetNumberVertices();
|
||||
|
||||
Weights = (WEIGHTS *)malloc( nbWeights * sizeof(WEIGHTS) );
|
||||
|
||||
for (int i=0;i<nbWeights;i++)
|
||||
{
|
||||
vtxExport = (IPhyVertexExport *)contextExport->GetVertexInterface( i );
|
||||
|
||||
if (vtxExport)
|
||||
{
|
||||
vtype = vtxExport->GetVertexType();
|
||||
|
||||
if (vtype == RIGID_TYPE)
|
||||
{
|
||||
rvtExport = (IPhyRigidVertex *)vtxExport;
|
||||
bonenode = rvtExport->GetNode();
|
||||
|
||||
Weights[i].vertno = i;
|
||||
Weights[i].nodecount = 1;
|
||||
Weights[i].weights[0] = 1.f;
|
||||
Weights[i].Offsets[0] = rvtExport->GetOffsetVector();
|
||||
sprintf( Weights[i].names[0], "%s", bonenode->GetName() );
|
||||
}
|
||||
else
|
||||
{
|
||||
brvExport = (IPhyBlendedRigidVertex *)vtxExport;
|
||||
nbNodes = brvExport->GetNumberNodes();
|
||||
|
||||
Weights[i].vertno = i;
|
||||
Weights[i].nodecount = nbNodes;
|
||||
if (nbNodes > MAX_BONE_NODES)
|
||||
{
|
||||
MessageBox( MAX_hWnd, "INCREASE MAX_BONE_NODES", "ERROR", MB_OK );
|
||||
return;
|
||||
}
|
||||
for (int n=0;n<nbNodes;n++)
|
||||
{
|
||||
bonenode = brvExport->GetNode( n );
|
||||
|
||||
weight = brvExport->GetWeight( n );
|
||||
offsetvector = brvExport->GetOffsetVector( n );
|
||||
|
||||
Weights[i].weights[n] = weight;
|
||||
Weights[i].Offsets[n] = brvExport->GetOffsetVector(n);
|
||||
sprintf( Weights[i].names[n], "%s", bonenode->GetName() );
|
||||
}
|
||||
}
|
||||
|
||||
contextExport->ReleaseVertexInterface( vtxExport );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ExportBones(ip->GetRootNode());
|
||||
if (Weights) {
|
||||
free (Weights);
|
||||
Weights = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AsciiExp::IsBoned(INode *node)
|
||||
{
|
||||
if (FindPhysiqueModifier(node))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
|
||||
Modifier * AsciiExp::FindPhysiqueModifier (INode* node, ModContext**mc)
|
||||
{
|
||||
// Get object from node. Abort if no object.
|
||||
Object* ObjectPtr = node->GetObjectRef();
|
||||
|
||||
if (!ObjectPtr) return NULL;
|
||||
|
||||
// Is derived object ?
|
||||
if (ObjectPtr->SuperClassID() == GEN_DERIVOB_CLASS_ID)
|
||||
{
|
||||
// Yes -> Cast.
|
||||
IDerivedObject* DerivedObjectPtr = static_cast<IDerivedObject*>(ObjectPtr);
|
||||
|
||||
// Iterate over all entries of the modifier stack.
|
||||
int ModStackIndex = 0;
|
||||
while (ModStackIndex < DerivedObjectPtr->NumModifiers())
|
||||
{
|
||||
// Get current modifier.
|
||||
Modifier* ModifierPtr = DerivedObjectPtr->GetModifier(ModStackIndex);
|
||||
|
||||
// Is this Physique ?
|
||||
if (ModifierPtr->ClassID() == Class_ID(PHYSIQUE_CLASS_ID_A, PHYSIQUE_CLASS_ID_B))
|
||||
{
|
||||
*mc = DerivedObjectPtr->GetModContext(ModStackIndex);
|
||||
// Yes -> Exit.
|
||||
return ModifierPtr;
|
||||
}
|
||||
|
||||
// Next modifier stack entry.
|
||||
ModStackIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
// Not found.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Modifier * AsciiExp::FindPhysiqueModifier (INode* node)
|
||||
{
|
||||
// Get object from node. Abort if no object.
|
||||
Object* ObjectPtr = node->GetObjectRef();
|
||||
|
||||
if (!ObjectPtr) return NULL;
|
||||
|
||||
// Is derived object ?
|
||||
if (ObjectPtr->SuperClassID() == GEN_DERIVOB_CLASS_ID)
|
||||
{
|
||||
// Yes -> Cast.
|
||||
IDerivedObject* DerivedObjectPtr = static_cast<IDerivedObject*>(ObjectPtr);
|
||||
|
||||
// Iterate over all entries of the modifier stack.
|
||||
int ModStackIndex = 0;
|
||||
while (ModStackIndex < DerivedObjectPtr->NumModifiers())
|
||||
{
|
||||
// Get current modifier.
|
||||
Modifier* ModifierPtr = DerivedObjectPtr->GetModifier(ModStackIndex);
|
||||
|
||||
// Is this Physique ?
|
||||
if (ModifierPtr->ClassID() == Class_ID(PHYSIQUE_CLASS_ID_A, PHYSIQUE_CLASS_ID_B))
|
||||
{
|
||||
// Yes -> Exit.
|
||||
return ModifierPtr;
|
||||
}
|
||||
|
||||
// Next modifier stack entry.
|
||||
ModStackIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
// Not found.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*===========================================================================
|
||||
end */
|
237
Utils/GinExp/ExpCamLight.cpp
Normal file
237
Utils/GinExp/ExpCamLight.cpp
Normal file
|
@ -0,0 +1,237 @@
|
|||
/*=========================================================================
|
||||
|
||||
.CPP
|
||||
|
||||
Author: Tim Swann @ CLIMAX
|
||||
Created:
|
||||
Project:
|
||||
Purpose:
|
||||
|
||||
Copyright (c) 1998 Climax Development Ltd
|
||||
|
||||
===========================================================================*/
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Includes
|
||||
-------- */
|
||||
|
||||
#include "AsciiExp.h"
|
||||
|
||||
|
||||
/* Std Lib
|
||||
------- */
|
||||
|
||||
/* Glib
|
||||
---- */
|
||||
|
||||
/* Local
|
||||
----- */
|
||||
|
||||
/* Graphics
|
||||
-------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Tyepdefs && Defines
|
||||
------------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Structure defintions
|
||||
-------------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Positional Vars
|
||||
--------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function Prototypes
|
||||
------------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Vars
|
||||
---- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Data
|
||||
---- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
void AsciiExp::ExportCamera(INode* node)
|
||||
{
|
||||
INode * target = node->GetTarget();
|
||||
CameraState cs;
|
||||
TimeValue t = 0;
|
||||
Interval valid = FOREVER;
|
||||
Interval animRange = ip->GetAnimRange();
|
||||
ObjectState os = node->EvalWorldState(t);
|
||||
CameraObject * cam = (CameraObject *)os.obj;
|
||||
|
||||
|
||||
cam->EvalCameraState(t, valid, &cs);
|
||||
|
||||
if (target)
|
||||
{
|
||||
WriteChunkHdr( (char*)CAMERA_ID, 0 );
|
||||
fwrite( &totFrames, sizeof( Uint32 ), 1, expStream );
|
||||
|
||||
DumpCamPosSample( node );
|
||||
DumpCamPosSample( target );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
void AsciiExp::DumpCamPosSample(INode* node)
|
||||
{
|
||||
TimeValue start = ip->GetAnimRange().Start();
|
||||
TimeValue end = ip->GetAnimRange().End();
|
||||
TimeValue t;
|
||||
int delta = GetTicksPerFrame() * 1;
|
||||
Matrix3 tm;
|
||||
AffineParts ap;
|
||||
Point3 pos;
|
||||
Point3 opos;
|
||||
|
||||
|
||||
for (t=start; t<=end; t+=delta)
|
||||
{
|
||||
tm = node->GetNodeTM(t);
|
||||
|
||||
decomp_affine(tm, &ap);
|
||||
|
||||
pos = ap.t;
|
||||
|
||||
opos.x = pos.x;
|
||||
opos.y = pos.z;
|
||||
opos.z = pos.y;
|
||||
|
||||
fwrite( &opos.x, sizeof( float ), 1, expStream ); // WRITE CAMERA POSITION
|
||||
fwrite( &opos.y, sizeof( float ), 1, expStream );
|
||||
fwrite( &opos.z, sizeof( float ), 1, expStream );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
void AsciiExp::ExportLight(INode* node)
|
||||
{
|
||||
Interval valid = FOREVER;
|
||||
Matrix3 mtx = node->GetNodeTM( 0 );
|
||||
ObjectState os = node->EvalWorldState( 0 );
|
||||
GenLight * light;
|
||||
LightState ls;
|
||||
AffineParts ap;
|
||||
Point3 pos;
|
||||
Point3 opos;
|
||||
float ang[4];
|
||||
Point3 oang;
|
||||
Quat rot;
|
||||
INode * target;
|
||||
float hotsize;
|
||||
float fallsize;
|
||||
float attenStart;
|
||||
float attenEnd;
|
||||
|
||||
|
||||
|
||||
if (!os.obj) return;
|
||||
|
||||
// EXPORT LIGHT
|
||||
WriteChunkHdr( (char*)LIGHT_ID, 0 );
|
||||
|
||||
light = (GenLight*)os.obj;
|
||||
light->EvalLightState( 0, valid, &ls );
|
||||
fwrite( &ls.type, sizeof(long), 1, expStream );
|
||||
|
||||
decomp_affine( mtx, &ap );
|
||||
|
||||
pos = ap.t;
|
||||
|
||||
opos.x = pos.x;
|
||||
opos.y = pos.z;
|
||||
opos.z = pos.y;
|
||||
|
||||
fwrite( &opos.x, sizeof( float ), 1, expStream ); // WRITE LIGHT POSITION
|
||||
fwrite( &opos.y, sizeof( float ), 1, expStream );
|
||||
fwrite( &opos.z, sizeof( float ), 1, expStream );
|
||||
|
||||
rot.x = ap.q.x;
|
||||
rot.y = ap.q.z;
|
||||
rot.z = ap.q.y;
|
||||
rot.w = ap.q.w;
|
||||
QuatToEuler( rot, ang);
|
||||
|
||||
oang.x = ang[0];
|
||||
oang.y = ang[1];
|
||||
oang.z = ang[2];
|
||||
// fwrite( &oang.x, sizeof( float ), 1, expStream ); // WRITE LIGHT ROTATION
|
||||
// fwrite( &oang.y, sizeof( float ), 1, expStream );
|
||||
// fwrite( &oang.z, sizeof( float ), 1, expStream );
|
||||
|
||||
target = node->GetTarget();
|
||||
if (target)
|
||||
{
|
||||
mtx = target->GetNodeTM( 0 );
|
||||
decomp_affine( mtx, &ap );
|
||||
|
||||
pos = ap.t;
|
||||
|
||||
opos.x = pos.x;
|
||||
opos.y = pos.z;
|
||||
opos.z = pos.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
// opos.x = 0.f;
|
||||
// opos.y = 0.f;
|
||||
// opos.z = 0.f;
|
||||
}
|
||||
fwrite( &opos.x, sizeof( float ), 1, expStream ); // WRITE LIGHT POSITION
|
||||
fwrite( &opos.y, sizeof( float ), 1, expStream );
|
||||
fwrite( &opos.z, sizeof( float ), 1, expStream );
|
||||
|
||||
fwrite( &ls.color.r, sizeof( float ), 1, expStream );
|
||||
fwrite( &ls.color.g, sizeof( float ), 1, expStream );
|
||||
fwrite( &ls.color.b, sizeof( float ), 1, expStream );
|
||||
fwrite( &ls.intens, sizeof( float ), 1, expStream );
|
||||
|
||||
|
||||
|
||||
hotsize = 0.f;
|
||||
fallsize = 0.f;
|
||||
attenStart = 0.f;
|
||||
attenEnd = 0.f;
|
||||
|
||||
if (ls.type != OMNI_LIGHT)
|
||||
{
|
||||
hotsize = ls.hotsize;
|
||||
fallsize = ls.fallsize;
|
||||
}
|
||||
if (ls.type != DIR_LIGHT && ls.useAtten)
|
||||
{
|
||||
attenStart = ls.attenStart;
|
||||
attenEnd = ls.attenEnd;
|
||||
}
|
||||
|
||||
fwrite( &hotsize, sizeof( float ), 1, expStream );
|
||||
fwrite( &fallsize, sizeof( float ), 1, expStream );
|
||||
fwrite( &attenStart, sizeof( float ), 1, expStream );
|
||||
fwrite( &attenEnd, sizeof( float ), 1, expStream );
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================
|
||||
end */
|
550
Utils/GinExp/ExpFFD.cpp
Normal file
550
Utils/GinExp/ExpFFD.cpp
Normal file
|
@ -0,0 +1,550 @@
|
|||
#include "max.h"
|
||||
#include "asciiexp.h"
|
||||
|
||||
#define EDITMESH_CLASS_ID 0x00050
|
||||
|
||||
typedef Tab<Point3> Point3Tab;
|
||||
//typedef Tab<AnimPoint3> AnimPoint3Tab;
|
||||
typedef Tab<Face> FaceTab;
|
||||
|
||||
class XFormProc {
|
||||
public:
|
||||
virtual Point3 proc(Point3& p, Matrix3 &mat, Matrix3 &imat)=0;
|
||||
virtual void SetMat( Matrix3& mat ) {}
|
||||
};
|
||||
|
||||
class MoveXForm : public XFormProc {
|
||||
private:
|
||||
Point3 delta, tdelta;
|
||||
public:
|
||||
Point3 proc(Point3& p, Matrix3 &mat, Matrix3 &imat)
|
||||
{ return p + tdelta; }
|
||||
void SetMat( Matrix3& mat )
|
||||
{ tdelta = VectorTransform(Inverse(mat),delta); }
|
||||
MoveXForm(Point3 d) { delta = d; }
|
||||
};
|
||||
|
||||
class RotateXForm : public XFormProc {
|
||||
private:
|
||||
Matrix3 rot, trot;
|
||||
public:
|
||||
Point3 proc(Point3& p, Matrix3 &mat, Matrix3 &imat)
|
||||
{ return (trot*p)*imat; }
|
||||
void SetMat( Matrix3& mat )
|
||||
{ trot = mat * rot; }
|
||||
RotateXForm(Quat q) { q.MakeMatrix(rot); }
|
||||
};
|
||||
|
||||
class ScaleXForm : public XFormProc {
|
||||
private:
|
||||
Matrix3 scale, tscale;
|
||||
public:
|
||||
Point3 proc(Point3& p, Matrix3 &mat, Matrix3 &imat)
|
||||
{ return (p*tscale)*imat; }
|
||||
void SetMat( Matrix3& mat )
|
||||
{ tscale = mat*scale; }
|
||||
ScaleXForm(Point3 s) { scale = ScaleMatrix(s); }
|
||||
};
|
||||
|
||||
|
||||
class VertexDelta {
|
||||
public:
|
||||
Point3Tab deltas; //DS-- I needed this public
|
||||
BitArray hide;
|
||||
|
||||
void SetSize(int size, BOOL clear=TRUE);
|
||||
Point3 operator[](int i);
|
||||
void Set(TimeValue t,int i, Point3& p);
|
||||
void Move(TimeValue t,int i, const Point3& p);
|
||||
void Apply(TimeValue t,Mesh& mesh);
|
||||
void Scale(float f);
|
||||
VertexDelta& operator=(VertexDelta& from);
|
||||
|
||||
~VertexDelta();
|
||||
VertexDelta();
|
||||
};
|
||||
|
||||
|
||||
class TopoOp {
|
||||
public:
|
||||
virtual void Apply(Mesh& mesh)=0;
|
||||
virtual TopoOp *Clone()=0;
|
||||
virtual ~TopoOp() {}
|
||||
};
|
||||
|
||||
typedef Tab<TopoOp*> TopoOpTab;
|
||||
|
||||
class FaceMap {
|
||||
public:
|
||||
DWORD v[3];
|
||||
};
|
||||
typedef Tab<FaceMap> FaceMapTab;
|
||||
|
||||
|
||||
// Bits for attribs:
|
||||
// First 3 bits are edge visibility
|
||||
// 4th bit is face visibility
|
||||
// 29,30 and 31 indicate which if any should be applied
|
||||
#define ATTRIB_APPLY_EDGE (1<<31)
|
||||
#define ATTRIB_APPLY_FACE (1<<30)
|
||||
#define ATTRIB_APPLY_MATID (1<<29)
|
||||
#define ATTRIB_APPLY_SMGROUP (1<<28)
|
||||
|
||||
// Mat ID takes bit 5-21
|
||||
#define ATTRIB_MATID_SHIFT 5
|
||||
#define ATTRIB_MATID_MASK 0xffff
|
||||
|
||||
|
||||
class TopoDelta {
|
||||
public:
|
||||
DWORDTab cverts; // Clone verts
|
||||
DWORDTab dverts; // Delete verts
|
||||
Point3Tab nverts; // Add verts
|
||||
Point3Tab nTverts; // Add texture verts
|
||||
DWORDTab dfaces; // Delete faces
|
||||
Tab<Face> nfaces; // New faces
|
||||
Tab<TVFace> nTVfaces; // New texture vert faces
|
||||
FaceMapTab map; // Remap faces
|
||||
FaceMapTab tmap; // TVFace remap
|
||||
DWORDTab attribs; // Changes attributes of a face.
|
||||
DWORDTab smgroups; // Changes smooth groups for a face.
|
||||
DWORD inputFaces; // Number of faces on input mesh
|
||||
DWORD inputVerts; // Number of vertices input mesh has
|
||||
|
||||
};
|
||||
|
||||
class EditMeshData : public LocalModData {
|
||||
public:
|
||||
DWORD flags;
|
||||
|
||||
// These record the changes to the incomming object.
|
||||
VertexDelta vdelta;
|
||||
TopoDelta tdelta;
|
||||
|
||||
// The selection sets.
|
||||
BitArray vsel;
|
||||
BitArray fsel;
|
||||
BitArray esel;
|
||||
|
||||
// Lists of named selection sets
|
||||
NamedSelSetList vselSet;
|
||||
NamedSelSetList fselSet;
|
||||
NamedSelSetList eselSet;
|
||||
|
||||
// While an object is being edited, this exists.
|
||||
// EMTempData *tempData;
|
||||
};
|
||||
|
||||
inline float BPoly4(int i, float u)
|
||||
{
|
||||
float s = 1.0f-u;
|
||||
switch (i) {
|
||||
case 0: return s*s*s;
|
||||
case 1: return 3.0f*u*s*s;
|
||||
case 2: return 3.0f*u*u*s;
|
||||
case 3: return u*u*u;
|
||||
default: return 0.0f;
|
||||
}
|
||||
}
|
||||
inline float BPoly3(int i, float u)
|
||||
{
|
||||
float s = 1.0f-u;
|
||||
switch (i) {
|
||||
case 0: return s*s;
|
||||
case 1: return 2.0f*u*s;
|
||||
case 2: return u*u;
|
||||
default: return 0.0f;
|
||||
}
|
||||
}
|
||||
inline float BPoly2(int i, float u)
|
||||
{
|
||||
switch (i) {
|
||||
case 0: return 1.0f-u;
|
||||
case 1: return u;
|
||||
default: return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
#define EPSILON 0.001f
|
||||
|
||||
|
||||
Point3 FfdLatticeSize(Box3 box)
|
||||
{
|
||||
Point3 size = box.Max()-box.Min();
|
||||
if (size.x==0.0f) size.x = 0.001f;
|
||||
if (size.y==0.0f) size.y = 0.001f;
|
||||
if (size.z==0.0f) size.z = 0.001f;
|
||||
return size;
|
||||
}
|
||||
|
||||
Matrix3 FFDMod::CompTM(TimeValue t,INode *inode,ModContext *mc)
|
||||
{
|
||||
// Compute a the transformation out of lattice space into world space
|
||||
Matrix3 ntm = inode->GetObjTMBeforeWSM(t);
|
||||
Matrix3 ctm(1);
|
||||
if (mc && mc->tm) {
|
||||
ntm = Inverse(*(mc->tm)) * ntm;
|
||||
}
|
||||
tmControl->GetValue(t,&ctm,FOREVER,CTRL_RELATIVE);
|
||||
return ctm * ntm;
|
||||
}
|
||||
|
||||
Box3 ComputeBBox(TimeValue t, INode *node) {
|
||||
Box3 box; // The computed box
|
||||
Matrix3 mat; // The Object TM
|
||||
Matrix3 sclMat(1); // This will be used to apply the scaling
|
||||
// Get the result of the pipeline at the current time
|
||||
Object *obj = node->EvalWorldState(t).obj;
|
||||
// Determine if the object is in world space or object space
|
||||
// so we can get the correct TM. We can check this by getting
|
||||
|
||||
if (node->GetObjTMAfterWSM(t).IsIdentity()) {
|
||||
mat = Inverse(node->GetObjTMBeforeWSM(t));
|
||||
|
||||
} else {
|
||||
// It's in object space, get the Object TM.
|
||||
mat = node->GetObjectTM(t);
|
||||
}
|
||||
// Extract just the scaling part from the TM
|
||||
AffineParts parts;
|
||||
decomp_affine(mat, &parts);
|
||||
//ApplyScaling(sclMat, ScaleValue(parts.k*parts.f, parts.u));
|
||||
// Get the bound box, and affect it by just
|
||||
// the scaling portion
|
||||
obj->GetDeformBBox(t, box, &sclMat);
|
||||
return box;
|
||||
}
|
||||
|
||||
void AsciiExp::ExportFFD( INode* node , FFDMod *FfdMod, ModContext *mc, Mesh *mesh)
|
||||
{
|
||||
TimeValue start = ip->GetAnimRange().Start();
|
||||
TimeValue end = ip->GetAnimRange().End();
|
||||
int delta = GetTicksPerFrame();
|
||||
int nbCtrlPnts;
|
||||
TimeValue t;
|
||||
int i;
|
||||
int Depth;
|
||||
int Width;
|
||||
int Height;
|
||||
|
||||
if (node->IsNodeHidden())
|
||||
return;
|
||||
|
||||
if (FfdMod) {
|
||||
|
||||
ObjectState os;
|
||||
Object * obj;
|
||||
|
||||
os = node->EvalWorldState( 0 );
|
||||
obj = node->GetObjectRef();
|
||||
while (obj && obj->SuperClassID() == GEN_DERIVOB_CLASS_ID) {
|
||||
obj = ((IDerivedObject*)obj)->GetObjRef();
|
||||
}
|
||||
|
||||
if (!obj) return;
|
||||
|
||||
if (FfdMod->ClassID() == FFD44_CLASS_ID) {
|
||||
Depth = Width = Height = 4;
|
||||
} else
|
||||
if (FfdMod->ClassID() == FFD33_CLASS_ID) {
|
||||
Depth = Width = Height = 3;
|
||||
} else
|
||||
if (FfdMod->ClassID() == FFD22_CLASS_ID) {
|
||||
Depth = Width = Height = 2;
|
||||
}
|
||||
|
||||
// Evaluate the TM controller
|
||||
Matrix3 ctm(1);
|
||||
FfdMod->tmControl->GetValue(start,&ctm,FOREVER,CTRL_RELATIVE);
|
||||
|
||||
// Get the ModContext TM (if there is one)
|
||||
Matrix3 tm = mc->tm ? *mc->tm : Matrix3(1);
|
||||
|
||||
// Apply our TM to the MC TM
|
||||
tm *= Inverse(ctm);
|
||||
|
||||
// The origin of the TM is the lower left corner of the
|
||||
// box, not the center.
|
||||
tm.SetTrans(tm.GetTrans()-mc->box->Min());
|
||||
|
||||
// Compute scale factors to normalize lattice space
|
||||
// to the extents of the box.
|
||||
Point3 s = FfdLatticeSize(*mc->box);
|
||||
|
||||
for (i=0; i<3; i++) {
|
||||
if (s[i]==0.0f) s[i] = 1.0f;
|
||||
else s[i] = 1.0f/s[i];
|
||||
}
|
||||
tm.Scale(s,TRUE);
|
||||
|
||||
Matrix3 itm = Inverse(tm);
|
||||
|
||||
AffineParts ap;
|
||||
decomp_affine(tm, &ap);
|
||||
|
||||
nbCtrlPnts = FfdMod->NumCtrlPts();
|
||||
WriteChunkHdr( (char*)FFD_ID, 0);
|
||||
fwrite( &nCurObj, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &FfdNum, sizeof(Uint32), 1, expStream);
|
||||
fwrite( &Width, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &Height, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &Depth, sizeof( Uint32 ), 1, expStream );
|
||||
|
||||
MRow *mr = tm.GetAddr();
|
||||
|
||||
fwrite( &mr[0][0], sizeof(MRow),1,expStream);
|
||||
fwrite( &mr[1][0], sizeof(MRow),1,expStream);
|
||||
fwrite( &mr[2][0], sizeof(MRow),1,expStream);
|
||||
fwrite( &mr[3][0], sizeof(MRow),1,expStream);
|
||||
|
||||
int dd,dw,dh;
|
||||
int nv = obj->NumPoints();
|
||||
|
||||
/* for (i=0; i<nv; i++) {
|
||||
float tw = 0.f;
|
||||
for (dw = 0; dw<Width; dw++) {
|
||||
for (dd = 0; dd<Depth; dd++) {
|
||||
for (dh = 0; dh<Height; dh++) {
|
||||
float w;
|
||||
Point3 pp = tm*obj->GetPoint(i);
|
||||
if (pp.x>=-0.001f && pp.x<=1.001f && pp.y>=-0.001f && pp.y<=1.001f && pp.z>=-0.001f && pp.z<=1.001f) {
|
||||
if (FfdMod->ClassID() == FFD44_CLASS_ID) {
|
||||
w = BPoly4(dw,pp.x) * BPoly4(dd,pp.y) * BPoly4(dh,pp.z);
|
||||
} else
|
||||
if (FfdMod->ClassID() == FFD33_CLASS_ID) {
|
||||
w = BPoly3(dw,pp.x) * BPoly3(dd,pp.y) * BPoly3(dh,pp.z);
|
||||
} else
|
||||
if (FfdMod->ClassID() == FFD22_CLASS_ID) {
|
||||
w = BPoly2(dw,pp.x) * BPoly2(dd,pp.y) * BPoly2(dh,pp.z);
|
||||
}
|
||||
} else {
|
||||
w = 0;
|
||||
}
|
||||
tw+=w;
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
fprintf( tempStream, "node = %s\n\n", node->GetName() );
|
||||
fprintf( tempStream, "selected = ");
|
||||
BitArray Selection = mesh->VertexTempSel();
|
||||
for (dw = 0; dw<Width; dw++) {
|
||||
for (dd = 0; dd<Depth; dd++) {
|
||||
for (dh = 0; dh<Height; dh++) {
|
||||
for (i=0; i<nv; i++) {
|
||||
float w;
|
||||
Point3 pp = tm*obj->GetPoint(i);
|
||||
//if (pp.x>=-0.0001f && pp.x<=1.0001f && pp.y>=-0.0001f && pp.y<=1.0001f && pp.z>=-0.0001f && pp.z<=1.0001f) {
|
||||
if (Selection[i])
|
||||
{
|
||||
if (FfdMod->ClassID() == FFD44_CLASS_ID) {
|
||||
w = BPoly4(dw,pp.x) * BPoly4(dd,pp.y) * BPoly4(dh,pp.z);
|
||||
} else
|
||||
if (FfdMod->ClassID() == FFD33_CLASS_ID) {
|
||||
w = BPoly3(dw,pp.x) * BPoly3(dd,pp.y) * BPoly3(dh,pp.z);
|
||||
} else
|
||||
if (FfdMod->ClassID() == FFD22_CLASS_ID) {
|
||||
w = BPoly2(dw,pp.x) * BPoly2(dd,pp.y) * BPoly2(dh,pp.z);
|
||||
}
|
||||
fprintf( tempStream, "%d %f, ", i, w);
|
||||
} else {
|
||||
w = 0;
|
||||
}
|
||||
fwrite(&w, sizeof(float), 1, expStream);
|
||||
}
|
||||
fprintf( tempStream, "\nendselected\n");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WriteChunkHdr( (char*)ANIM_ID, 0);
|
||||
fwrite( &CHANNEL_TYPE_FFD, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &nCurObj, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &totFrames, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &FfdNum, sizeof(Uint32), 1, expStream);
|
||||
fwrite( &Width, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &Height, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &Depth, sizeof( Uint32 ), 1, expStream );
|
||||
for (i=0; i<nbCtrlPnts; i++) {
|
||||
for (t=start; t<=end; t+=delta) {
|
||||
|
||||
Matrix3 ntm = node->GetObjTMBeforeWSM(t);
|
||||
Matrix3 ctm(1);
|
||||
if (mc && mc->tm) {
|
||||
ntm = Inverse(*(mc->tm)) * ntm;
|
||||
}
|
||||
FfdMod->tmControl->GetValue(t,&ctm,FOREVER,CTRL_RELATIVE);
|
||||
Matrix3 mm = ctm * ntm;
|
||||
Box3 lbox = *mc->box;
|
||||
Matrix3 stm = ScaleMatrix(FfdLatticeSize(lbox));
|
||||
stm.SetTrans(lbox.Min());
|
||||
|
||||
Point3 np = FfdMod->GetControlPoint(t,i);
|
||||
Point3 p = stm*FfdMod->GetControlPoint(t, i);
|
||||
Point3 p2 = mm * p;
|
||||
fwrite(&p2.x, sizeof(float), 1, expStream);
|
||||
fwrite(&p2.z, sizeof(float), 1, expStream);
|
||||
fwrite(&p2.y, sizeof(float), 1, expStream);
|
||||
}
|
||||
}
|
||||
|
||||
TimeValue start = ip->GetAnimRange().Start();
|
||||
TimeValue end = ip->GetAnimRange().End();
|
||||
int delta = GetTicksPerFrame();
|
||||
Control *c;
|
||||
WriteChunkHdr( (char*)KEY_ID, 0);
|
||||
fwrite( &CHANNEL_TYPE_FFD, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &CHANNEL_INFO_ALL, sizeof( Uint32) , 1, expStream);
|
||||
fwrite( &nCurObj, sizeof( Uint32), 1, expStream );
|
||||
fwrite( &FfdNum, sizeof(Uint32), 1, expStream);
|
||||
fwrite( &nbCtrlPnts, sizeof( Uint32), 1, expStream );
|
||||
for (i=0; i<nbCtrlPnts; i++) {
|
||||
TimeList tl;
|
||||
IKeyControl *ikeys;
|
||||
ITCBPoint3Key tcbPosKey;
|
||||
ITCBRotKey tcbRotKey;
|
||||
ITCBScaleKey tcbSclKey;
|
||||
IBezPoint3Key bezPosKey;
|
||||
IBezQuatKey bezRotKey;
|
||||
IBezScaleKey bezSclKey;
|
||||
ILinPoint3Key linPosKey;
|
||||
ILinRotKey linRotKey;
|
||||
ILinScaleKey linSclKey;
|
||||
int num;
|
||||
TimeValue time;
|
||||
tl.Clear();
|
||||
|
||||
c = FfdMod->GetPtCont(i);
|
||||
if (c) {
|
||||
ikeys = GetKeyControlInterface(c);
|
||||
int blah = c->IsKeyable();
|
||||
if (ikeys) {
|
||||
num = ikeys->GetNumKeys();
|
||||
if (num >0)
|
||||
{
|
||||
for (int j = 0; j<num; j++) {
|
||||
if (c->ClassID() == Class_ID(TCBINTERP_POINT3_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(j, &tcbPosKey);
|
||||
time = tcbPosKey.time;
|
||||
} else
|
||||
if (c->ClassID() == Class_ID(HYBRIDINTERP_POINT3_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(j, &bezPosKey);
|
||||
time = bezPosKey.time;
|
||||
}
|
||||
tl.Add(time);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!tl.Count()) {
|
||||
tl.Add(ip->GetAnimRange().Start());
|
||||
}
|
||||
num = tl.Count();
|
||||
|
||||
fwrite(&num, sizeof(int), 1, expStream);
|
||||
for ( int j = 0; j<num; j++) {
|
||||
time = tl.Get(j);
|
||||
|
||||
Matrix3 ntm = node->GetObjTMBeforeWSM(time);
|
||||
Matrix3 ctm(1);
|
||||
if (mc && mc->tm) {
|
||||
ntm = Inverse(*(mc->tm)) * ntm;
|
||||
}
|
||||
FfdMod->tmControl->GetValue(time,&ctm,FOREVER,CTRL_RELATIVE);
|
||||
Matrix3 mm = ctm * ntm;
|
||||
Box3 lbox = *mc->box;
|
||||
Matrix3 stm = ScaleMatrix(FfdLatticeSize(lbox));
|
||||
stm.SetTrans(lbox.Min());
|
||||
|
||||
Point3 np = FfdMod->GetControlPoint(time,i);
|
||||
Point3 p = stm*FfdMod->GetControlPoint(time, i);
|
||||
Point3 p2 = mm * p;
|
||||
|
||||
time = (time - start)/delta;
|
||||
fwrite(&time, sizeof(int), 1, expStream);
|
||||
fwrite(&p2.x, sizeof(float), 1, expStream);
|
||||
fwrite(&p2.z, sizeof(float), 1, expStream);
|
||||
fwrite(&p2.y, sizeof(float), 1, expStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AsciiExp::FindFFDModifier (INode* node)
|
||||
{
|
||||
// Get object from node. Abort if no object.
|
||||
Object* ObjectPtr = node->GetObjectRef();
|
||||
FfdNum = 0;
|
||||
bool Found= false;
|
||||
|
||||
if (!ObjectPtr)
|
||||
return false;
|
||||
|
||||
// Is derived object ?
|
||||
|
||||
int needDel;
|
||||
|
||||
while (ObjectPtr->SuperClassID() == GEN_DERIVOB_CLASS_ID)
|
||||
{
|
||||
IDerivedObject* DerivedObjectPtr = static_cast<IDerivedObject*>(ObjectPtr);
|
||||
ObjectPtr = DerivedObjectPtr->GetObjRef();
|
||||
}
|
||||
TriObject * tri = GetTriObjectFromObject(ObjectPtr, ip->GetAnimRange().Start(), needDel);
|
||||
if (!tri) return false;
|
||||
|
||||
Mesh* mesh = &tri->mesh;
|
||||
|
||||
BitArray SaveVtx = mesh->vertSel;
|
||||
BitArray SaveFce = mesh->faceSel;
|
||||
BitArray SaveEdg = mesh->edgeSel;
|
||||
|
||||
ObjectPtr = node->GetObjectRef();
|
||||
while (ObjectPtr->SuperClassID() == GEN_DERIVOB_CLASS_ID)
|
||||
{
|
||||
// Yes -> Cast.
|
||||
IDerivedObject* DerivedObjectPtr = static_cast<IDerivedObject*>(ObjectPtr);
|
||||
|
||||
// Iterate over all entries of the modifier stack.
|
||||
int ModStackIndex = DerivedObjectPtr->NumModifiers() - 1;
|
||||
while (ModStackIndex >= 0 )
|
||||
{
|
||||
// Get current modifier.
|
||||
Modifier* ModifierPtr = DerivedObjectPtr->GetModifier(ModStackIndex);
|
||||
ModContext *modContext = DerivedObjectPtr->GetModContext(ModStackIndex);
|
||||
// Is this FFD ?
|
||||
if (ModifierPtr->ClassID() == FFD44_CLASS_ID ||
|
||||
ModifierPtr->ClassID() == FFD33_CLASS_ID ||
|
||||
ModifierPtr->ClassID() == FFD22_CLASS_ID)
|
||||
{
|
||||
// Yes -> Exit.
|
||||
ExportFFD(node, (FFDMod*)ModifierPtr, modContext, mesh);
|
||||
FfdNum++;
|
||||
Found = true;
|
||||
} else
|
||||
if (ModifierPtr->ClassID() == Class_ID(EDITMESH_CLASS_ID,0))
|
||||
{
|
||||
EditMeshData *meshData = (EditMeshData*)modContext->localData;
|
||||
mesh->vertSel = meshData->vsel;
|
||||
mesh->faceSel = meshData->fsel;
|
||||
mesh->edgeSel = meshData->esel;
|
||||
}
|
||||
|
||||
// Next modifier stack entry.
|
||||
ModStackIndex--;
|
||||
|
||||
|
||||
}
|
||||
ObjectPtr = DerivedObjectPtr->GetObjRef();
|
||||
}
|
||||
|
||||
mesh->vertSel = SaveVtx;
|
||||
mesh->faceSel = SaveFce;
|
||||
mesh->edgeSel = SaveEdg;
|
||||
|
||||
if (needDel) delete tri;
|
||||
|
||||
return Found;
|
||||
}
|
||||
|
262
Utils/GinExp/ExpFileIo.cpp
Normal file
262
Utils/GinExp/ExpFileIo.cpp
Normal file
|
@ -0,0 +1,262 @@
|
|||
/*=========================================================================
|
||||
|
||||
FILEIO.CPP
|
||||
|
||||
Author: Tim Swann @ CLIMAX
|
||||
Created:
|
||||
Project:
|
||||
Purpose:
|
||||
|
||||
Copyright (c) 1998 Climax Development Ltd
|
||||
|
||||
===========================================================================*/
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Includes
|
||||
-------- */
|
||||
|
||||
#include "AsciiExp.h"
|
||||
#include "ExpFileIO.h"
|
||||
|
||||
|
||||
/* Std Lib
|
||||
------- */
|
||||
|
||||
/* Glib
|
||||
---- */
|
||||
|
||||
/* Local
|
||||
----- */
|
||||
|
||||
/* Graphics
|
||||
-------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Tyepdefs && Defines
|
||||
------------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Structure defintions
|
||||
-------------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Positional Vars
|
||||
--------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function Prototypes
|
||||
------------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Vars
|
||||
---- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Data
|
||||
---- */
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
void FIO_Stripfileinfo(char * Name, char * fname, char * ext, char * dir, char * drive)
|
||||
{
|
||||
char tdrive[_MAX_DRIVE];
|
||||
char tdir[_MAX_DIR];
|
||||
char tfname[_MAX_FNAME];
|
||||
char text[_MAX_EXT];
|
||||
|
||||
|
||||
_splitpath(Name, tdrive, tdir, tfname, text);
|
||||
|
||||
if (fname)
|
||||
strcpy(fname, tfname);
|
||||
|
||||
if (ext)
|
||||
strcpy(ext, text);
|
||||
|
||||
if (dir)
|
||||
strcpy(dir, tdir);
|
||||
|
||||
if (drive)
|
||||
strcpy(drive, tdrive);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
bool FIO_FileExists(const char * Name)
|
||||
{
|
||||
int hFile;
|
||||
|
||||
/* Open input file */
|
||||
hFile = _open(Name, _O_RDONLY | _O_BINARY);
|
||||
|
||||
if(hFile != -1)
|
||||
{
|
||||
_close(hFile); // file close
|
||||
return(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
void * FIO_Read(char const * Name, int Offset)
|
||||
{
|
||||
int hFile;
|
||||
long filelen;
|
||||
void * pAddr;
|
||||
long pos;
|
||||
|
||||
|
||||
/* Open input file */
|
||||
hFile = _open(Name, _O_RDONLY | _O_BINARY);
|
||||
|
||||
if(hFile != -1)
|
||||
{
|
||||
filelen = FIO_FileLen(Name); // length of file
|
||||
pAddr = malloc(filelen); // allocate mainmemory
|
||||
|
||||
pos = _lseek( hFile, Offset, SEEK_SET );
|
||||
if( pos == -1 ) assert(!"File seek");
|
||||
filelen -= pos;
|
||||
|
||||
_read(hFile, pAddr, filelen); // read in file
|
||||
_close(hFile); // file close
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
return pAddr;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
bool FIO_ReadAtAddr(char const * Name, unsigned char * Dest, int Len, int Offset)
|
||||
{
|
||||
int hFile;
|
||||
long filelen;
|
||||
long pos;
|
||||
|
||||
|
||||
/* Open input file */
|
||||
hFile = _open(Name, _O_RDONLY | _O_BINARY);
|
||||
|
||||
if(hFile != -1)
|
||||
{
|
||||
filelen = FIO_FileLen(Name); // length of file
|
||||
|
||||
if (Len && (Len < filelen)) filelen = Len;
|
||||
|
||||
pos = _lseek( hFile, Offset, SEEK_SET );
|
||||
if( pos == -1 ) assert(!"File seek");
|
||||
|
||||
_read(hFile, Dest, filelen); // read in file
|
||||
_close(hFile); // file close
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
int FIO_FileLen(const char * Name)
|
||||
{
|
||||
int hFile;
|
||||
int filelen = 0;
|
||||
|
||||
|
||||
/* Open input file */
|
||||
hFile = _open(Name, _O_RDONLY | _O_BINARY);
|
||||
|
||||
if(hFile != -1)
|
||||
{
|
||||
filelen = _filelength(hFile); // length of file
|
||||
_close(hFile); // file close
|
||||
}
|
||||
return filelen;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
bool FIO_Save(const char * Name,unsigned char * Addr,int Len)
|
||||
{
|
||||
HANDLE hFile;
|
||||
UINT fResult;
|
||||
DWORD nWrited;
|
||||
|
||||
|
||||
/* Open output file */
|
||||
hFile = CreateFile( Name, /* output filename */
|
||||
GENERIC_WRITE, /* mode = write */
|
||||
0, /* share mode = not share */
|
||||
NULL, /* security attribute = cancel */
|
||||
CREATE_ALWAYS, /* create file always */
|
||||
FILE_ATTRIBUTE_NORMAL, /* file attribute = normal */
|
||||
NULL /* template file = non */
|
||||
);
|
||||
if(hFile)
|
||||
{
|
||||
fResult = WriteFile(hFile, /* IN : file handle */
|
||||
Addr, /* IN : pointer to write data */
|
||||
(DWORD)Len, /* IN : number of data in bytes */
|
||||
&nWrited, /* OUT : number of data just writed */
|
||||
NULL /* IN : pointer to OVERLAPPED structure */
|
||||
);
|
||||
CloseHandle(hFile); /* close file */
|
||||
|
||||
if(fResult == FALSE)
|
||||
assert(!("SaveFile: ERROR Can not write file %s",Name));
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================
|
||||
end */
|
63
Utils/GinExp/ExpFileIo.h
Normal file
63
Utils/GinExp/ExpFileIo.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*=========================================================================
|
||||
|
||||
FILEIO.H
|
||||
|
||||
Author: Tim Swann @ CLIMAX
|
||||
Created:
|
||||
Project:
|
||||
Purpose:
|
||||
|
||||
Copyright (c) 1998 Climax Development Ltd
|
||||
|
||||
===========================================================================*/
|
||||
|
||||
#ifndef __FILEIO__
|
||||
#define __FILEIO__
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Includes
|
||||
-------- */
|
||||
|
||||
/* Std Lib
|
||||
------- */
|
||||
|
||||
/* Glib
|
||||
---- */
|
||||
|
||||
/* Local
|
||||
----- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Tyepdefs && Defines
|
||||
------------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Structure defintions
|
||||
-------------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Globals
|
||||
------- */
|
||||
|
||||
/* Vars
|
||||
---- */
|
||||
|
||||
/* Data
|
||||
---- */
|
||||
|
||||
/* Functions
|
||||
--------- */
|
||||
|
||||
void * FIO_Read(char const * Name, int Offset = 0);
|
||||
bool FIO_ReadAtAddr(char const * Name,unsigned char * Dest,int Len = 0, int Offset = 0);
|
||||
int FIO_FileLen(const char * Name);
|
||||
bool FIO_FileExists(const char * Name);
|
||||
bool FIO_Save(const char * Name,unsigned char * Addr,int Len);
|
||||
void FIO_Stripfileinfo(char * Name, char * fname = NULL, char * ext = NULL, char * dir = NULL, char * drive = NULL);
|
||||
|
||||
/*---------------------------------------------------------------------- */
|
||||
|
||||
#endif /* __FILEIO__ */
|
||||
|
||||
/*===========================================================================
|
||||
end */
|
741
Utils/GinExp/ExpMain.cpp
Normal file
741
Utils/GinExp/ExpMain.cpp
Normal file
|
@ -0,0 +1,741 @@
|
|||
/*=========================================================================
|
||||
|
||||
EXPMAIN.CPP
|
||||
|
||||
Author: Tim Swann @ CLIMAX
|
||||
Created:
|
||||
Project:
|
||||
Purpose:
|
||||
|
||||
Copyright (c) 1998 Climax Development Ltd
|
||||
|
||||
===========================================================================*/
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Includes
|
||||
-------- */
|
||||
|
||||
#include "Asciiexp.h"
|
||||
#include "ExpFileIO.h"
|
||||
|
||||
|
||||
/* Std Lib
|
||||
------- */
|
||||
|
||||
/* Glib
|
||||
---- */
|
||||
|
||||
/* Local
|
||||
----- */
|
||||
|
||||
/* Graphics
|
||||
-------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Tyepdefs && Defines
|
||||
------------------- */
|
||||
|
||||
#define NINJAEXP_CLASS_ID Class_ID(0x689c7996, 0x13531d0d)
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Structure defintions
|
||||
-------------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Positional Vars
|
||||
--------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function Prototypes
|
||||
------------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Vars
|
||||
---- */
|
||||
|
||||
static HINSTANCE hInstance;
|
||||
static AsciiExpClassDesc AsciiExpDesc;
|
||||
static bool controlsInit = FALSE;
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Data
|
||||
---- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL,ULONG fdwReason,LPVOID lpvReserved)
|
||||
{
|
||||
hInstance = hinstDLL;
|
||||
|
||||
// Initialize the custom controls. This should be done only once.
|
||||
if (!controlsInit)
|
||||
{
|
||||
controlsInit = TRUE;
|
||||
InitCustomControls(hInstance);
|
||||
InitCommonControls();
|
||||
}
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
__declspec( dllexport ) const TCHAR* LibDescription()
|
||||
{
|
||||
return GetString(IDS_LIBDESCRIPTION);
|
||||
}
|
||||
|
||||
|
||||
__declspec( dllexport ) int LibNumberClasses()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
__declspec( dllexport ) ClassDesc* LibClassDesc(int i)
|
||||
{
|
||||
switch(i) {
|
||||
case 0: return GetAsciiExpDesc();
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
__declspec( dllexport ) ULONG LibVersion()
|
||||
{
|
||||
return VERSION_3DSMAX;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
ClassDesc * GetAsciiExpDesc(void)
|
||||
{
|
||||
return &AsciiExpDesc;
|
||||
}
|
||||
|
||||
|
||||
TCHAR * GetString(int id)
|
||||
{
|
||||
static TCHAR buf[256];
|
||||
|
||||
if (hInstance)
|
||||
return LoadString(hInstance, id, buf, sizeof(buf)) ? buf : NULL;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
AsciiExp::AsciiExp()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
AsciiExp::~AsciiExp()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int AsciiExp::ExtCount()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
const TCHAR * AsciiExp::Ext(int n)
|
||||
{
|
||||
switch(n)
|
||||
{
|
||||
case 0:
|
||||
return _T("GIN");
|
||||
}
|
||||
return _T("");
|
||||
}
|
||||
|
||||
|
||||
const TCHAR * AsciiExp::LongDesc()
|
||||
{
|
||||
return GetString(IDS_LONGDESC);
|
||||
}
|
||||
|
||||
|
||||
const TCHAR * AsciiExp::ShortDesc()
|
||||
{
|
||||
return GetString(IDS_SHORTDESC);
|
||||
}
|
||||
|
||||
|
||||
const TCHAR * AsciiExp::AuthorName()
|
||||
{
|
||||
return _T("Tim Swann / Mike Armstrong");
|
||||
}
|
||||
|
||||
|
||||
const TCHAR * AsciiExp::CopyrightMessage()
|
||||
{
|
||||
return GetString(IDS_COPYRIGHT);
|
||||
}
|
||||
|
||||
|
||||
const TCHAR * AsciiExp::OtherMessage1()
|
||||
{
|
||||
return _T("");
|
||||
}
|
||||
|
||||
|
||||
const TCHAR * AsciiExp::OtherMessage2()
|
||||
{
|
||||
return _T("");
|
||||
}
|
||||
|
||||
|
||||
unsigned int AsciiExp::Version()
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
|
||||
|
||||
static BOOL CALLBACK AboutBoxDlgProc(HWND hWnd, UINT msg,
|
||||
WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (msg) {
|
||||
case WM_INITDIALOG:
|
||||
CenterWindow(hWnd, GetParent(hWnd));
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
switch (LOWORD(wParam)) {
|
||||
case IDOK:
|
||||
EndDialog(hWnd, 1);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
void AsciiExp::ShowAbout(HWND hWnd)
|
||||
{
|
||||
// DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, AboutBoxDlgProc, 0);
|
||||
}
|
||||
|
||||
|
||||
static BOOL CALLBACK ExportDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
AsciiExp * exp = (AsciiExp*)GetWindowLong(hWnd, GWL_USERDATA);
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
exp = (AsciiExp*)lParam;
|
||||
SetWindowLong(hWnd,GWL_USERDATA,lParam);
|
||||
CenterWindow(hWnd, GetParent(hWnd));
|
||||
// CheckDlgButton(hWnd, IDC_ANIMCHECK, exp->GetExportAnimFlag());
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
case IDOK:
|
||||
// exp->SetExportAnimFlag(IsDlgButtonChecked(hWnd, IDC_ANIMCHECK));
|
||||
EndDialog(hWnd, 1);
|
||||
break;
|
||||
|
||||
case IDCANCEL:
|
||||
EndDialog(hWnd, 0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
// Dummy function for progress bar
|
||||
DWORD WINAPI fn(LPVOID arg)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
#if MAX_RELEASE == 2500
|
||||
int AsciiExp::DoExport(const TCHAR * name, ExpInterface * ei, Interface * i, BOOL suppressPrompts)
|
||||
#else
|
||||
int AsciiExp::DoExport(const TCHAR * name, ExpInterface * ei, Interface * i, BOOL suppressPrompts,DWORD options)
|
||||
#endif
|
||||
{
|
||||
int numChildren;
|
||||
// NodeCount = 0;
|
||||
|
||||
|
||||
// GRAB THE INTERFACE POINTER
|
||||
ip = i;
|
||||
MAX_hWnd = ip->GetMAXHWnd();
|
||||
// SetExportAnimFlag(0);
|
||||
// if (!suppressPrompts && !DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_ASCIIEXPORT_DLG), MAX_hWnd, ExportDlgProc, (LPARAM)this)) return 1;
|
||||
|
||||
tempStream = NULL;
|
||||
expStream = NULL;
|
||||
nbChunks = 0;
|
||||
|
||||
|
||||
// GET SCENE FILENAME
|
||||
sprintf( SceneName, "%s", FixupName(ip->GetCurFileName()) );
|
||||
_strupr( SceneName );
|
||||
|
||||
|
||||
// OPEN DEBUG TEXT FILE
|
||||
tempStream = _tfopen("C:\\ExpDebug.txt",_T("wt"));
|
||||
if (!tempStream) return 0;
|
||||
|
||||
fprintf( tempStream, "TEST\n" );
|
||||
|
||||
// OPEN OUTPUT FILE
|
||||
_splitpath(name, drive, dir, fname, ext);
|
||||
sprintf(filename, "%s%s%s.GIN", drive, dir, fname);
|
||||
_strlwr(filename);
|
||||
expStream = _tfopen(filename, _T("wb"));
|
||||
if (!expStream) return 0;
|
||||
|
||||
// WRITE FILE HEADER
|
||||
if (WriteChunkHdr( (char*)FILE_ID, 0 ))
|
||||
{
|
||||
// STARTUP THE PROGRESS BAR
|
||||
// if (GetExportAnimFlag())
|
||||
// ip->ProgressStart("Exporting with Anims", TRUE, fn, NULL);
|
||||
// else
|
||||
ip->ProgressStart("Exporting without Vertex Anims", TRUE, fn, NULL);
|
||||
|
||||
|
||||
Weights = NULL;
|
||||
nTotalNodeCount = 0;
|
||||
nCurNode = 0;
|
||||
nCurObj = 0;
|
||||
nbFrames = 0;
|
||||
totFrames = 0;
|
||||
nbWeights = 0;
|
||||
NbEmmitters = 0;
|
||||
|
||||
GetNoFrames();
|
||||
fwrite(&totFrames, sizeof(int), 1, expStream);
|
||||
|
||||
WriteChunkHdr( (char*)VERSION_ID, 0);
|
||||
int MyVer = VERSION;
|
||||
fwrite(&MyVer, sizeof(int), 1, expStream);
|
||||
|
||||
OrigProcess(ip->GetRootNode());
|
||||
FfdProcess(ip->GetRootNode(), nTotalNodeCount);
|
||||
|
||||
ExportTree();
|
||||
|
||||
numChildren = ip->GetRootNode()->NumberOfChildren();
|
||||
for (int idx=0; idx<numChildren; idx++)
|
||||
{
|
||||
if (ip->GetCancel()) break;
|
||||
nodeEnum( ip->GetRootNode()->GetChildNode(idx));
|
||||
}
|
||||
|
||||
ExportMaterialList();
|
||||
}
|
||||
|
||||
// WRITE FILE TERMINATOR HEADER
|
||||
WriteChunkHdr( (char*)TERMINATOR_ID, 0 );
|
||||
|
||||
|
||||
// Close the streams
|
||||
if (tempStream) fclose(tempStream);
|
||||
if (expStream) fclose(expStream);
|
||||
if (Weights) free(Weights);
|
||||
|
||||
// FILL IN CHUNK SIZES
|
||||
CalcChunkSizes();
|
||||
|
||||
// WE'RE DONE. FINISH THE PROGRESS BAR.
|
||||
ip->ProgressEnd();
|
||||
|
||||
/* if (!DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_ENDDIALOG), MAX_hWnd, ExportDlgProc, (LPARAM)this))
|
||||
{
|
||||
return 1;
|
||||
}*/
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
BOOL AsciiExp::nodeEnum(INode* node)
|
||||
{
|
||||
nCurNode++;
|
||||
|
||||
ip->ProgressUpdate((int)((float)nCurNode/nTotalNodeCount*100.0f));
|
||||
|
||||
if (ip->GetCancel()) return FALSE;
|
||||
|
||||
ExportNode(node);
|
||||
|
||||
for (int c = 0; c < node->NumberOfChildren(); c++)
|
||||
{
|
||||
if (!nodeEnum(node->GetChildNode(c))) return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
void AsciiExp::BoneProcess(INode* node, int& nodeCount)
|
||||
{
|
||||
nodeCount++;
|
||||
|
||||
// GET WEIGHTS BEFORE BONES ARE EXPORTED
|
||||
ExportWeights( node );
|
||||
|
||||
for (int c = 0; c < node->NumberOfChildren(); c++)
|
||||
{
|
||||
BoneProcess(node->GetChildNode(c), nodeCount);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AsciiExp::FfdProcess(INode* node, int& nodeCount)
|
||||
{
|
||||
nodeCount++;
|
||||
|
||||
// GET WEIGHTS BEFORE BONES ARE EXPORTED
|
||||
// ExportFFD( node );
|
||||
Control *cont = node->GetTMController();
|
||||
if (cont) {
|
||||
|
||||
if ((cont->ClassID() == BIPSLAVE_CONTROL_CLASS_ID) ||
|
||||
(cont->ClassID() == BIPBODY_CONTROL_CLASS_ID) ||
|
||||
(cont->ClassID() == FOOTPRINT_CLASS_ID))
|
||||
{
|
||||
IBipedExport *BipIface = (IBipedExport *) cont->GetInterface(I_BIPINTERFACE);
|
||||
if (BipIface)
|
||||
{
|
||||
//BipIface->RemoveNonUniformScale(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int c = 0; c < node->NumberOfChildren(); c++)
|
||||
{
|
||||
FfdProcess(node->GetChildNode(c), nodeCount);
|
||||
}
|
||||
}
|
||||
|
||||
void AsciiExp::OrigProcess(INode *node)
|
||||
{
|
||||
char TempName[256];
|
||||
sprintf(TempName, "%s", node->GetName());
|
||||
_strupr(TempName);
|
||||
if (strcmp(TempName, "ORIGIN")==0) {
|
||||
Matrix3 tm = node->GetObjTMAfterWSM( ip->GetAnimRange().Start() );
|
||||
AffineParts ap;
|
||||
decomp_affine(tm, &ap);
|
||||
WriteChunkHdr( (char*)ORIG_ID, 0);
|
||||
fwrite(&ap.t.x, sizeof(float), 1, expStream);
|
||||
fwrite(&ap.t.z, sizeof(float), 1, expStream);
|
||||
fwrite(&ap.t.y, sizeof(float), 1, expStream);
|
||||
}
|
||||
for (int c = 0; c < node->NumberOfChildren(); c++)
|
||||
{
|
||||
OrigProcess(node->GetChildNode(c));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AsciiExp::GetNoFrames( void )
|
||||
{
|
||||
TimeValue start = ip->GetAnimRange().Start();
|
||||
TimeValue end = ip->GetAnimRange().End();
|
||||
TimeValue t;
|
||||
int delta = GetTicksPerFrame();
|
||||
Object * obj = ip->GetRootNode()->EvalWorldState(ip->GetAnimRange().Start()).obj;
|
||||
|
||||
totFrames = 0;
|
||||
for (t=start; t<=end; t+=delta) totFrames++;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
void AsciiExp::ExportNode(INode* node)
|
||||
{
|
||||
ObjectState os = node->EvalWorldState(ip->GetAnimRange().Start());
|
||||
|
||||
OutputDebugString(node->GetName());
|
||||
|
||||
if (os.obj)
|
||||
{
|
||||
switch(os.obj->SuperClassID())
|
||||
{
|
||||
case GEOMOBJECT_CLASS_ID:
|
||||
ip->ProgressStart("Export Model", TRUE, fn, NULL);
|
||||
ExportModel( node );
|
||||
break;
|
||||
case HELPER_CLASS_ID:
|
||||
ip->ProgressStart("Export Helper", TRUE, fn, NULL);
|
||||
break;
|
||||
case CAMERA_CLASS_ID:
|
||||
ip->ProgressStart("Export Camera", TRUE, fn, NULL);
|
||||
ExportCamera( node );
|
||||
break;
|
||||
case LIGHT_CLASS_ID:
|
||||
ip->ProgressStart("Export Light", TRUE, fn, NULL);
|
||||
ExportLight(node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ExportProp(node);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function: Misc Utility functions
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function: Misc Utility functions
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
static Point3 basic_tva[3] =
|
||||
{
|
||||
Point3(0.0,0.0,0.0),Point3(1.0,0.0,0.0),Point3(1.0,1.0,0.0)
|
||||
};
|
||||
|
||||
static Point3 basic_tvb[3] =
|
||||
{
|
||||
Point3(1.0,1.0,0.0),Point3(0.0,1.0,0.0),Point3(0.0,0.0,0.0)
|
||||
};
|
||||
|
||||
static int nextpt[3] = {1,2,0};
|
||||
static int prevpt[3] = {2,0,1};
|
||||
|
||||
|
||||
|
||||
BOOL AsciiExp::TMNegParity(Matrix3 &m)
|
||||
{
|
||||
return (DotProd(CrossProd(m.GetRow(0),m.GetRow(1)),m.GetRow(2))<0.0)?1:0;
|
||||
}
|
||||
|
||||
|
||||
TriObject * AsciiExp::GetTriObjectFromNode(INode *node, TimeValue t, int &deleteIt)
|
||||
{
|
||||
deleteIt = FALSE;
|
||||
|
||||
Object *obj = node->EvalWorldState(t).obj;
|
||||
|
||||
ObjectState os = obj->Eval(t);
|
||||
obj = os.obj;
|
||||
|
||||
if (obj && obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0)))
|
||||
{
|
||||
TriObject *tri = (TriObject *) obj->ConvertToType(t, Class_ID(TRIOBJ_CLASS_ID, 0));
|
||||
if (obj != tri) deleteIt = TRUE;
|
||||
|
||||
return tri;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
TriObject * AsciiExp::GetTriObjectFromObject(Object *obj, TimeValue t, int &deleteIt)
|
||||
{
|
||||
deleteIt = FALSE;
|
||||
|
||||
if (obj && obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0)))
|
||||
{
|
||||
TriObject *tri = (TriObject *) obj->ConvertToType(t, Class_ID(TRIOBJ_CLASS_ID, 0));
|
||||
if (obj != tri) deleteIt = TRUE;
|
||||
|
||||
return tri;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void AsciiExp::make_face_uv(Face *f, Point3 *tv)
|
||||
{
|
||||
int na,nhid,i;
|
||||
Point3 *basetv;
|
||||
|
||||
/* make the invisible edge be 2->0 */
|
||||
nhid = 2;
|
||||
if (!(f->flags&EDGE_A)) nhid=0;
|
||||
else if (!(f->flags&EDGE_B)) nhid = 1;
|
||||
else if (!(f->flags&EDGE_C)) nhid = 2;
|
||||
na = 2-nhid;
|
||||
basetv = (f->v[prevpt[nhid]]<f->v[nhid]) ? basic_tva : basic_tvb;
|
||||
for (i=0; i<3; i++)
|
||||
{
|
||||
tv[i] = basetv[na];
|
||||
na = nextpt[na];
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
bool AsciiExp::WriteChunkHdr( char* ChunkID, long Size )
|
||||
{
|
||||
|
||||
SizeTab[nbChunks] = ftell( expStream );
|
||||
if (SizeTab[nbChunks] & 0x3) assert(0);
|
||||
//SizeTab[nbChunks] /= 4;
|
||||
|
||||
int sl = strlen(ChunkID) + 1;
|
||||
if (sl&3) {
|
||||
sl += 4 - (sl & 3);
|
||||
}
|
||||
|
||||
fwrite( ChunkID, sl, 1, expStream );
|
||||
fwrite( &Size, sizeof(Uint32), 1, expStream );
|
||||
|
||||
nbChunks++;
|
||||
if(nbChunks >= MAX_FILE_CHUNKS)
|
||||
{
|
||||
MessageBox( MAX_hWnd, "INCREASE MAX_FILE_CHUNKS", "ERROR", MB_OK);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void AsciiExp::CalcChunkSizes( void )
|
||||
{
|
||||
int hFile;
|
||||
long filelen;
|
||||
char * filebuf;
|
||||
|
||||
|
||||
hFile = _open(filename, _O_RDONLY | _O_BINARY);
|
||||
|
||||
if(hFile != -1)
|
||||
{
|
||||
filelen = FIO_FileLen(filename); // length of file
|
||||
filebuf = (char *)malloc(filelen); // allocate mainmemory
|
||||
|
||||
_read(hFile, filebuf, filelen); // read in file
|
||||
_close(hFile); // file close
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
for (int i=0;i<(nbChunks-1);i++)
|
||||
{
|
||||
long offset;
|
||||
long filepos;
|
||||
|
||||
filepos = SizeTab[i];
|
||||
int sl = strlen(&filebuf[filepos]) + 1;
|
||||
if (sl&3) {
|
||||
sl += 4 - (sl & 3);
|
||||
}
|
||||
filepos += sl;
|
||||
offset = (SizeTab[i+1] - filepos - 4);
|
||||
//offset -= 8; // DON'T INCLUDE CHUNK HDR IN CHUNK SIZE
|
||||
|
||||
*(long*)&filebuf[filepos] = offset;
|
||||
}
|
||||
|
||||
FIO_Save( filename, (unsigned char *)filebuf, filelen);
|
||||
|
||||
free( filebuf );
|
||||
|
||||
if(expStream) fclose( expStream);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function: String manipulation functions
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
#define CTL_CHARS 40
|
||||
#define SINGLE_QUOTE 39
|
||||
|
||||
TCHAR* AsciiExp::FixupName(TCHAR* name)
|
||||
{
|
||||
static char buffer[256];
|
||||
TCHAR* cPtr;
|
||||
|
||||
_tcscpy(buffer, name);
|
||||
cPtr = buffer;
|
||||
|
||||
while(*cPtr)
|
||||
{
|
||||
if (*cPtr <= CTL_CHARS || *cPtr == '-')
|
||||
*cPtr = _T('_');
|
||||
cPtr++;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================
|
||||
end */
|
518
Utils/GinExp/ExpMaterial.cpp
Normal file
518
Utils/GinExp/ExpMaterial.cpp
Normal file
|
@ -0,0 +1,518 @@
|
|||
/*=========================================================================
|
||||
|
||||
EXPMATERIAL.CPP
|
||||
|
||||
Author: Tim Swann @ CLIMAX
|
||||
Created:
|
||||
Project:
|
||||
Purpose:
|
||||
|
||||
Copyright (c) 1998 Climax Development Ltd
|
||||
|
||||
===========================================================================*/
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Includes
|
||||
-------- */
|
||||
|
||||
#include "AsciiExp.h"
|
||||
#include "string.h"
|
||||
|
||||
/* Std Lib
|
||||
------- */
|
||||
|
||||
/* Glib
|
||||
---- */
|
||||
|
||||
/* Local
|
||||
----- */
|
||||
|
||||
/* Graphics
|
||||
-------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Tyepdefs && Defines
|
||||
------------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Structure defintions
|
||||
-------------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Positional Vars
|
||||
--------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function Prototypes
|
||||
------------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Vars
|
||||
---- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Data
|
||||
---- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
void AsciiExp::ExportMaterialList(void)
|
||||
{
|
||||
int numMtls = mtlList.Count();
|
||||
int i = 0;
|
||||
|
||||
|
||||
nbTexs = 0;
|
||||
nbMats = 0;
|
||||
|
||||
if (numMtls)
|
||||
{
|
||||
// EXPORT TEXTURE FILE LIST
|
||||
for (i=0; i<numMtls; i++) DumpMaterial( mtlList.GetMtl(i), i, -1 );
|
||||
if (nbTexs)
|
||||
{
|
||||
WriteChunkHdr( (char*)TEXTURE_ID, 0 );
|
||||
fwrite( &nbTexs, sizeof(Uint32), 1, expStream );
|
||||
for (int t=0;t<nbTexs;t++)
|
||||
{
|
||||
int PathLen = strlen(TexList[t]) + 1;
|
||||
if (PathLen&3) {
|
||||
PathLen += 4 - (PathLen & 3);
|
||||
}
|
||||
fwrite( &TexList[t], sizeof(char), PathLen, expStream );
|
||||
}
|
||||
}
|
||||
|
||||
// EXPORT MATERIAL LIST
|
||||
if (nbMats)
|
||||
{
|
||||
WriteChunkHdr( (char*)MATERIAL_ID, 0 );
|
||||
fwrite( &nbMats, sizeof(Uint32), 1, expStream );
|
||||
fwrite( &nCurObj, sizeof(Uint32), 1, expStream );
|
||||
for (int m=0;m<nbMats;m++)
|
||||
{
|
||||
fwrite( &MatList[m].material.diffuse.alpha, sizeof(float), 1, expStream);
|
||||
fwrite( &MatList[m].material.diffuse.colour.r, sizeof(float), 1, expStream);
|
||||
fwrite( &MatList[m].material.diffuse.colour.g, sizeof(float), 1, expStream);
|
||||
fwrite( &MatList[m].material.diffuse.colour.b, sizeof(float), 1, expStream);
|
||||
fwrite( &MatList[m].material.specular.alpha, sizeof(float), 1, expStream);
|
||||
fwrite( &MatList[m].material.specular.colour.r, sizeof(float), 1, expStream);
|
||||
fwrite( &MatList[m].material.specular.colour.g, sizeof(float), 1, expStream);
|
||||
fwrite( &MatList[m].material.specular.colour.b, sizeof(float), 1, expStream);
|
||||
fwrite( &MatList[m].material.tex_flags, sizeof(Uint32), 1, expStream);
|
||||
fwrite( &MatList[m].material.attr_flags, sizeof(Uint32), 1, expStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
---------------------------------------------------------------------- */
|
||||
char *makerelative(char const *basepath,char const *newpath, char *outstr)
|
||||
{
|
||||
#define FF_PATHNAMEMAX 256
|
||||
char temp1[FF_PATHNAMEMAX];
|
||||
char temp2[FF_PATHNAMEMAX];
|
||||
int i, j, match;
|
||||
|
||||
// Are the filenames the same?
|
||||
match = 0;
|
||||
for (j = 0; j < FF_PATHNAMEMAX; j++)
|
||||
{
|
||||
if (basepath[j] != newpath[j])
|
||||
{
|
||||
match = 0;
|
||||
break;
|
||||
}
|
||||
else if (basepath[j] == '.') // Matching
|
||||
{
|
||||
match = 1;
|
||||
break;
|
||||
}
|
||||
else if (basepath[j] == 0) // Identical
|
||||
{
|
||||
match = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (match) // Matching paths and filenames
|
||||
{
|
||||
strcpy(outstr, "#");
|
||||
strcat(outstr, &newpath[j]);
|
||||
}
|
||||
else if (basepath[0] != newpath[0]) // Drive letters are different
|
||||
strcpy(outstr, newpath);
|
||||
else
|
||||
{
|
||||
// Find the paths
|
||||
strcpy(temp1, basepath);
|
||||
for (i = strlen(temp1) - 1; i >= 0; i--)
|
||||
if (temp1[i] == '\\')
|
||||
break;
|
||||
else
|
||||
temp1[i] = 0;
|
||||
|
||||
strcpy(temp2, newpath);
|
||||
for (i = strlen(temp2) - 1; i >= 0; i--)
|
||||
if (temp2[i] == '\\')
|
||||
break;
|
||||
else
|
||||
temp2[i] = 0;
|
||||
|
||||
// Are the paths the same?
|
||||
strcpy(outstr, "");
|
||||
if (strcmp(temp1, temp2) == 0) // Paths are the same
|
||||
{
|
||||
j = strlen(temp1);
|
||||
}
|
||||
else // Paths are different
|
||||
{
|
||||
j = 2; // Drives are the same
|
||||
// Find different bits
|
||||
for (i = 0; i < (int) strlen(temp1); i++)
|
||||
{
|
||||
if ((temp1[i] == '\\') && (temp2[i] == '\\'))
|
||||
j = i + 1;
|
||||
else
|
||||
if (temp1[i] != temp2[i])
|
||||
break;
|
||||
}
|
||||
if (j > 3)
|
||||
{
|
||||
for (i = j; i < (int) strlen(temp1); i++)
|
||||
if (temp1[i] == '\\')
|
||||
strcat(outstr,"..\\");
|
||||
}
|
||||
else
|
||||
j = 2;
|
||||
}
|
||||
strcat(outstr, &newpath[j]);
|
||||
}
|
||||
return outstr;
|
||||
}
|
||||
|
||||
bool FileExists(const char* Name)
|
||||
{
|
||||
FILE *f = fopen(Name,"rb");
|
||||
if (f)
|
||||
{
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
TSTR AsciiExp::FindTextureFName(TSTR MapName)
|
||||
{
|
||||
char Out[256];
|
||||
_splitpath(filename, drive, dir, fname, ext);
|
||||
TSTR GinDir = TSTR(drive)+TSTR(dir);
|
||||
_splitpath(MapName, drive, dir, fname, ext);
|
||||
TSTR DriveDir = TSTR(drive)+TSTR(dir);
|
||||
TSTR FName = TSTR(fname) + TSTR(ext);
|
||||
|
||||
if (!FileExists(GinDir + FName))
|
||||
{
|
||||
MapName = ip->GetCurFilePath();
|
||||
_splitpath(MapName, drive, dir, fname, ext);
|
||||
DriveDir = TSTR(drive)+TSTR(dir);
|
||||
if (!FileExists(GinDir + FName))
|
||||
{
|
||||
int i=0;
|
||||
while (i<TheManager->GetMapDirCount())
|
||||
{
|
||||
DriveDir = TheManager->GetMapDir(i);
|
||||
DriveDir = DriveDir + TSTR("\\");
|
||||
if (FileExists(DriveDir + FName)) {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (i==TheManager->GetMapDirCount())
|
||||
{
|
||||
DriveDir = TSTR("");
|
||||
}
|
||||
}
|
||||
}
|
||||
GinDir.toLower();
|
||||
DriveDir.toLower();
|
||||
makerelative(GinDir, DriveDir, Out);
|
||||
return TSTR(Out);
|
||||
}
|
||||
|
||||
void AsciiExp::DumpTexture( Mtl* mtl, int matno, int subno )
|
||||
{
|
||||
Texmap * subTex = mtl->GetSubTexmap(ID_DI);
|
||||
|
||||
TSTR N = mtl->GetName();
|
||||
if (mtl->ClassID() == Class_ID(DMTL_CLASS_ID, 0))
|
||||
{
|
||||
if (subTex && subTex->ClassID() == Class_ID(BMTEX_CLASS_ID, 0))
|
||||
{
|
||||
// If it is a standard material we can see if the map is enabled.
|
||||
if (((StdMat*)mtl)->MapEnabled(ID_DI))
|
||||
{
|
||||
Bool found = FALSE;
|
||||
int texidx = nbTexs;
|
||||
char TexListTemp[256];
|
||||
|
||||
|
||||
TSTR mapName = ((BitmapTex *)subTex)->GetMapName();
|
||||
TSTR RelativePath = FindTextureFName(mapName);
|
||||
_splitpath(mapName, drive, dir, fname, ext);
|
||||
|
||||
if (RelativePath.isNull())
|
||||
{
|
||||
sprintf( TexListTemp, "%s%s", fname, ext);
|
||||
} else
|
||||
{
|
||||
sprintf( TexListTemp, "%s%s%s", RelativePath, fname, ext);
|
||||
}
|
||||
|
||||
for (int t=0;t<nbTexs;t++)
|
||||
{
|
||||
if (!strcmp(TexList[t], TexListTemp))
|
||||
{
|
||||
texidx = t;
|
||||
found = TRUE;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
strcpy( TexList[nbTexs], TexListTemp );
|
||||
nbTexs++;
|
||||
if(nbTexs>= MAXCOUNT) MessageBox( MAX_hWnd, "nbTexs Overflow", "ERROR", MB_OK);
|
||||
}
|
||||
MatList[matno].SubTex[(subno+1)] = texidx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (mtl->NumSubMtls() > 0)
|
||||
{
|
||||
for (int i=0; i<mtl->NumSubMtls(); i++)
|
||||
{
|
||||
Mtl * subMtl = mtl->GetSubMtl(i);
|
||||
if (subMtl)
|
||||
{
|
||||
DumpTexture( subMtl, matno, i );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int AsciiExp::getTextureId( Mtl *mtl )
|
||||
{
|
||||
Texmap * subTex = mtl->GetSubTexmap(ID_DI);
|
||||
|
||||
TSTR N = mtl->GetName();
|
||||
if (mtl->ClassID() == Class_ID(DMTL_CLASS_ID, 0))
|
||||
{
|
||||
if (subTex && subTex->ClassID() == Class_ID(BMTEX_CLASS_ID, 0))
|
||||
{
|
||||
// If it is a standard material we can see if the map is enabled.
|
||||
if (((StdMat*)mtl)->MapEnabled(ID_DI))
|
||||
{
|
||||
Bool found = FALSE;
|
||||
int texidx = nbTexs;
|
||||
char TexListTemp[256];
|
||||
|
||||
|
||||
TSTR mapName = ((BitmapTex *)subTex)->GetMapName();
|
||||
TSTR RelativePath = FindTextureFName(mapName);
|
||||
_splitpath(mapName, drive, dir, fname, ext);
|
||||
|
||||
fprintf( tempStream, " texName = %s\n", fname );
|
||||
if (RelativePath.isNull())
|
||||
{
|
||||
sprintf( TexListTemp, "%s%s", fname, ext);
|
||||
} else
|
||||
{
|
||||
sprintf( TexListTemp, "%s%s%s", RelativePath, fname, ext);
|
||||
}
|
||||
|
||||
for (int t=0;t<nbTexs;t++)
|
||||
{
|
||||
if (!strcmp(TexList[t], TexListTemp))
|
||||
{
|
||||
return t;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
strcpy( TexList[nbTexs], TexListTemp );
|
||||
nbTexs++;
|
||||
if(nbTexs>= MAXCOUNT) MessageBox( MAX_hWnd, "nbTexs Overflow", "ERROR", MB_OK);
|
||||
|
||||
return nbTexs-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
void AsciiExp::DumpMaterial( Mtl* mtl, int matno, int subno , bool recurse)
|
||||
{
|
||||
Color col;
|
||||
float alpha;
|
||||
Uint32 AttrFlags = 0;
|
||||
|
||||
|
||||
if (!mtl) return;
|
||||
|
||||
|
||||
sprintf( MatList[nbMats].name, "%s", FixupName( mtl->GetName() ) );
|
||||
|
||||
fprintf( tempStream, "matName = %s %d\n", mtl->GetName(), nbMats );
|
||||
// WE KNOW THE STANDARD MATERIAL, SO WE CAN GET SOME EXTRA INFO
|
||||
if (mtl->ClassID() == Class_ID(DMTL_CLASS_ID, 0))
|
||||
{
|
||||
StdMat * std;
|
||||
|
||||
std = (StdMat*)mtl;
|
||||
|
||||
|
||||
int tmap = getTextureId(mtl);
|
||||
if (std->MapEnabled(ID_DI) && tmap != -1) AttrFlags |= GIN_FLAG_USE_TEXTURE;
|
||||
if (std->MapEnabled(ID_RL)) AttrFlags |= GIN_FLAG_USE_ENVTEXTURE;
|
||||
if (std->GetTwoSided()) AttrFlags |= GIN_FLAG_DOUBLE_SIDE;
|
||||
if (std->GetSelfIllum( 0 ) > 0.2f ) AttrFlags |= GIN_FLAG_IGNORE_LIGHT;
|
||||
AttrFlags |= (std->GetTransparencyType()<<3);
|
||||
|
||||
col = std->GetDiffuse( 0 );
|
||||
alpha = std->GetOpacity( 0 );
|
||||
if (std->MapEnabled(ID_DI)) {
|
||||
MatList[nbMats].material.diffuse.alpha = alpha;
|
||||
MatList[nbMats].material.diffuse.colour = col;
|
||||
} else {
|
||||
MatList[nbMats].material.diffuse.alpha = alpha;
|
||||
MatList[nbMats].material.diffuse.colour = col;
|
||||
}
|
||||
|
||||
col = std->GetSpecular( 0 );
|
||||
MatList[nbMats].material.specular.alpha = alpha;
|
||||
MatList[nbMats].material.specular.colour = col;
|
||||
|
||||
MatList[nbMats].material.exponent = 6.f;
|
||||
|
||||
fprintf( tempStream, " tmap = %d\n\n", tmap );
|
||||
MatList[nbMats].material.tex_flags = tmap;
|
||||
MatList[nbMats].material.attr_flags = AttrFlags;
|
||||
|
||||
nbMats++;
|
||||
|
||||
} else
|
||||
{
|
||||
if (mtl->ClassID() != Class_ID(MULTI_CLASS_ID, 0))
|
||||
{
|
||||
memset(&MatList[nbMats], 0, sizeof(MATLIST));
|
||||
MatList[nbMats].material.tex_flags = -1;
|
||||
nbMats++;
|
||||
}
|
||||
}
|
||||
|
||||
if (mtl->NumSubMtls() > 0)
|
||||
{
|
||||
int c = (recurse) ? 1 : mtl->NumSubMtls();
|
||||
for (int i=0; i< c ; i++)
|
||||
{
|
||||
Mtl* subMtl = mtl->GetSubMtl(i);
|
||||
if (subMtl)
|
||||
{
|
||||
DumpMaterial( subMtl, matno, i , true);
|
||||
} else
|
||||
{
|
||||
nbMats++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(nbMats>= MAXCOUNT) MessageBox( MAX_hWnd, "nbMats Overflow", "ERROR", MB_OK);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
int MtlKeeper::GetSubMtlCount(Mtl* mtl, bool recurse)
|
||||
{
|
||||
int Count = 0;
|
||||
if (!mtl)
|
||||
return 0;
|
||||
if (mtl->ClassID() == Class_ID(DMTL_CLASS_ID, 0))
|
||||
Count ++;
|
||||
if (mtl->NumSubMtls() > 0)
|
||||
{
|
||||
int c = (recurse) ? 1 : mtl->NumSubMtls();
|
||||
for (int i=0; i<c; i++)
|
||||
{
|
||||
Mtl* subMtl = mtl->GetSubMtl(i);
|
||||
if (subMtl)
|
||||
{
|
||||
Count += GetSubMtlCount( subMtl, true);
|
||||
} else
|
||||
{
|
||||
Count ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Count;
|
||||
}
|
||||
|
||||
BOOL MtlKeeper::AddMtl(Mtl* mtl)
|
||||
{
|
||||
if (!mtl) return FALSE;
|
||||
|
||||
int numMtls = mtlTab.Count();
|
||||
for (int i=0; i<numMtls; i++)
|
||||
{
|
||||
if (mtlTab[i] == mtl) return FALSE;
|
||||
}
|
||||
|
||||
mtlTab.Append(1, &mtl, 25);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
int MtlKeeper::GetMtlID(Mtl* mtl)
|
||||
{
|
||||
int numMtls = mtlTab.Count();
|
||||
int CurIdx = 0;
|
||||
int count = 0;
|
||||
for (int i=0; i<numMtls; i++)
|
||||
{
|
||||
if (mtlTab[i] == mtl) return count;
|
||||
count += GetSubMtlCount(mtlTab[i], false);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int MtlKeeper::Count()
|
||||
{
|
||||
return mtlTab.Count();
|
||||
}
|
||||
|
||||
Mtl* MtlKeeper::GetMtl(int id)
|
||||
{
|
||||
return mtlTab[id];
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================
|
||||
end */
|
952
Utils/GinExp/ExpModel.cpp
Normal file
952
Utils/GinExp/ExpModel.cpp
Normal file
|
@ -0,0 +1,952 @@
|
|||
/*=========================================================================
|
||||
|
||||
EXPMODEL.CPP
|
||||
|
||||
Author: Tim Swann @ CLIMAX
|
||||
Created:
|
||||
Project:
|
||||
Purpose:
|
||||
|
||||
Copyright (c) 1998 Climax Development Ltd
|
||||
|
||||
===========================================================================*/
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Includes
|
||||
-------- */
|
||||
|
||||
#include "AsciiExp.h"
|
||||
|
||||
|
||||
/* Std Lib
|
||||
------- */
|
||||
|
||||
/* Glib
|
||||
---- */
|
||||
|
||||
/* Local
|
||||
----- */
|
||||
|
||||
/* Graphics
|
||||
-------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Tyepdefs && Defines
|
||||
------------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Structure defintions
|
||||
-------------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Positional Vars
|
||||
--------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function Prototypes
|
||||
------------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Vars
|
||||
---- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Data
|
||||
---- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
void AsciiExp::ExportModel(INode* node)
|
||||
{
|
||||
ObjectState os = node->EvalWorldState( ip->GetAnimRange().Start() );
|
||||
char nodeName[256];
|
||||
|
||||
// Targets are actually geomobjects, but we will export them
|
||||
// from the camera and light objects, so we skip them here.
|
||||
if (os.obj->ClassID() == Class_ID(TARGET_CLASS_ID, 0)) return;
|
||||
ip->ProgressUpdate(0,0,"Export Model0");
|
||||
|
||||
sprintf(nodeName, "%s", node->GetName());
|
||||
strupr(nodeName);
|
||||
if (nodeName[0] != 'R' ||
|
||||
nodeName[1] != 'O' ||
|
||||
nodeName[2] != 'O' ||
|
||||
nodeName[3] != 'T')
|
||||
{
|
||||
ip->ProgressUpdate(0,0,"Export ModelRoot");
|
||||
WriteChunkHdr( (char*)OBJ_ID, 0 );
|
||||
fwrite(&totFrames, sizeof(int), 1, expStream);
|
||||
fwrite(nodeName, MAX_NAME_LENGTH, 1, expStream);
|
||||
|
||||
ip->ProgressUpdate(0,0,"Export Model-Mesh");
|
||||
ExportMesh( node );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
void AsciiExp::ExportMesh( INode* node )
|
||||
{
|
||||
|
||||
Matrix3 tm = node->GetObjTMAfterWSM( ip->GetAnimRange().Start() );
|
||||
Uint32 EvalFlags = 0;
|
||||
Point3 ObjPos;
|
||||
Point3 ObjRot;
|
||||
Point3 ObjSca;
|
||||
Point3 center = Point3(0.f, 0.f, 0.f);
|
||||
AffineParts ap;
|
||||
Mesh * mesh;
|
||||
ObjectState os;
|
||||
Object * obj;
|
||||
BOOL needDel;
|
||||
TriObject * tri;
|
||||
|
||||
os = node->EvalWorldState( ip->GetAnimRange().Start() );
|
||||
obj = node->EvalWorldState( ip->GetAnimRange().Start() ).obj;
|
||||
|
||||
Mtl * nodeMtl = node->GetMtl();
|
||||
if (!nodeMtl) return;
|
||||
|
||||
if (!os.obj) return;
|
||||
if (!obj->IsRenderable()) return;
|
||||
if (node->IsNodeHidden()) return;
|
||||
if (!obj || os.obj->SuperClassID() != GEOMOBJECT_CLASS_ID) return; // Safety net. This shouldn't happen.
|
||||
|
||||
tri = GetTriObjectFromNode(node, ip->GetAnimRange().Start(), needDel);
|
||||
if (!tri) return;
|
||||
|
||||
mesh = &tri->mesh;
|
||||
|
||||
mtlList.AddMtl(nodeMtl);
|
||||
|
||||
ip->ProgressUpdate(0,0,"ExportMeshList");
|
||||
ExportMeshList( node, mesh );
|
||||
ip->ProgressUpdate(0,0,"ExportPoints");
|
||||
ExportPoints( node, mesh );
|
||||
ip->ProgressUpdate(0,0,"ExportVectors");
|
||||
ExportVectors( node, mesh);
|
||||
ip->ProgressUpdate(0,0,"ExportVectorsDone");
|
||||
|
||||
if (needDel) delete tri;
|
||||
|
||||
tri = GetTriObjectFromNode(node, ip->GetAnimRange().End(), needDel);
|
||||
if (!tri) return;
|
||||
|
||||
mesh = &tri->mesh;
|
||||
ip->ProgressUpdate(0,0,"ExportNormals");
|
||||
ExportNormals( node, mesh );
|
||||
if (needDel) delete tri;
|
||||
ip->ProgressUpdate(0,0,"ExportNormalsDone");
|
||||
|
||||
tm = node->GetObjTMAfterWSM(ip->GetAnimRange().Start());// * Inverse(node->GetParentTM(t));
|
||||
decomp_affine(tm, &ap);
|
||||
|
||||
ip->ProgressUpdate(0,0,"WriteHeader0");
|
||||
WriteChunkHdr( (char*)MODEL_ID, 0 );
|
||||
fwrite( &nCurObj, sizeof(long), 1, expStream );
|
||||
char NodeName[MAX_NAME_LENGTH];
|
||||
sprintf(NodeName,"%s",node->GetName());
|
||||
// fwrite( node->GetName(), MAX_NAME_LENGTH, 1, expStream);
|
||||
fwrite( NodeName, MAX_NAME_LENGTH, 1, expStream);
|
||||
fwrite( &radius, sizeof(float), 1, expStream );
|
||||
fwrite( ¢er.x, sizeof(float), 1, expStream );
|
||||
fwrite( ¢er.y, sizeof(float), 1, expStream );
|
||||
fwrite( ¢er.z, sizeof(float), 1, expStream );
|
||||
fwrite( &ap.t.x, sizeof(float), 1, expStream );
|
||||
fwrite( &ap.t.z, sizeof(float), 1, expStream );
|
||||
fwrite( &ap.t.y, sizeof(float), 1, expStream );
|
||||
//ProgressUpdate(int pct, BOOL showPct = TRUE, TCHAR *title = NULL)=0
|
||||
|
||||
ip->ProgressUpdate(0,0,"WriteHeaderDone");
|
||||
|
||||
ip->ProgressUpdate(0,0,"FindPhysiqueModifier");
|
||||
if (FindPhysiqueModifier(node))
|
||||
{
|
||||
ip->ProgressUpdate(0,0,"ExportWeights");
|
||||
ExportWeights(node);
|
||||
}
|
||||
else
|
||||
ip->ProgressUpdate(0,0,"FindFFDModifier");
|
||||
if (FindFFDModifier(node))
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
ip->ProgressUpdate(0,0,"ExportNodeAnimMesh");
|
||||
ExportNodeAnimMesh( node );
|
||||
}
|
||||
|
||||
// ExportAnimMesh( node );
|
||||
ip->ProgressUpdate(0,0,"FindEditableMesh");
|
||||
FindEditableMesh(node);
|
||||
ip->ProgressUpdate(0,0,"ExportVisTrack");
|
||||
ExportVisTrack( node );
|
||||
nCurObj++;
|
||||
}
|
||||
|
||||
void AsciiExp::FindEditableMesh(INode *node)
|
||||
{
|
||||
Object *o = node->GetObjectRef();
|
||||
while (o && o->SuperClassID() == GEN_DERIVOB_CLASS_ID)
|
||||
{
|
||||
o = ((IDerivedObject*)o)->GetObjRef();
|
||||
}
|
||||
if (o && o->ClassID() == Class_ID(EDITTRIOBJ_CLASS_ID,0))
|
||||
{
|
||||
ExportMeshVertAnim(node, (EditTriObject*)o);
|
||||
}
|
||||
}
|
||||
|
||||
void AsciiExp::ExportMeshVertAnim(INode *node, EditTriObject *e)
|
||||
{
|
||||
TimeValue start = ip->GetAnimRange().Start();
|
||||
TimeValue end = ip->GetAnimRange().End();
|
||||
int delta = GetTicksPerFrame();
|
||||
|
||||
int Controls = e->cont.Count();
|
||||
|
||||
|
||||
Matrix3 tm = node->GetObjTMAfterWSM( ip->GetAnimRange().Start() );
|
||||
Point3 p;
|
||||
|
||||
Controls = 0;
|
||||
for (int i=0; i<e->cont.Count(); i++) {
|
||||
if (e->cont[i]) {
|
||||
Controls++;
|
||||
}
|
||||
}
|
||||
|
||||
ITCBPoint3Key tcbPosKey;
|
||||
IBezPoint3Key bezPosKey;
|
||||
|
||||
WriteChunkHdr( (char*)KEY_ID, 0);
|
||||
fwrite( &CHANNEL_TYPE_VERTEX, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &CHANNEL_INFO_POSITION, sizeof( Uint32) , 1, expStream);
|
||||
fwrite( &nCurObj, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &Controls, sizeof(int), 1, expStream);
|
||||
|
||||
for (i=0; i<e->cont.Count(); i++) {
|
||||
if (e->cont[i]) {
|
||||
Control *c = GetControlInterface(e->cont[i]);
|
||||
IKeyControl *ikeys;
|
||||
TimeList tl;
|
||||
TimeValue time;
|
||||
tl.Clear();
|
||||
if (c) {
|
||||
ikeys = GetKeyControlInterface(c);
|
||||
int num = ikeys->GetNumKeys();
|
||||
for (int j = 0; j<num; j++)
|
||||
{
|
||||
if (c->ClassID() == Class_ID(TCBINTERP_POINT3_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(j, &tcbPosKey);
|
||||
time = tcbPosKey.time;
|
||||
}
|
||||
else
|
||||
if (c->ClassID() == Class_ID(HYBRIDINTERP_POINT3_CLASS_ID, 0))
|
||||
{
|
||||
ikeys->GetKey(j, &bezPosKey);
|
||||
time = bezPosKey.time;
|
||||
}
|
||||
tl.Add(time);
|
||||
}
|
||||
num = tl.Count();
|
||||
fwrite(&i, sizeof(int), 1, expStream);
|
||||
fwrite(&num, sizeof(int), 1, expStream);
|
||||
for (j=0; j<num; j++) {
|
||||
time = tl.Get(j);
|
||||
tm = node->GetObjTMAfterWSM(time);
|
||||
e->cont[i]->GetValue(time,&p,FOREVER);
|
||||
p = tm * p;
|
||||
time = (time-start) / delta;
|
||||
fwrite(&time, sizeof(int), 1, expStream);
|
||||
fwrite(&p.x, sizeof(float), 1, expStream);
|
||||
fwrite(&p.z, sizeof(float), 1, expStream);
|
||||
fwrite(&p.y, sizeof(float), 1, expStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
---------------------------------------------------------------------- */
|
||||
int GetSubMtlCount(Mtl* mtl, bool recurse = false)
|
||||
{
|
||||
int Count = 0;
|
||||
if (!mtl)
|
||||
return 0;
|
||||
if (mtl->ClassID() == Class_ID(DMTL_CLASS_ID, 0))
|
||||
Count ++;
|
||||
|
||||
if (mtl->NumSubMtls() > 0)
|
||||
{
|
||||
int c = (recurse) ? 1 : mtl->NumSubMtls();
|
||||
for (int i=0; i<c; i++)
|
||||
{
|
||||
Mtl* subMtl = mtl->GetSubMtl(i);
|
||||
if (subMtl)
|
||||
{
|
||||
Count += GetSubMtlCount( subMtl, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Count;
|
||||
}
|
||||
|
||||
void AsciiExp::ExportMeshList(INode * node, Mesh * mesh)
|
||||
{
|
||||
MtlID matid;
|
||||
MtlID matref;
|
||||
Mtl * nodeMtl = node->GetMtl();
|
||||
int m;
|
||||
ObjectState os;
|
||||
Object * obj;
|
||||
Matrix3 tm = node->GetObjTMAfterWSM( ip->GetAnimRange().Start() );
|
||||
BOOL negScale = TMNegParity(tm);
|
||||
int vx1, vx2, vx3;
|
||||
const char * name = node->GetName();
|
||||
|
||||
|
||||
// fprintf( tempStream, "MESHLIST = %s\n\n", name );
|
||||
|
||||
obj = node->EvalWorldState( ip->GetAnimRange().Start() ).obj;
|
||||
mesh->buildNormals();
|
||||
|
||||
// Order of the vertices. Get 'em counter clockwise if the objects is
|
||||
// negatively scaled.
|
||||
if (negScale)
|
||||
{
|
||||
vx1 = 2;
|
||||
vx2 = 1;
|
||||
vx3 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
vx1 = 0;
|
||||
vx2 = 1;
|
||||
vx3 = 2;
|
||||
}
|
||||
|
||||
int MtlCount = GetSubMtlCount(nodeMtl);
|
||||
if (MtlCount == 0) return;
|
||||
// Find all mesh materials used
|
||||
nbMeshs = 0;
|
||||
for (int i=0; i<mesh->getNumFaces(); i++)
|
||||
{
|
||||
Bool found = FALSE;
|
||||
|
||||
matid = ((unsigned long)mesh->getFaceMtlIndex(i)) % MtlCount;
|
||||
|
||||
// fprintf( tempStream, "MATID = %d - FACEID = %d\n", mesh->faces[i].getMatID(), mesh->getFaceMtlIndex(i) );
|
||||
|
||||
for (int f=0;f<nbMeshs;f++)
|
||||
{
|
||||
if (matid == MeshSet[f].MatId)
|
||||
{
|
||||
MeshSet[f].nbFaces++;
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
MeshSet[nbMeshs].MatId = matid;
|
||||
MeshSet[nbMeshs].nbFaces = 1;
|
||||
nbMeshs++;
|
||||
if(nbMeshs>= MAXCOUNT) MessageBox( MAX_hWnd, "nbMeshs Overflow", "ERROR", MB_OK);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Sort material id's for ease of access
|
||||
|
||||
for (m=0;m<nbMeshs;m++)
|
||||
{
|
||||
for (int m2=0;m2<(nbMeshs-1);m2++)
|
||||
{
|
||||
if (MeshSet[m2].MatId > MeshSet[m2+1].MatId)
|
||||
{
|
||||
MESH_SET meshset = MeshSet[m2];
|
||||
MeshSet[m2] = MeshSet[m2+1];
|
||||
MeshSet[m2+1] = meshset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (m=0;m<nbMeshs;m++)
|
||||
{
|
||||
int nbFaces;
|
||||
|
||||
// EXPORT POLY CONNECT LIST - PER MESH
|
||||
WriteChunkHdr( (char*)POLY_ID, 0 );
|
||||
fwrite( &nCurObj, sizeof(Uint16), 1, expStream );
|
||||
fwrite( &m, sizeof(Uint16), 1, expStream );
|
||||
nbFaces = MeshSet[m].nbFaces;
|
||||
fwrite( &nbFaces, sizeof(Uint32), 1, expStream );
|
||||
|
||||
for (i=0; i<mesh->getNumFaces(); i++)
|
||||
{
|
||||
matid = ((unsigned long)mesh->getFaceMtlIndex(i)) % MtlCount;
|
||||
if (matid == MeshSet[m].MatId)
|
||||
{
|
||||
fwrite( &mesh->faces[i].v[vx1], sizeof(long), 1, expStream );
|
||||
fwrite( &mesh->faces[i].v[vx2], sizeof(long), 1, expStream );
|
||||
fwrite( &mesh->faces[i].v[vx3], sizeof(long), 1, expStream );
|
||||
long HF0=mesh->faces[i].getEdgeVis(vx1);
|
||||
long HF1=mesh->faces[i].getEdgeVis(vx2);
|
||||
long HF2=mesh->faces[i].getEdgeVis(vx3);
|
||||
fwrite( &HF0, sizeof(long), 1, expStream );
|
||||
fwrite( &HF1, sizeof(long), 1, expStream );
|
||||
fwrite( &HF2, sizeof(long), 1, expStream );
|
||||
// fprintf( tempStream, "Face = %d - HF= %d %d %d\n", i,HF0,HF1,HF2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// EXPORT FACE MAP TEXCOORDS IF WE HAVE THEM...
|
||||
if (obj->HasUVW())
|
||||
{
|
||||
if (!CheckForAndExportFaceMap(nodeMtl, mesh, m))
|
||||
{
|
||||
// If not, export standard tverts
|
||||
int numTVx = mesh->getNumTVerts();
|
||||
|
||||
if (numTVx)
|
||||
{
|
||||
int nbFaces;
|
||||
|
||||
WriteChunkHdr( (char*)UV_ID, 0 );
|
||||
fwrite( &nCurObj, sizeof(Uint16), 1, expStream );
|
||||
fwrite( &m, sizeof(Uint16), 1, expStream );
|
||||
nbFaces = MeshSet[m].nbFaces;
|
||||
fwrite( &nbFaces, sizeof(Uint32), 1, expStream );
|
||||
|
||||
for (i=0; i<mesh->getNumFaces(); i++)
|
||||
{
|
||||
matid = ((unsigned long)mesh->getFaceMtlIndex(i)) % MtlCount;
|
||||
|
||||
if (matid == MeshSet[m].MatId)
|
||||
{
|
||||
UVVert tv;
|
||||
int idx;
|
||||
|
||||
idx = mesh->tvFace[i].t[vx1];
|
||||
tv = mesh->tVerts[idx];
|
||||
fwrite(&tv.x, sizeof(float), 1, expStream);
|
||||
fwrite(&tv.y, sizeof(float), 1, expStream);
|
||||
|
||||
idx = mesh->tvFace[i].t[vx2];
|
||||
tv = mesh->tVerts[idx];
|
||||
fwrite(&tv.x, sizeof(float), 1, expStream);
|
||||
fwrite(&tv.y, sizeof(float), 1, expStream);
|
||||
|
||||
idx = mesh->tvFace[i].t[vx3];
|
||||
tv = mesh->tVerts[idx];
|
||||
fwrite(&tv.x, sizeof(float), 1, expStream);
|
||||
fwrite(&tv.y, sizeof(float), 1, expStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
int nbFaces;
|
||||
|
||||
WriteChunkHdr( (char*)FACENORMAL_ID, 0 );
|
||||
fwrite( &nCurObj, sizeof(Uint16), 1, expStream );
|
||||
fwrite( &m, sizeof(Uint16), 1, expStream );
|
||||
nbFaces = MeshSet[m].nbFaces;
|
||||
fwrite( &nbFaces, sizeof(Uint32), 1, expStream );
|
||||
|
||||
for (i=0; i<mesh->getNumFaces(); i++)
|
||||
{
|
||||
matid = ((unsigned long)mesh->getFaceMtlIndex(i)) % MtlCount;
|
||||
if (matid == MeshSet[m].MatId)
|
||||
{
|
||||
Point3 n=GetVertexNormal(mesh, i,mesh->getRVertPtr(mesh->faces[i].v[vx1]));
|
||||
fwrite(&n.x, sizeof(float), 1, expStream);
|
||||
fwrite(&n.y, sizeof(float), 1, expStream);
|
||||
fwrite(&n.z, sizeof(float), 1, expStream);
|
||||
|
||||
n=GetVertexNormal(mesh, i,mesh->getRVertPtr(mesh->faces[i].v[vx2]));
|
||||
fwrite(&n.x, sizeof(float), 1, expStream);
|
||||
fwrite(&n.y, sizeof(float), 1, expStream);
|
||||
fwrite(&n.z, sizeof(float), 1, expStream);
|
||||
|
||||
n=GetVertexNormal(mesh, i,mesh->getRVertPtr(mesh->faces[i].v[vx3]));
|
||||
fwrite(&n.x, sizeof(float), 1, expStream);
|
||||
fwrite(&n.y, sizeof(float), 1, expStream);
|
||||
fwrite(&n.z, sizeof(float), 1, expStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
// tris[result].VertNormals[s] = Normalize(transpose * (m * get_vertex_normal(&triobj->mesh, j, triobj->mesh.getRVertPtr(fces[j].v[s]))));
|
||||
if (mesh->getNumVertCol())
|
||||
{
|
||||
Point3 vc;
|
||||
WriteChunkHdr( (char*)VCOL_ID, 0 );
|
||||
fwrite( &nCurObj, sizeof(Uint32), 1, expStream );
|
||||
fwrite( &m , sizeof(Uint32), 1, expStream );
|
||||
int nbFaces = MeshSet[m].nbFaces;
|
||||
fwrite( &nbFaces, sizeof(Uint32), 1, expStream );
|
||||
for (i=0; i<mesh->getNumFaces(); i++)
|
||||
{
|
||||
matid = ((unsigned long)mesh->getFaceMtlIndex(i)) % MtlCount;
|
||||
|
||||
if (matid == MeshSet[m].MatId)
|
||||
{
|
||||
TVFace *f = &mesh->vcFace[i];
|
||||
int vert = f->t[vx1];
|
||||
vc = mesh->vertCol[vert];
|
||||
fwrite(&vc.x, sizeof(float), 1, expStream);
|
||||
fwrite(&vc.y, sizeof(float), 1, expStream);
|
||||
fwrite(&vc.z, sizeof(float), 1, expStream);
|
||||
|
||||
vert = f->t[vx2];
|
||||
vc = mesh->vertCol[vert];
|
||||
fwrite(&vc.x, sizeof(float), 1, expStream);
|
||||
fwrite(&vc.y, sizeof(float), 1, expStream);
|
||||
fwrite(&vc.z, sizeof(float), 1, expStream);
|
||||
|
||||
vert = f->t[vx3];
|
||||
vc = mesh->vertCol[vert];
|
||||
fwrite(&vc.x, sizeof(float), 1, expStream);
|
||||
fwrite(&vc.y, sizeof(float), 1, expStream);
|
||||
fwrite(&vc.z, sizeof(float), 1, expStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// EXPORT MESHSET INFO
|
||||
WriteChunkHdr( (char*)MESH_ID, 0 );
|
||||
fwrite( &nCurObj, sizeof(long), 1, expStream );
|
||||
fwrite( &nbMeshs, sizeof(long), 1, expStream );
|
||||
|
||||
int NodeMatRef = mtlList.GetMtlID(nodeMtl);
|
||||
for (m=0;m<nbMeshs;m++)
|
||||
{
|
||||
matref = MeshSet[m].MatId + NodeMatRef;
|
||||
// fprintf( tempStream, "matIdx = %d %d\n", MeshSet[m].MatId, matref );
|
||||
|
||||
fwrite(&matref, sizeof(Uint16), 1, expStream);
|
||||
fwrite(&MeshSet[m].nbFaces, sizeof(Uint16), 1, expStream);
|
||||
|
||||
Uint32 TempStore;
|
||||
TempStore = m;
|
||||
fwrite(&TempStore, sizeof(Uint32), 1, expStream); // polt list
|
||||
TempStore = -1;
|
||||
fwrite(&TempStore, sizeof(Uint32), 1, expStream); // attr list
|
||||
fwrite(&TempStore, sizeof(Uint32), 1, expStream); // normal list
|
||||
TempStore = -1;
|
||||
if (!mesh->vertCol)
|
||||
TempStore = m;
|
||||
fwrite(&TempStore, sizeof(Uint32), 1, expStream); // vertex col list
|
||||
TempStore = -1;
|
||||
if (obj->HasUVW())
|
||||
TempStore = m;
|
||||
fwrite(&TempStore, sizeof(Uint32), 1, expStream); // texture list
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
BOOL AsciiExp::CheckForAndExportFaceMap(Mtl* mtl, Mesh* mesh, int meshno)
|
||||
{
|
||||
MtlID matid;
|
||||
ULONG matreq;
|
||||
|
||||
return FALSE;
|
||||
|
||||
if (!mtl || !mesh) return FALSE;
|
||||
|
||||
matreq = mtl->Requirements(-1);
|
||||
|
||||
// ARE WE USING FACE MAPPING?
|
||||
if (!(matreq & MTLREQ_FACEMAP)) return FALSE;
|
||||
|
||||
|
||||
// OK, WE HAVE A FACEMAP SITUATION HERE...
|
||||
|
||||
WriteChunkHdr( (char*)UV_ID, 0 );
|
||||
fwrite( &nCurObj, sizeof(Uint16), 1, expStream );
|
||||
fwrite( &meshno, sizeof(Uint16), 1, expStream );
|
||||
Uint32 mnf = MeshSet[meshno].nbFaces;
|
||||
fwrite( &mnf, sizeof(Uint32), 1, expStream );
|
||||
|
||||
for (int i=0; i<mesh->getNumFaces(); i++)
|
||||
{
|
||||
matid = mesh->getFaceMtlIndex(i);//faces[i].getMatID();
|
||||
|
||||
if (matid == MeshSet[meshno].MatId)
|
||||
{
|
||||
Point3 tv[3];
|
||||
Face * f;
|
||||
// NJS_COLOR uv;
|
||||
|
||||
f = &mesh->faces[i];
|
||||
make_face_uv( f, tv );
|
||||
|
||||
fwrite(&tv[0].x, sizeof(float), 1, expStream);
|
||||
fwrite(&tv[0].y, sizeof(float), 1, expStream);
|
||||
fwrite(&tv[1].x, sizeof(float), 1, expStream);
|
||||
fwrite(&tv[1].y, sizeof(float), 1, expStream);
|
||||
fwrite(&tv[2].x, sizeof(float), 1, expStream);
|
||||
fwrite(&tv[2].y, sizeof(float), 1, expStream);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
void AsciiExp::ExportPoints(INode * node, Mesh * mesh)
|
||||
{
|
||||
Matrix3 tm = node->GetObjTMAfterWSM( ip->GetAnimRange().Start() );
|
||||
Point3 Trans;
|
||||
int nbVerts;
|
||||
|
||||
radius = 0.f;
|
||||
nbVerts = mesh->getNumVerts();
|
||||
|
||||
// EXPORT MODEL POINTS
|
||||
WriteChunkHdr( (char*)POINTS_ID, 0 );
|
||||
fwrite( &nCurObj, sizeof(Uint32), 1, expStream );
|
||||
fwrite( &nbVerts, sizeof(Uint32), 1, expStream );
|
||||
|
||||
for (int i=0; i<nbVerts; i++)
|
||||
{
|
||||
Point3 v1;
|
||||
Point3 v2;
|
||||
|
||||
tm = node->GetObjTMAfterWSM( ip->GetAnimRange().Start() );
|
||||
v1 = mesh->verts[i];
|
||||
//v2 = VectorTransform( tm, v1 );
|
||||
//v2 += tm.GetTrans();
|
||||
v2 = tm * v1;
|
||||
Trans = v2;
|
||||
|
||||
//Trans.y = Trans.y;
|
||||
fwrite( &Trans.x, sizeof(float), 1, expStream );
|
||||
fwrite( &Trans.z, sizeof(float), 1, expStream );
|
||||
fwrite( &Trans.y, sizeof(float), 1, expStream );
|
||||
|
||||
if (radius < fabs(Trans.x)) radius = (float)fabs(Trans.x);
|
||||
if (radius < fabs(Trans.y)) radius = (float)fabs(Trans.y);
|
||||
if (radius < fabs(Trans.z)) radius = (float)fabs(Trans.z);
|
||||
}
|
||||
}
|
||||
|
||||
void AsciiExp::ExportVectors(INode * node, Mesh * mesh)
|
||||
{
|
||||
Matrix3 tm = node->GetObjTMAfterWSM( ip->GetAnimRange().Start() );
|
||||
Point3 Trans;
|
||||
int nbVerts;
|
||||
|
||||
radius = 0.f;
|
||||
nbVerts = mesh->getNumVerts();
|
||||
|
||||
// EXPORT MODEL POINTS
|
||||
WriteChunkHdr( (char*)VECT_ID, 0 );
|
||||
fwrite( &nCurObj, sizeof(Uint32), 1, expStream );
|
||||
fwrite( &nbVerts, sizeof(Uint32), 1, expStream );
|
||||
|
||||
for (int i=0; i<nbVerts; i++)
|
||||
{
|
||||
Point3 v1;
|
||||
|
||||
v1 = mesh->verts[i];
|
||||
|
||||
fwrite( &v1.x, sizeof(float), 1, expStream );
|
||||
fwrite( &v1.z, sizeof(float), 1, expStream );
|
||||
fwrite( &v1.y, sizeof(float), 1, expStream );
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
void AsciiExp::ExportNormals(INode * node, Mesh * mesh)
|
||||
{
|
||||
int nbVerts;
|
||||
Point3 * vnorms;
|
||||
Point3 fn; // Face normal
|
||||
Point3 vn; // Vertex normal
|
||||
|
||||
int i;
|
||||
Matrix3 tm = node->GetObjTMAfterWSM( ip->GetAnimRange().End() );
|
||||
BOOL negScale = TMNegParity(tm);
|
||||
int vx1, vx2, vx3;
|
||||
|
||||
|
||||
if (negScale)
|
||||
{
|
||||
vx1 = 2;
|
||||
vx2 = 1;
|
||||
vx3 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
vx1 = 0;
|
||||
vx2 = 1;
|
||||
vx3 = 2;
|
||||
}
|
||||
|
||||
|
||||
mesh->buildNormals();
|
||||
|
||||
nbVerts = mesh->getNumVerts();
|
||||
vnorms = new Point3[nbVerts];
|
||||
|
||||
for (i=0; i<mesh->getNumVerts(); i++)
|
||||
{
|
||||
vnorms[i] = GetAverageVertNormal(node, mesh, i);
|
||||
}
|
||||
|
||||
|
||||
// EXPORT MODEL NORMALS
|
||||
WriteChunkHdr( (char*)NORMAL_ID, 0 );
|
||||
fwrite( &nCurObj, sizeof(Uint32), 1, expStream );
|
||||
fwrite( &nbVerts, sizeof(Uint32), 1, expStream );
|
||||
|
||||
for (i=0; i<nbVerts; i++)
|
||||
{
|
||||
vn = vnorms[i];
|
||||
fwrite( &vn.x, sizeof(float), 1, expStream );
|
||||
fwrite( &vn.z, sizeof(float), 1, expStream );
|
||||
fwrite( &vn.y, sizeof(float), 1, expStream );
|
||||
}
|
||||
|
||||
delete vnorms;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
Point3 AsciiExp::GetVertexNormal(Mesh* mesh, int faceNo, RVertex* rv)
|
||||
{
|
||||
Face* f = &mesh->faces[faceNo];
|
||||
DWORD smGroup = f->smGroup;
|
||||
int numNormals;
|
||||
Point3 vertexNormal;
|
||||
|
||||
// Is normal specified
|
||||
// SPCIFIED is not currently used, but may be used in future versions.
|
||||
if (rv->rFlags & SPECIFIED_NORMAL)
|
||||
{
|
||||
// fprintf( pStream, "SPECIFIED_NORMAL\n");
|
||||
vertexNormal = rv->rn.getNormal();
|
||||
}
|
||||
// If normal is not specified it's only available if the face belongs
|
||||
// to a smoothing group
|
||||
else if ((numNormals = rv->rFlags & NORCT_MASK) && smGroup)
|
||||
{
|
||||
// If there is only one vertex is found in the rn member.
|
||||
if (numNormals == 1)
|
||||
{
|
||||
// fprintf( pStream, "SINGLE SMOOTHING GROUP\n");
|
||||
vertexNormal = rv->rn.getNormal();
|
||||
}
|
||||
else
|
||||
{
|
||||
// fprintf( pStream, "SMOOTHING GROUP %d\n", numNormals);
|
||||
|
||||
// If two or more vertices are there you need to step through them
|
||||
// and find the vertex with the same smoothing group as the current face.
|
||||
// You will find multiple normals in the ern member.
|
||||
for (int i = 0; i < numNormals; i++)
|
||||
{
|
||||
vertexNormal = rv->ern[i].getNormal();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// fprintf( pStream, "NO SMOOTHING GROUP\n");
|
||||
// Get the normal from the Face if no smoothing groups are there
|
||||
vertexNormal = mesh->getFaceNormal(faceNo);
|
||||
}
|
||||
|
||||
return vertexNormal;
|
||||
}
|
||||
|
||||
Point3 AsciiExp::GetAverageVertNormal(INode *node, Mesh* mesh, int VertNo)
|
||||
{
|
||||
int i;
|
||||
int c=0;
|
||||
Matrix3 tm = node->GetNodeTM(ip->GetAnimRange().Start());
|
||||
tm.NoTrans();
|
||||
Point3 n= Point3(0.f,0.f,0.f);
|
||||
for (i=0; i<mesh->getNumFaces(); i++) {
|
||||
if (mesh->faces[i].v[0] == VertNo || mesh->faces[i].v[1] == VertNo || mesh->faces[i].v[2] == VertNo)
|
||||
{
|
||||
Point3 p0 = tm * mesh->verts[mesh->faces[i].v[0]];
|
||||
Point3 p1 = tm * mesh->verts[mesh->faces[i].v[1]];
|
||||
Point3 p2 = tm * mesh->verts[mesh->faces[i].v[2]];
|
||||
Point3 Nrm = Normalize(CrossProd(p0 - p1, p0 - p2));
|
||||
n += Nrm;
|
||||
c ++;
|
||||
}
|
||||
}
|
||||
n /= (float)c;
|
||||
return Normalize(n);
|
||||
}
|
||||
|
||||
void AsciiExp::ExportNodeAnimMesh( INode* node )
|
||||
{
|
||||
INode *parent;
|
||||
Matrix3 parentTM, nodeTM, localTM;
|
||||
parent = node->GetParentNode();
|
||||
|
||||
TimeValue start = ip->GetAnimRange().Start();
|
||||
TimeValue end = ip->GetAnimRange().End();
|
||||
int delta = GetTicksPerFrame();
|
||||
TimeValue t;
|
||||
Matrix3 tm;
|
||||
Matrix3 StartM;
|
||||
AffineParts ap;
|
||||
int i;
|
||||
Quat q;
|
||||
Quat StartQ, StartU;
|
||||
Point3 StartP, StartS;
|
||||
|
||||
nodeTM = node->GetNodeTM(start);
|
||||
parentTM = parent->GetNodeTM(start);
|
||||
StartM = nodeTM*Inverse(parentTM);
|
||||
|
||||
for (t=start; t<=end; t+=delta)
|
||||
{
|
||||
nodeTM = node->GetNodeTM(t);
|
||||
parentTM = parent->GetNodeTM(t);
|
||||
tm = nodeTM*Inverse(parentTM);
|
||||
for (i=0;i<4;i++) {
|
||||
Point3 m0 = StartM.GetRow(i);
|
||||
Point3 m1 = tm.GetRow(i);
|
||||
if (fabs(m0.x-m1.x)>0.001 ||
|
||||
fabs(m0.y-m1.y)>0.001 ||
|
||||
fabs(m0.z-m1.z)>0.001)
|
||||
break;
|
||||
|
||||
}
|
||||
if (i!=4)
|
||||
break;
|
||||
}
|
||||
if (t==end)
|
||||
return;
|
||||
|
||||
char text[250];
|
||||
sprintf(text,"%s", node->GetName());
|
||||
|
||||
WriteChunkHdr( (char*)ANIM_ID, 0);
|
||||
fwrite( &CHANNEL_TYPE_NODE, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &nCurObj, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &totFrames, sizeof( Uint32 ), 1, expStream );
|
||||
for (t=start; t<=end; t+=delta) {
|
||||
// TRANSLATION
|
||||
tm = node->GetNodeTM(t) * Inverse(node->GetParentTM(t));
|
||||
decomp_affine(tm, &ap);
|
||||
|
||||
fwrite( &ap.t.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||||
fwrite( &ap.t.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||||
fwrite( &ap.t.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
|
||||
fwrite( &ap.q.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||||
fwrite( &ap.q.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||||
fwrite( &ap.q.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
fwrite( &ap.q.w, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
|
||||
fwrite( &ap.k.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||||
fwrite( &ap.k.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||||
fwrite( &ap.k.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
|
||||
fwrite( &ap.u.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||||
fwrite( &ap.u.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||||
fwrite( &ap.u.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
fwrite( &ap.u.w, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
}
|
||||
}
|
||||
|
||||
void AsciiExp::ExportVisTrack( INode* node )
|
||||
{
|
||||
Control *VisControl = node->GetVisController();
|
||||
if (VisControl) {
|
||||
float VisF;
|
||||
TimeValue start = ip->GetAnimRange().Start();
|
||||
TimeValue end = ip->GetAnimRange().End();
|
||||
int delta = GetTicksPerFrame();
|
||||
TimeValue t;
|
||||
WriteChunkHdr( (char*)VIS_ID, 0);
|
||||
fwrite( &nCurObj, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &totFrames, sizeof( Uint32 ), 1, expStream );
|
||||
for (t=start; t<=end; t+=delta) {
|
||||
Interval I = Interval(t, t);
|
||||
VisControl->GetValue(t, &VisF, I, CTRL_ABSOLUTE);
|
||||
fwrite( &VisF, sizeof(float), 1, expStream);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void AsciiExp::ExportAnimMesh( INode* node )
|
||||
{
|
||||
TimeValue start = ip->GetAnimRange().Start();
|
||||
TimeValue end = ip->GetAnimRange().End();
|
||||
int delta = GetTicksPerFrame();
|
||||
BOOL needDel;
|
||||
Mesh *mesh;
|
||||
TriObject *tri;
|
||||
TimeValue t;
|
||||
|
||||
WriteChunkHdr( (char*)ANIM_ID, 0);
|
||||
fwrite( &CHANNEL_TYPE_VERTEX, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &nCurObj, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &totFrames, sizeof( Uint32 ), 1, expStream );
|
||||
for (t=start; t<=end; t+=delta)
|
||||
{
|
||||
tri = GetTriObjectFromNode(node, t, needDel);
|
||||
if (!tri) return;
|
||||
mesh = &tri->mesh;
|
||||
Matrix3 tm = node->GetObjTMAfterWSM( t );
|
||||
for (int i=0; i<mesh->getNumVerts(); i++)
|
||||
{
|
||||
Point3 v1;
|
||||
Point3 v2;
|
||||
|
||||
v1 = mesh->verts[i];
|
||||
v2 = tm * v1;
|
||||
|
||||
fwrite( &v2.x, sizeof(float), 1, expStream );
|
||||
fwrite( &v2.z, sizeof(float), 1, expStream );
|
||||
fwrite( &v2.y, sizeof(float), 1, expStream );
|
||||
}
|
||||
if (needDel) tri->DeleteThis();
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================
|
||||
end */
|
536
Utils/GinExp/ExpTree.cpp
Normal file
536
Utils/GinExp/ExpTree.cpp
Normal file
|
@ -0,0 +1,536 @@
|
|||
#include "AsciiExp.h"
|
||||
|
||||
Matrix3 Uniform_Matrix(Matrix3 orig_cur_mat)
|
||||
{
|
||||
AffineParts parts;
|
||||
Matrix3 mat;
|
||||
|
||||
///Remove scaling from orig_cur_mat
|
||||
//1) Decompose original and get decomposition info
|
||||
decomp_affine(orig_cur_mat, &parts);
|
||||
|
||||
//2) construct 3x3 rotation from quaternion parts.q
|
||||
parts.q.MakeMatrix(mat);
|
||||
|
||||
//3) construct position row from translation parts.t
|
||||
mat.SetRow(3, parts.t);
|
||||
|
||||
return(mat);
|
||||
}
|
||||
|
||||
//GET_RELATIVE_MATRIX: RETURNS RELATIVE
|
||||
//MATRIX WITHOUT NON_UNIFORM SCALING
|
||||
Matrix3 Get_Relative_Matrix(INode *node, int t)
|
||||
{
|
||||
/* Note: This function removes the non-uniform scaling
|
||||
from MAX node transformations. before multiplying the
|
||||
current node by the inverse of its parent. The
|
||||
removal must be done on both nodes before the
|
||||
multiplication and Inverse are applied. This is especially
|
||||
useful for Biped export (which uses non-uniform scaling on
|
||||
its body parts.) */
|
||||
|
||||
INode *p_node = node->GetParentNode();
|
||||
|
||||
Matrix3 orig_cur_mat; // for current and parent
|
||||
Matrix3 orig_par_mat; // original matrices
|
||||
|
||||
Matrix3 cur_mat; // for current and parent
|
||||
Matrix3 par_mat; // decomposed matrices
|
||||
|
||||
//Get transformation matrices
|
||||
orig_cur_mat = node->GetNodeTM(t);
|
||||
if (p_node)
|
||||
{
|
||||
orig_par_mat = p_node->GetNodeTM(t);
|
||||
} else
|
||||
{
|
||||
orig_par_mat.IdentityMatrix();
|
||||
}
|
||||
|
||||
char Text[256];
|
||||
sprintf(Text, "%s", node->GetName());
|
||||
cur_mat = orig_cur_mat;
|
||||
par_mat = orig_par_mat;
|
||||
/* Control *c = node->GetTMController();
|
||||
if (c)
|
||||
{
|
||||
if ((c->ClassID() == BIPSLAVE_CONTROL_CLASS_ID) ||
|
||||
(c->ClassID() == BIPBODY_CONTROL_CLASS_ID) ||
|
||||
(c->ClassID() == FOOTPRINT_CLASS_ID))
|
||||
{
|
||||
//Decompose each matrix
|
||||
cur_mat = Uniform_Matrix(orig_cur_mat);
|
||||
}
|
||||
}
|
||||
if (p_node)
|
||||
{
|
||||
c = p_node->GetTMController();
|
||||
if (c)
|
||||
{
|
||||
if ((c->ClassID() == BIPSLAVE_CONTROL_CLASS_ID) ||
|
||||
(c->ClassID() == BIPBODY_CONTROL_CLASS_ID) ||
|
||||
(c->ClassID() == FOOTPRINT_CLASS_ID))
|
||||
{
|
||||
par_mat = Uniform_Matrix(orig_par_mat);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
//then return relative matrix in coordinate space of parent
|
||||
return(cur_mat * Inverse( par_mat));
|
||||
}
|
||||
|
||||
|
||||
void AsciiExp::ExportTree()
|
||||
{
|
||||
WriteChunkHdr( (char*)TREE_ID, 0);
|
||||
ExportTreeNodes(ip->GetRootNode());
|
||||
|
||||
WriteChunkHdr( (char*)ANIM_ID, 0);
|
||||
fwrite( &CHANNEL_TYPE_TREE, sizeof( Uint32 ), 1, expStream );
|
||||
// Change by Dave - Need frame count!!
|
||||
fwrite( &totFrames, sizeof( Uint32 ), 1, expStream );
|
||||
ExportTreeAnim(ip->GetRootNode());
|
||||
/*
|
||||
WriteChunkHdr( (char*)MOTION_ID, 0);
|
||||
fwrite( &totFrames, sizeof( Uint32 ), 1, expStream );
|
||||
ExportMotionAnim(ip->GetRootNode());
|
||||
*/
|
||||
WriteChunkHdr( (char*)KEY_ID, 0);
|
||||
fwrite( &CHANNEL_TYPE_TREE, sizeof( Uint32 ), 1, expStream );
|
||||
fwrite( &CHANNEL_INFO_ALL, sizeof( Uint32) , 1, expStream);
|
||||
ExportTreeKeyAnim(ip->GetRootNode());
|
||||
|
||||
ExportParticles();
|
||||
}
|
||||
|
||||
void AsciiExp::ExportParticles()
|
||||
{
|
||||
WriteChunkHdr( (char*)PART_ID, 0);
|
||||
fwrite(&NbEmmitters, sizeof(int), 1, expStream);
|
||||
NbEmmitters = 0;
|
||||
ExportParticleNodes(ip->GetRootNode());
|
||||
}
|
||||
|
||||
void AsciiExp::ExportParticleNodes( INode *node)
|
||||
{
|
||||
ObjectState os = node->EvalWorldState( ip->GetAnimRange().Start() );
|
||||
Object * obj = node->EvalWorldState(ip->GetAnimRange().Start()).obj;
|
||||
if (obj && obj->GetInterface(I_PARTICLEOBJ))
|
||||
{
|
||||
fwrite(&NbEmmitters, sizeof(int), 1, expStream);
|
||||
Control *VisControl = node->GetVisController();
|
||||
if (VisControl) {
|
||||
float VisF;
|
||||
TimeValue start = ip->GetAnimRange().Start();
|
||||
TimeValue end = ip->GetAnimRange().End();
|
||||
int delta = GetTicksPerFrame();
|
||||
TimeValue t;
|
||||
fwrite( &totFrames, sizeof( Uint32 ), 1, expStream );
|
||||
for (t=start; t<=end; t+=delta) {
|
||||
Interval I = Interval(t, t);
|
||||
VisControl->GetValue(t, &VisF, I, CTRL_ABSOLUTE);
|
||||
fwrite( &VisF, sizeof(float), 1, expStream);
|
||||
}
|
||||
} else
|
||||
{
|
||||
float VisF = 1.f;
|
||||
TimeValue start = ip->GetAnimRange().Start();
|
||||
TimeValue end = ip->GetAnimRange().End();
|
||||
int delta = GetTicksPerFrame();
|
||||
TimeValue t;
|
||||
fwrite( &totFrames, sizeof( Uint32 ), 1, expStream );
|
||||
for (t=start; t<=end; t+=delta) {
|
||||
fwrite( &VisF, sizeof(float), 1, expStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
NbEmmitters ++;
|
||||
int nbChilds = node->NumberOfChildren();
|
||||
fwrite( &nbChilds, sizeof(int), 1, expStream);
|
||||
for (int c=0;c<nbChilds;c++) // RUN THROUGH ALL OF THE CHILDREN
|
||||
{
|
||||
INode *ChildNode = node->GetChildNode(c);
|
||||
if (ChildNode) ExportParticleNodes( ChildNode );
|
||||
}
|
||||
}
|
||||
|
||||
void AsciiExp::ExportTreeNodes( INode * node )
|
||||
{
|
||||
INode * ChildNode;
|
||||
long nbChilds;
|
||||
Matrix3 tm;
|
||||
AffineParts ap;
|
||||
|
||||
char name[256];
|
||||
ObjectState os = node->EvalWorldState( ip->GetAnimRange().Start() );
|
||||
Object * obj = node->EvalWorldState(ip->GetAnimRange().Start()).obj;
|
||||
|
||||
if (obj && obj->GetInterface(I_PARTICLEOBJ))
|
||||
{
|
||||
NbEmmitters ++;
|
||||
}
|
||||
// EXPORT BONE
|
||||
sprintf( name, "%s", node->GetName() );
|
||||
fprintf( tempStream, "OUTPUTTING - %s\n", name ); // DEBUG FILE
|
||||
fwrite( &name, sizeof(char), MAX_NAME_LENGTH, expStream ); // WRITE BONE NAME
|
||||
|
||||
// BONE TRANSLATION
|
||||
/*Dave!! tm = node->GetNodeTM( ip->GetAnimRange().Start() ) * Inverse(node->GetParentTM(ip->GetAnimRange().Start()));*/
|
||||
tm = Get_Relative_Matrix(node , ip->GetAnimRange().Start());
|
||||
decomp_affine( tm, &ap );
|
||||
|
||||
fwrite( &ap.t.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||||
fwrite( &ap.t.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||||
fwrite( &ap.t.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
|
||||
fwrite( &ap.q.x, sizeof(float), 1, expStream ); // WRITE BONE ROT X-AXIS
|
||||
fwrite( &ap.q.z, sizeof(float), 1, expStream ); // WRITE BONE ROT Y-AXIS
|
||||
fwrite( &ap.q.y, sizeof(float), 1, expStream ); // WRITE BONE ROT Z-AXIS
|
||||
fwrite( &ap.q.w, sizeof(float), 1, expStream ); // WRITE BONE ROT W ANGLE
|
||||
|
||||
fwrite( &ap.k.x, sizeof(float), 1, expStream);
|
||||
fwrite( &ap.k.z, sizeof(float), 1, expStream);
|
||||
fwrite( &ap.k.y, sizeof(float), 1, expStream);
|
||||
|
||||
fwrite( &ap.u.x, sizeof(float), 1, expStream);
|
||||
fwrite( &ap.u.z, sizeof(float), 1, expStream);
|
||||
fwrite( &ap.u.y, sizeof(float), 1, expStream);
|
||||
fwrite( &ap.u.w, sizeof(float), 1, expStream);
|
||||
|
||||
Matrix3 m0(TRUE);
|
||||
Matrix3 m1(TRUE);
|
||||
Matrix3 m2(TRUE);
|
||||
Matrix3 m3(TRUE);
|
||||
Matrix3 m4(TRUE);
|
||||
|
||||
m0.SetTrans(ap.t);
|
||||
ap.q.MakeMatrix(m1);
|
||||
ap.u.MakeMatrix(m2);
|
||||
m3.Scale(ap.k);
|
||||
m4 = Inverse(m2);
|
||||
|
||||
Matrix3 j = m0 * m1 * m4 * m3 * m2;
|
||||
Matrix3 y = m2 * m3 * m4 * m1 * m0;
|
||||
|
||||
// EXPORT CHILDREN
|
||||
nbChilds = ValidateBoneKids( node );
|
||||
fwrite( &nbChilds, sizeof(long), 1, expStream ); // WRITE BONE CHILD COUNT
|
||||
|
||||
nbBones++;
|
||||
nbChilds = node->NumberOfChildren();
|
||||
for (int c=0;c<nbChilds;c++) // RUN THROUGH ALL OF THE CHILDREN
|
||||
{
|
||||
ChildNode = node->GetChildNode(c);
|
||||
if (ChildNode) ExportTreeNodes( ChildNode );
|
||||
}
|
||||
}
|
||||
/*
|
||||
void AsciiExp::ExportMotionAnim( INode* node)
|
||||
{
|
||||
TimeValue start = ip->GetAnimRange().Start();
|
||||
TimeValue end = ip->GetAnimRange().End();
|
||||
TimeValue t;
|
||||
int delta = GetTicksPerFrame();
|
||||
Matrix3 tm;
|
||||
AffineParts ap;
|
||||
INode * ChildNode;
|
||||
long nbChilds;
|
||||
Control *Cnt= node->GetTMController();
|
||||
|
||||
if (Cnt)
|
||||
if (Cnt->ClassID() == BIPBODY_CONTROL_CLASS_ID)
|
||||
for (t=start; t<=end; t+=delta)
|
||||
{
|
||||
// tm = node->GetNodeTM(t) * Inverse(node->GetParentTM(t));
|
||||
tm = node->GetNodeTM(t) ;
|
||||
decomp_affine(tm, &ap);
|
||||
|
||||
fwrite( &ap.t.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||||
fwrite( &ap.t.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||||
fwrite( &ap.t.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
}
|
||||
|
||||
nbChilds = node->NumberOfChildren();
|
||||
for (int c=0;c<nbChilds;c++) // RUN THROUGH ALL OF THE CHILDREN (Just cos Im lazy)
|
||||
{
|
||||
ChildNode = node->GetChildNode(c);
|
||||
if (ChildNode) ExportMotionAnim( ChildNode );
|
||||
}
|
||||
}
|
||||
*/
|
||||
void AsciiExp::ExportTreeAnim( INode* node )
|
||||
{
|
||||
TimeValue start = ip->GetAnimRange().Start();
|
||||
TimeValue end = ip->GetAnimRange().End();
|
||||
TimeValue t;
|
||||
int delta = GetTicksPerFrame();
|
||||
Matrix3 tm;
|
||||
AffineParts ap;
|
||||
Point3 prevPos;
|
||||
Point3 startScale;
|
||||
Quat prevQ;
|
||||
Quat scaleQ;
|
||||
Quat q;
|
||||
Quat InvQ;
|
||||
INode * ChildNode;
|
||||
ObjectState os = node->EvalWorldState( ip->GetAnimRange().Start() );
|
||||
Object * obj = node->EvalWorldState(ip->GetAnimRange().Start()).obj;
|
||||
long nbChilds;
|
||||
|
||||
char name[256];
|
||||
sprintf( name, "%s", node->GetName() );
|
||||
|
||||
for (t=start; t<=end; t+=delta)
|
||||
{
|
||||
// tm = node->GetNodeTM(t) * Inverse(node->GetParentTM(t));
|
||||
tm = Get_Relative_Matrix(node , t);
|
||||
decomp_affine(tm, &ap);
|
||||
|
||||
fwrite( &ap.t.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||||
fwrite( &ap.t.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||||
fwrite( &ap.t.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
|
||||
fwrite( &ap.q.x, sizeof(float), 1, expStream ); // WRITE BONE ROT X-AXIS
|
||||
fwrite( &ap.q.z, sizeof(float), 1, expStream ); // WRITE BONE ROT Y-AXIS
|
||||
fwrite( &ap.q.y, sizeof(float), 1, expStream ); // WRITE BONE ROT Z-AXIS
|
||||
fwrite( &ap.q.w, sizeof(float), 1, expStream ); // WRITE BONE ROT W ANGLE
|
||||
|
||||
fwrite( &ap.k.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||||
fwrite( &ap.k.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||||
fwrite( &ap.k.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
|
||||
fwrite( &ap.u.x, sizeof(float), 1, expStream ); // WRITE BONE ROT X-AXIS
|
||||
fwrite( &ap.u.z, sizeof(float), 1, expStream ); // WRITE BONE ROT Y-AXIS
|
||||
fwrite( &ap.u.y, sizeof(float), 1, expStream ); // WRITE BONE ROT Z-AXIS
|
||||
fwrite( &ap.u.w, sizeof(float), 1, expStream ); // WRITE BONE ROT W ANGLE
|
||||
}
|
||||
|
||||
nbChilds = node->NumberOfChildren();
|
||||
fwrite( &nbChilds, sizeof(int), 1, expStream);
|
||||
for (int c=0;c<nbChilds;c++) // RUN THROUGH ALL OF THE CHILDREN
|
||||
{
|
||||
ChildNode = node->GetChildNode(c);
|
||||
if (ChildNode) ExportTreeAnim( ChildNode );
|
||||
}
|
||||
}
|
||||
|
||||
void AsciiExp::ExportTreeKeyAnim( INode* node)
|
||||
{
|
||||
TimeValue start = ip->GetAnimRange().Start();
|
||||
TimeValue end = ip->GetAnimRange().End();
|
||||
int delta = GetTicksPerFrame();
|
||||
Matrix3 tm;
|
||||
AffineParts ap, StartAp;
|
||||
Point3 prevPos;
|
||||
Point3 startScale;
|
||||
Quat prevQ;
|
||||
Quat scaleQ;
|
||||
Quat q;
|
||||
Quat InvQ;
|
||||
INode * ChildNode;
|
||||
ObjectState os = node->EvalWorldState( ip->GetAnimRange().Start() );
|
||||
Object * obj = node->EvalWorldState(ip->GetAnimRange().Start()).obj;
|
||||
long nbChilds;
|
||||
|
||||
int num;
|
||||
int i;
|
||||
int FrameN;
|
||||
Interval ivalid;
|
||||
IKey k;
|
||||
Control *c;
|
||||
IKeyControl *ikeys;
|
||||
ITCBPoint3Key tcbPosKey;
|
||||
ITCBRotKey tcbRotKey;
|
||||
ITCBScaleKey tcbSclKey;
|
||||
IBezPoint3Key bezPosKey;
|
||||
IBezQuatKey bezRotKey;
|
||||
IBezScaleKey bezSclKey;
|
||||
ILinPoint3Key linPosKey;
|
||||
ILinRotKey linRotKey;
|
||||
ILinScaleKey linSclKey;
|
||||
TimeValue time;
|
||||
|
||||
|
||||
TSTR Name = node->GetName();
|
||||
TimeList tl;
|
||||
tl.Clear();
|
||||
INode *KeyNode = node;
|
||||
c = KeyNode->GetTMController();
|
||||
if (c) {
|
||||
|
||||
if ((c->ClassID() == BIPSLAVE_CONTROL_CLASS_ID) ||
|
||||
(c->ClassID() == BIPBODY_CONTROL_CLASS_ID) ||
|
||||
(c->ClassID() == FOOTPRINT_CLASS_ID))
|
||||
{
|
||||
for (i=0; i<c->NumSubs(); i++)
|
||||
{
|
||||
Animatable *a = c->SubAnim(i);
|
||||
int k = a->NumKeys();
|
||||
for (int j=0; j<k; j++)
|
||||
{
|
||||
time = a->GetKeyTime(j);
|
||||
if (time > start && time < end)
|
||||
tl.Add( time );
|
||||
}
|
||||
}
|
||||
int k = c->NumKeys();
|
||||
for (int j=0; j<k; j++)
|
||||
{
|
||||
time = c->GetKeyTime(j);
|
||||
if (time > start && time < end)
|
||||
tl.Add( time );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
c = c->GetPositionController();
|
||||
if (c) {
|
||||
ikeys = GetKeyControlInterface(c);
|
||||
if (ikeys) {
|
||||
|
||||
num = ikeys->GetNumKeys();
|
||||
if (num >0)
|
||||
{
|
||||
for (i = 0; i<num; i++) {
|
||||
if (c->ClassID() == Class_ID(TCBINTERP_POSITION_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(i, &tcbPosKey);
|
||||
time = tcbPosKey.time;
|
||||
} else
|
||||
if (c->ClassID() == Class_ID(HYBRIDINTERP_POSITION_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(i, &bezPosKey);
|
||||
time = bezPosKey.time;
|
||||
} else
|
||||
if (c->ClassID() == Class_ID(LININTERP_POSITION_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(i, &linPosKey);
|
||||
time = linPosKey.time;
|
||||
}
|
||||
if (time > start && time < end)
|
||||
tl.Add(time);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
c = KeyNode->GetTMController();
|
||||
if (c) {
|
||||
c = c->GetRotationController();
|
||||
if (c) {
|
||||
ikeys = GetKeyControlInterface(c);
|
||||
if (ikeys) {
|
||||
|
||||
num = ikeys->GetNumKeys();
|
||||
if (num >0)
|
||||
{
|
||||
for (i = 0; i<num; i++) {
|
||||
if (c->ClassID() == Class_ID(TCBINTERP_ROTATION_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(i, &tcbRotKey);
|
||||
int rots;
|
||||
if (i)
|
||||
{
|
||||
ITCBRotKey oldtcbRotKey;
|
||||
ikeys->GetKey(i-1, &oldtcbRotKey);
|
||||
rots = fabs(tcbRotKey.val.angle - oldtcbRotKey.val.angle) / (0.6667 * PI) + 1;
|
||||
for (int k=1; k<rots; k++)
|
||||
{
|
||||
tl.Add(oldtcbRotKey.time+(int)((float)k*(tcbRotKey.time-oldtcbRotKey.time)/rots));
|
||||
}
|
||||
}
|
||||
time = tcbRotKey.time;
|
||||
} else
|
||||
if (c->ClassID() == Class_ID(HYBRIDINTERP_ROTATION_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(i, &bezRotKey);
|
||||
time = bezRotKey.time;
|
||||
} else
|
||||
if (c->ClassID() == Class_ID(LININTERP_ROTATION_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(i, &linRotKey);
|
||||
time = linRotKey.time;
|
||||
}
|
||||
if (time > start && time < end)
|
||||
tl.Add(time);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
c = KeyNode->GetTMController();
|
||||
if (c) {
|
||||
c = c->GetScaleController();
|
||||
if (c) {
|
||||
ikeys = GetKeyControlInterface(c);
|
||||
if (ikeys) {
|
||||
|
||||
num = ikeys->GetNumKeys();
|
||||
if (num >0)
|
||||
{
|
||||
for (i = 0; i<num; i++) {
|
||||
if (c->ClassID() == Class_ID(TCBINTERP_SCALE_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(i, &tcbSclKey);
|
||||
time = tcbSclKey.time;
|
||||
} else
|
||||
if (c->ClassID() == Class_ID(HYBRIDINTERP_SCALE_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(i, &bezSclKey);
|
||||
time = bezSclKey.time;
|
||||
} else
|
||||
if (c->ClassID() == Class_ID(LININTERP_SCALE_CLASS_ID, 0)) {
|
||||
ikeys->GetKey(i, &linSclKey);
|
||||
time = linSclKey.time;
|
||||
}
|
||||
|
||||
if (time > start && time < end)
|
||||
tl.Add(time);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tl.Count())
|
||||
{
|
||||
tl.Add(start);
|
||||
tl.Add(end);
|
||||
}
|
||||
num = tl.Count();
|
||||
fwrite( &num, sizeof( Uint32 ), 1, expStream );
|
||||
|
||||
for (num = 0; num <tl.Count(); num++) {
|
||||
time = tl.Get(num);
|
||||
// tm = node->GetNodeTM(time) * Inverse(node->GetParentTM(time));
|
||||
tm = Get_Relative_Matrix(node , time);
|
||||
|
||||
FrameN = (int)((float)(time - start) / delta);
|
||||
|
||||
decomp_affine(tm, &ap);
|
||||
if (num == 0)
|
||||
StartAp = ap;
|
||||
|
||||
fwrite( &FrameN, sizeof(Uint32), 1, expStream);
|
||||
fwrite( &ap.t.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||||
fwrite( &ap.t.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||||
fwrite( &ap.t.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
|
||||
fwrite( &ap.q.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||||
fwrite( &ap.q.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||||
fwrite( &ap.q.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
fwrite( &ap.q.w, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
|
||||
fwrite( &ap.k.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||||
fwrite( &ap.k.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||||
fwrite( &ap.k.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
|
||||
fwrite( &ap.u.x, sizeof(float), 1, expStream ); // WRITE BONE X-POS
|
||||
fwrite( &ap.u.z, sizeof(float), 1, expStream ); // WRITE BONE Y-POS
|
||||
fwrite( &ap.u.y, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
fwrite( &ap.u.w, sizeof(float), 1, expStream ); // WRITE BONE Z-POS
|
||||
}
|
||||
|
||||
CurBone++;
|
||||
nbChilds = node->NumberOfChildren();
|
||||
fwrite( &nbChilds, sizeof(int), 1, expStream);
|
||||
for (int cn=0;cn<nbChilds;cn++) // RUN THROUGH ALL OF THE CHILDREN
|
||||
{
|
||||
ChildNode = node->GetChildNode(cn);
|
||||
if (ChildNode) ExportTreeKeyAnim( ChildNode);
|
||||
}
|
||||
}
|
||||
|
96
Utils/GinExp/ExpUProp.cpp
Normal file
96
Utils/GinExp/ExpUProp.cpp
Normal file
|
@ -0,0 +1,96 @@
|
|||
/*=========================================================================
|
||||
|
||||
EXPUPROP.CPP
|
||||
|
||||
Author: Dave
|
||||
Created:
|
||||
Project:
|
||||
Purpose:
|
||||
|
||||
Copyright (c) 1998 Climax Development Ltd
|
||||
|
||||
===========================================================================*/
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Includes
|
||||
-------- */
|
||||
|
||||
#include "AsciiExp.h"
|
||||
|
||||
|
||||
/* Std Lib
|
||||
------- */
|
||||
|
||||
/* Glib
|
||||
---- */
|
||||
|
||||
/* Local
|
||||
----- */
|
||||
|
||||
/* Graphics
|
||||
-------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Tyepdefs && Defines
|
||||
------------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Structure defintions
|
||||
-------------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Positional Vars
|
||||
--------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function Prototypes
|
||||
------------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Vars
|
||||
---- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Data
|
||||
---- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
const char UPROP_ID[] = MAKE_LONG( 'P', 'R', 'O', 'P' );
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
void AsciiExp::ExportProp( INode* node )
|
||||
{
|
||||
ObjectState os;
|
||||
Object * obj;
|
||||
TSTR UPBuffer;
|
||||
Uint32 Len;
|
||||
Uint32 ModNum=nCurNode;
|
||||
char *TxtPtr;
|
||||
|
||||
os = node->EvalWorldState( ip->GetAnimRange().Start() );
|
||||
obj = node->EvalWorldState( ip->GetAnimRange().Start() ).obj;
|
||||
|
||||
if (!os.obj) return;
|
||||
// if (!obj->IsRenderable()) return;
|
||||
if (node->IsNodeHidden()) return;
|
||||
// if (!obj || os.obj->SuperClassID() != GEOMOBJECT_CLASS_ID) return; // Safety net. This shouldn't happen.
|
||||
|
||||
node->GetUserPropBuffer(UPBuffer);
|
||||
Len=UPBuffer.Length();//strlen(UPBuffer);
|
||||
Len=(Len+3)&0xfffc;
|
||||
TxtPtr=UPBuffer.data();
|
||||
WriteChunkHdr( (char*)UPROP_ID, 0 );
|
||||
fwrite( &ModNum, sizeof(Uint32), 1, expStream );
|
||||
fwrite( &Len, sizeof(Uint32), 1, expStream );
|
||||
fwrite( TxtPtr, sizeof(char), Len, expStream );
|
||||
}
|
958
Utils/GinExp/Triobjed.h
Normal file
958
Utils/GinExp/Triobjed.h
Normal file
|
@ -0,0 +1,958 @@
|
|||
/**********************************************************************
|
||||
*<
|
||||
FILE: triobjed.h
|
||||
|
||||
DESCRIPTION: Editable Triangle Mesh Object
|
||||
|
||||
CREATED BY: Rolf Berteig
|
||||
|
||||
HISTORY: created 4 March 1996
|
||||
|
||||
*> Copyright (c) 1996, All Rights Reserved.
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef __TRIOBJED__
|
||||
#define __TRIOBJED__
|
||||
|
||||
#include "meshadj.h"
|
||||
typedef Tab<Point3> Point3Tab;
|
||||
|
||||
#ifdef _SUBMTLASSIGNMENT
|
||||
#include "sbmtlapi.h"
|
||||
#endif
|
||||
|
||||
// Selection levels
|
||||
#define SL_OBJECT 0
|
||||
#define SL_VERTEX 1
|
||||
#define SL_FACE 2
|
||||
#define SL_EDGE 3
|
||||
|
||||
#define ALIGN_CONST 0
|
||||
#define ALIGN_VIEW 1
|
||||
|
||||
#define DEF_PICKBOX_SIZE 4
|
||||
|
||||
class WeldVertCMode;
|
||||
class CreateVertCMode;
|
||||
class BuildFaceCMode;
|
||||
class DivideEdgeCMode;
|
||||
class TurnEdgeCMode;
|
||||
class AttachPickMode;
|
||||
class ExtrudeCMode;
|
||||
class AlignFaceCMode;
|
||||
class FlipNormCMode;
|
||||
class CutEdgeCMode; // SCA
|
||||
|
||||
#define CID_CREATEVERT CID_USER + 973
|
||||
#define CID_BUILDFACE CID_USER + 975
|
||||
#define CID_WELDVERT CID_USER + 978
|
||||
#define CID_DIVIDEEDGE CID_USER + 979
|
||||
#define CID_TURNEDGE CID_USER + 980
|
||||
#define CID_EXTRUDE CID_USER + 990
|
||||
#define CID_ALIGNFACE CID_USER + 1000
|
||||
#define CID_FLIPNORM CID_USER + 1010
|
||||
#define CID_CUTEDGE CID_USER + 1020 // SCA
|
||||
|
||||
#define SELTYPE_SINGLE 1
|
||||
#define SELTYPE_POLY 2
|
||||
#define SELTYPE_ELEMENT 3
|
||||
|
||||
#define IDC_SELSINGLE 0x4010
|
||||
#define IDC_SELPOLY 0x4011
|
||||
#define IDC_SELELEMENT 0x4012
|
||||
|
||||
#define MAX_MATID 0xffff
|
||||
|
||||
class NamedSelSetList {
|
||||
public:
|
||||
Tab<BitArray*> sets;
|
||||
Tab<TSTR*> names;
|
||||
|
||||
~NamedSelSetList();
|
||||
BitArray &operator[](int i) {return *sets[i];}
|
||||
int Count() {return sets.Count();}
|
||||
void AppendSet(BitArray &nset,TSTR &name);
|
||||
void DeleteSet(int i);
|
||||
IOResult Load(ILoad *iload);
|
||||
IOResult Save(ISave *isave);
|
||||
void SetSize(int size);
|
||||
NamedSelSetList& operator=(NamedSelSetList& from);
|
||||
void DeleteSetElements(BitArray &set,int m=1);
|
||||
int FindSet(TSTR &name);
|
||||
};
|
||||
|
||||
#ifdef _SUBMTLASSIGNMENT
|
||||
class EditTriObject : public TriObject, public EventUser, public ISubMtlAPI {
|
||||
#else
|
||||
class EditTriObject : public TriObject, public EventUser {
|
||||
#endif
|
||||
public:
|
||||
|
||||
// Class vars
|
||||
static HWND hParams1;
|
||||
static HWND hParams2;
|
||||
static HACCEL hAccel;
|
||||
static Interface *ip;
|
||||
static MoveModBoxCMode *moveMode;
|
||||
static RotateModBoxCMode *rotMode;
|
||||
static UScaleModBoxCMode *uscaleMode;
|
||||
static NUScaleModBoxCMode *nuscaleMode;
|
||||
static SquashModBoxCMode *squashMode;
|
||||
static SelectModBoxCMode *selectMode;
|
||||
static WeldVertCMode *weldVertMode;
|
||||
static CreateVertCMode *createVertMode;
|
||||
static BuildFaceCMode* buildFaceMode;
|
||||
static TurnEdgeCMode* turnEdgeMode;
|
||||
static DivideEdgeCMode* divideEdgeMode;
|
||||
static AttachPickMode* attachPickMode;
|
||||
static ExtrudeCMode* extrudeMode;
|
||||
static AlignFaceCMode* alignFaceMode;
|
||||
static FlipNormCMode* flipMode;
|
||||
static CutEdgeCMode * cutEdgeMode; // SCA
|
||||
static float falloff, pinch, bubble;
|
||||
static int selType;
|
||||
static float normScale;
|
||||
static BOOL selByVert;
|
||||
static BOOL inBuildFace;
|
||||
static BOOL faceUIValid;
|
||||
static BOOL inNormalMove;
|
||||
static BOOL ignoreBackfaces, ignoreBackedges;
|
||||
static BOOL ignoreVisEdge;
|
||||
static int pickBoxSize;
|
||||
static int weldBoxSize;
|
||||
static int attachMat;
|
||||
static BOOL condenseMat;
|
||||
static bool sliceSplit, cutQuadSafe, cutRefine;
|
||||
static Quat sliceRot;
|
||||
static Point3 sliceCenter;
|
||||
static float sliceSize;
|
||||
static bool sliceMode;
|
||||
|
||||
// Cache for computing coord. systems
|
||||
static FaceClusterList *clust;
|
||||
static Point3Tab *centers;
|
||||
static Point3Tab *normals;
|
||||
static DWORDTab *vclust;
|
||||
static Tab<float> *distTab;
|
||||
Point3Tab &CoordCenters();
|
||||
Point3Tab &CoordNormals();
|
||||
DWORDTab &VertClusters();
|
||||
Tab<float> *EdgeDistTab(int iterations);
|
||||
void FreeDistTab();
|
||||
void FreeCoordCaches();
|
||||
void MakeClusterList();
|
||||
void InvalidateCoordCaches(BOOL selChange=FALSE);
|
||||
|
||||
NamedSelSetList vselSet;
|
||||
NamedSelSetList fselSet;
|
||||
NamedSelSetList eselSet;
|
||||
Tab<Control*> cont;
|
||||
|
||||
EditTriObject();
|
||||
|
||||
// Animatable methods
|
||||
void DeleteThis() {delete this;}
|
||||
Class_ID ClassID() {return Class_ID(EDITTRIOBJ_CLASS_ID,0);}
|
||||
void GetClassName(TSTR& s) ;//{s = GetString(IDS_RB_EDITABLEMESH);}
|
||||
void BeginEditParams(IObjParam *ip, ULONG flags,Animatable *prev);
|
||||
void EndEditParams(IObjParam *ip, ULONG flags,Animatable *next);
|
||||
int NumSubs() {return cont.Count();}
|
||||
Animatable* SubAnim(int i);
|
||||
TSTR SubAnimName(int i);
|
||||
BOOL AssignController(Animatable *control,int subAnim);
|
||||
int SubNumToRefNum(int subNum) {return subNum;}
|
||||
BOOL SelectSubAnim(int subNum);
|
||||
|
||||
// Reference methods
|
||||
int NumRefs() {return cont.Count();}
|
||||
RefTargetHandle GetReference(int i);
|
||||
void SetReference(int i, RefTargetHandle rtarg);
|
||||
void CreateContArray();
|
||||
void SynchContArray();
|
||||
//BOOL BypassTreeView();
|
||||
void DeletePointConts(BitArray &set);
|
||||
void PlugControllersSel(TimeValue t,BitArray &set);
|
||||
BOOL PlugControl(TimeValue t,int i);
|
||||
void SetPointAnim(TimeValue t, int i, Point3 pt);
|
||||
BOOL CloneVertCont(int from, int to);
|
||||
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message);
|
||||
|
||||
// BaseObject methods
|
||||
ObjectState Eval(TimeValue time);
|
||||
void Transform(TimeValue t, Matrix3& partm, Matrix3 tmAxis, BOOL localOrigin, Matrix3 xfrm, BOOL ar, int type);
|
||||
void Move(TimeValue t, Matrix3& partm, Matrix3& tmAxis, Point3& val, BOOL localOrigin=FALSE);
|
||||
void Rotate(TimeValue t, Matrix3& partm, Matrix3& tmAxis, Quat& val, BOOL localOrigin=FALSE);
|
||||
void Scale(TimeValue t, Matrix3& partm, Matrix3& tmAxis, Point3& val, BOOL localOrigin=FALSE);
|
||||
void TransformStart(TimeValue t) {if (ip) ip->LockAxisTripods(TRUE);}
|
||||
void TransformFinish(TimeValue t) {if (ip) ip->LockAxisTripods(FALSE); InvalidateCoordCaches(); FreeDistTab();}
|
||||
void TransformCancel(TimeValue t) {if (ip) ip->LockAxisTripods(FALSE); FreeDistTab();}
|
||||
int Display(TimeValue t, INode* inode, ViewExp *vpt, int flags);
|
||||
void GetWorldBoundBox (TimeValue t, INode * inode, ViewExp* vp, Box3& box);
|
||||
void GetLocalBoundBox (TimeValue t, INode* inode, ViewExp* vp, Box3& box);
|
||||
int HitTest(TimeValue t, INode* inode, int type, int crossing, int flags, IPoint2 *p, ViewExp *vpt, ModContext* mc);
|
||||
void CloneSelSubComponents(TimeValue t);
|
||||
void AcceptCloneSelSubComponents(TimeValue t);
|
||||
void SelectSubComponent(
|
||||
HitRecord *hitRec, BOOL selected, BOOL all, BOOL invert=FALSE);
|
||||
void ClearSelection(int selLevel);
|
||||
void SelectAll(int selLevel);
|
||||
void InvertSelection(int selLevel);
|
||||
void ActivateSubobjSel(int level, XFormModes& modes );
|
||||
void GetSubObjectCenters(SubObjAxisCallback *cb,TimeValue t,INode *node,ModContext *mc);
|
||||
void GetSubObjectTMs(SubObjAxisCallback *cb,TimeValue t,INode *node,ModContext *mc);
|
||||
|
||||
// Object methods
|
||||
TCHAR *GetObjectName() ;//{ return GetString(IDS_RB_EDITABLEMESH);}
|
||||
BOOL IsSubClassOf(Class_ID classID);
|
||||
|
||||
BOOL SupportsNamedSubSels() {return TRUE;}
|
||||
void ActivateSubSelSet(TSTR &setName);
|
||||
void NewSetFromCurSel(TSTR &setName);
|
||||
void RemoveSubSelSet(TSTR &setName);
|
||||
void SetupNamedSelDropDown();
|
||||
int NumNamedSelSets();
|
||||
TSTR GetNamedSelSetName(int i);
|
||||
void SetNamedSelSetName(int i,TSTR &newName);
|
||||
void NewSetByOperator(TSTR &newName,Tab<int> &sets,int op);
|
||||
|
||||
// Reference methods
|
||||
RefTargetHandle Clone(RemapDir& remap = NoRemap());
|
||||
IOResult Load(ILoad *iload);
|
||||
IOResult Save(ISave *isave);
|
||||
|
||||
// From EventUser
|
||||
void Notify() {DeleteSelected();/*delete key was pressed*/}
|
||||
|
||||
// Local methods
|
||||
void VertsHaveBeenDeleted(BitArray &set);
|
||||
NamedSelSetList &GetSelSet();
|
||||
void KeyboardAccelerator(int id);
|
||||
void RemoveRollupPages();
|
||||
void SetRollupPages();
|
||||
int GetSubobjectLevel();
|
||||
void SetSubobjectLevel(int level);
|
||||
void SetSelType(int type);
|
||||
void HoldVerts();
|
||||
void HoldTopology();
|
||||
void DeleteSelected();
|
||||
Point3 CalcRegionAffect(Point3 v,Point3 center,Point3 delta);
|
||||
Point3 CalcRegionAffect(float dist,Point3 delta);
|
||||
void DeleteVertSet(BitArray set);
|
||||
void DeleteFaceSet(BitArray set, BitArray *isoVert);
|
||||
void HideSelectedVerts();
|
||||
void UnhideAllVerts();
|
||||
void HideSelectedFaces();
|
||||
void UnhideAllFaces();
|
||||
BOOL WeldSelectedVerts(float thresh);
|
||||
void WeldSelectedVerts(Point3 pt);
|
||||
void CollapseSelectedVerts();
|
||||
void CollapseSelFaces();
|
||||
void CollapseSelEdges();
|
||||
void WeldVertSet(BitArray set,Point3 *weldPoint=NULL);
|
||||
void AddNewVertex(Point3 pt);
|
||||
void BuildNewFace(int *v);
|
||||
void MakePlanar();
|
||||
float GetPolyFaceThesh();
|
||||
HitRecord *VertHitsToFaceHits(HitRecord *hitRec,BOOL all);
|
||||
DWORD GetSelSmoothBits(DWORD &invalid);
|
||||
void SetSelSmoothBits(DWORD bits,DWORD which);
|
||||
void SelectBySmoothGroup(DWORD bits,BOOL clear);
|
||||
void AutoSmooth(float thresh);
|
||||
DWORD GetUsedSmoothBits();
|
||||
int GetSelMatIndex();
|
||||
void SetSelMatIndex(int index);
|
||||
void SelectByMat(int index,BOOL clear);
|
||||
void InvalidateSurfaceUI();
|
||||
void FlipSelNormals();
|
||||
void FlipANormal(int ix);
|
||||
void UnifySelNormals();
|
||||
void DetachVertFaces(TSTR &name,BOOL doFaces,BOOL del=TRUE,BOOL elem=FALSE);
|
||||
void ShowNormals();
|
||||
void SetSelEdgeVis(BOOL onOff);
|
||||
void AutoEdge(float angle);
|
||||
void AttachObject(INode *node);
|
||||
void MultiAttachObject(INodeTab &nodeTab);
|
||||
void TesselateFaces(float tens,BOOL edge);
|
||||
void ExplodeFaces(float thresh, BOOL objs, TSTR &name);
|
||||
void DoExtrude();
|
||||
void StartExtrudeMode();
|
||||
void BeginNormalMove(TimeValue t);
|
||||
void EndNormalMove(TimeValue t,BOOL accept);
|
||||
void NormalMove(TimeValue t, float amount);
|
||||
void CloneSelVerts();
|
||||
void CloneSelFaces(BitArray &set);
|
||||
void BreakVerts();
|
||||
void RemoveIsoVerts();
|
||||
void AlignVertsTo(int which);
|
||||
void AlignFacesTo(int which,DWORD f);
|
||||
Matrix3 ComputeAlignTM(int which, float &zcent);
|
||||
void SetEdgeVisCheckState();
|
||||
void NSCopy();
|
||||
void NSPaste();
|
||||
BOOL GetUniqueSetName(TSTR &name);
|
||||
int SelectNamedSet();
|
||||
void SelectByNormal(BOOL front);
|
||||
void SetNumSelLabel();
|
||||
Color GetSelVertColor();
|
||||
void SetSelVertColor(Color c);
|
||||
void SelectVertByColor(Point3 selcol,int selDeltaR,int selDeltaG,int selDeltaB,BOOL add,BOOL sub);
|
||||
BOOL AllocateVertColor();
|
||||
BOOL SplitSharedVertCol();
|
||||
void CreateCurveFromEdge(TSTR name,int curveType,BOOL ignoreHiddenEdges);
|
||||
void SelectOpenEdges();
|
||||
BOOL DoAttachMatOptionDialog();
|
||||
int DoCut (Point3 & viewNorm, DWORD e1, float prop1, DWORD e2, float prop2); // SCA
|
||||
void Slice ();
|
||||
void EnterSliceMode (HWND hwnd);
|
||||
void ExitSliceMode (HWND hwnd);
|
||||
|
||||
#ifdef _SUBMTLASSIGNMENT
|
||||
void* GetInterface(ULONG id);
|
||||
MtlID GetNextAvailMtlID();
|
||||
BOOL HasFaceSelection();
|
||||
void SetSelFaceMtlID(MtlID id, BOOL bResetUnsel = FALSE);
|
||||
int GetSelFaceUniqueMtlID();
|
||||
int GetSelFaceAnyMtlID();
|
||||
int GetMaxMtlID();
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
// --- Command Modes -----------------------------------------------
|
||||
|
||||
class ExtrudeMouseProc : public MouseCallBack {
|
||||
private:
|
||||
MoveTransformer moveTrans;
|
||||
EditTriObject *eo;
|
||||
Interface *ip;
|
||||
IPoint2 om;
|
||||
|
||||
public:
|
||||
ExtrudeMouseProc(EditTriObject* o, IObjParam *i)
|
||||
: moveTrans(i) {eo=o;ip=i;}
|
||||
int proc(
|
||||
HWND hwnd,
|
||||
int msg,
|
||||
int point,
|
||||
int flags,
|
||||
IPoint2 m );
|
||||
};
|
||||
|
||||
class ExtrudeSelectionProcessor : public GenModSelectionProcessor {
|
||||
protected:
|
||||
HCURSOR GetTransformCursor();
|
||||
|
||||
public:
|
||||
ExtrudeSelectionProcessor(ExtrudeMouseProc *mc, EditTriObject *o, IObjParam *i)
|
||||
: GenModSelectionProcessor(mc,o,i) {}
|
||||
};
|
||||
|
||||
class ExtrudeCMode : public CommandMode {
|
||||
private:
|
||||
ChangeFGObject fgProc;
|
||||
ExtrudeSelectionProcessor mouseProc;
|
||||
ExtrudeMouseProc eproc;
|
||||
EditTriObject* eo;
|
||||
|
||||
public:
|
||||
ExtrudeCMode(EditTriObject* o, IObjParam *i) :
|
||||
fgProc(o), mouseProc(&eproc,o,i), eproc(o,i) {eo=o;}
|
||||
|
||||
int Class() { return MODIFY_COMMAND; }
|
||||
int ID() { return CID_EXTRUDE; }
|
||||
MouseCallBack *MouseProc(int *numPoints) { *numPoints=2; return &mouseProc; }
|
||||
ChangeForegroundCallback *ChangeFGProc() { return &fgProc; }
|
||||
BOOL ChangeFG( CommandMode *oldMode ) { return oldMode->ChangeFGProc() != &fgProc; }
|
||||
void EnterMode();
|
||||
void ExitMode();
|
||||
};
|
||||
|
||||
|
||||
|
||||
class AttachPickMode :
|
||||
public PickModeCallback,
|
||||
public PickNodeCallback {
|
||||
public:
|
||||
EditTriObject* eo;
|
||||
IObjParam *ip;
|
||||
|
||||
AttachPickMode(EditTriObject* o, IObjParam *i)
|
||||
{eo=o;ip=i;}
|
||||
BOOL HitTest(IObjParam *ip,HWND hWnd,ViewExp *vpt,IPoint2 m,int flags);
|
||||
BOOL Pick(IObjParam *ip,ViewExp *vpt);
|
||||
void EnterMode(IObjParam *ip);
|
||||
void ExitMode(IObjParam *ip);
|
||||
|
||||
BOOL Filter(INode *node);
|
||||
BOOL RightClick(IObjParam *ip,ViewExp *vpt) {return TRUE;}
|
||||
PickNodeCallback *GetFilter() {return this;}
|
||||
};
|
||||
|
||||
|
||||
class WeldVertMouseProc : public MoveModBox {
|
||||
private:
|
||||
EditTriObject *et;
|
||||
IObjParam *ip;
|
||||
|
||||
public:
|
||||
WeldVertMouseProc(EditTriObject* e, IObjParam *i)
|
||||
: MoveModBox(e,i) {et=e;ip=i;}
|
||||
BOOL HitTestVerts(IPoint2 &m, ViewExp *vpt,int &v);
|
||||
int proc(
|
||||
HWND hwnd,
|
||||
int msg,
|
||||
int point,
|
||||
int flags,
|
||||
IPoint2 m );
|
||||
};
|
||||
|
||||
class WeldVertSelectionProcessor : public GenModSelectionProcessor {
|
||||
protected:
|
||||
HCURSOR GetTransformCursor();
|
||||
|
||||
public:
|
||||
WeldVertSelectionProcessor(WeldVertMouseProc *mc, Object *o, IObjParam *i)
|
||||
: GenModSelectionProcessor(mc,o,i) {}
|
||||
};
|
||||
|
||||
class WeldVertCMode : public CommandMode {
|
||||
private:
|
||||
ChangeFGObject fgProc;
|
||||
WeldVertSelectionProcessor mouseProc;
|
||||
WeldVertMouseProc eproc;
|
||||
EditTriObject* et;
|
||||
|
||||
public:
|
||||
WeldVertCMode(EditTriObject* mod, IObjParam *i) :
|
||||
fgProc(mod), mouseProc(&eproc,mod,i), eproc(mod,i) {et=mod;}
|
||||
|
||||
int Class() { return MODIFY_COMMAND; }
|
||||
int ID() { return CID_WELDVERT; }
|
||||
MouseCallBack *MouseProc(int *numPoints) {*numPoints=2; return &mouseProc;}
|
||||
ChangeForegroundCallback *ChangeFGProc() {return &fgProc; }
|
||||
BOOL ChangeFG( CommandMode *oldMode ) {return oldMode->ChangeFGProc() != &fgProc;}
|
||||
void EnterMode();
|
||||
void ExitMode();
|
||||
};
|
||||
|
||||
|
||||
class CreateVertMouseProc : public MouseCallBack {
|
||||
private:
|
||||
EditTriObject *et;
|
||||
IObjParam *ip;
|
||||
|
||||
public:
|
||||
CreateVertMouseProc(EditTriObject* mod, IObjParam *i)
|
||||
{et=mod;ip=i;}
|
||||
int proc(
|
||||
HWND hwnd,
|
||||
int msg,
|
||||
int point,
|
||||
int flags,
|
||||
IPoint2 m );
|
||||
};
|
||||
|
||||
class CreateVertCMode : public CommandMode {
|
||||
private:
|
||||
ChangeFGObject fgProc;
|
||||
CreateVertMouseProc proc;
|
||||
EditTriObject* et;
|
||||
|
||||
public:
|
||||
CreateVertCMode(EditTriObject* mod, IObjParam *i)
|
||||
: fgProc(mod), proc(mod,i) {et=mod;}
|
||||
|
||||
int Class() { return MODIFY_COMMAND; }
|
||||
int ID() { return CID_CREATEVERT; }
|
||||
MouseCallBack *MouseProc(int *numPoints) {*numPoints=1; return &proc;}
|
||||
ChangeForegroundCallback *ChangeFGProc() {return &fgProc;}
|
||||
BOOL ChangeFG(CommandMode *oldMode) {return oldMode->ChangeFGProc()!= &fgProc;}
|
||||
void EnterMode();
|
||||
void ExitMode();
|
||||
};
|
||||
|
||||
|
||||
class BuildFaceMouseProc : public MouseCallBack {
|
||||
private:
|
||||
EditTriObject *et;
|
||||
IObjParam *ip;
|
||||
int vts[3];
|
||||
IPoint3 mpts[3];
|
||||
int pt;
|
||||
IPoint2 lm;
|
||||
|
||||
public:
|
||||
BuildFaceMouseProc(EditTriObject* e, IObjParam *i);
|
||||
void DrawFace(HWND hWnd,IPoint2 &m);
|
||||
BOOL HitTestVerts(IPoint2 &m, ViewExp *vpt,int &v);
|
||||
int proc(
|
||||
HWND hwnd,
|
||||
int msg,
|
||||
int point,
|
||||
int flags,
|
||||
IPoint2 m );
|
||||
};
|
||||
|
||||
class BuildFaceCMode : public CommandMode {
|
||||
private:
|
||||
ChangeFGObject fgProc;
|
||||
BuildFaceMouseProc proc;
|
||||
EditTriObject *et;
|
||||
|
||||
public:
|
||||
BuildFaceCMode(EditTriObject* e, IObjParam *i)
|
||||
: fgProc(e), proc(e,i) {et=e;}
|
||||
|
||||
int Class() { return MODIFY_COMMAND; }
|
||||
int ID() { return CID_BUILDFACE; }
|
||||
MouseCallBack *MouseProc(int *numPoints) {*numPoints=999999; return &proc;}
|
||||
ChangeForegroundCallback *ChangeFGProc() {return &fgProc;}
|
||||
BOOL ChangeFG(CommandMode *oldMode) {return oldMode->ChangeFGProc()!= &fgProc;}
|
||||
void EnterMode();
|
||||
void ExitMode();
|
||||
};
|
||||
|
||||
|
||||
class AlignFaceMouseProc : public MouseCallBack {
|
||||
public:
|
||||
EditTriObject *et;
|
||||
IObjParam *ip;
|
||||
int which;
|
||||
|
||||
AlignFaceMouseProc(EditTriObject* e, IObjParam *i)
|
||||
{et=e;ip=i;which=ALIGN_CONST;}
|
||||
HitRecord *HitTestFaces(IPoint2 &m, ViewExp *vpt);
|
||||
int proc(
|
||||
HWND hwnd,
|
||||
int msg,
|
||||
int point,
|
||||
int flags,
|
||||
IPoint2 m );
|
||||
};
|
||||
|
||||
class AlignFaceCMode : public CommandMode {
|
||||
public:
|
||||
ChangeFGObject fgProc;
|
||||
AlignFaceMouseProc proc;
|
||||
EditTriObject* et;
|
||||
|
||||
AlignFaceCMode(EditTriObject* e, IObjParam *i)
|
||||
: fgProc(e), proc(e,i ) {et=e;}
|
||||
|
||||
int Class() { return MODIFY_COMMAND; }
|
||||
int ID() { return CID_ALIGNFACE; }
|
||||
MouseCallBack *MouseProc(int *numPoints) {*numPoints=1; return &proc;}
|
||||
ChangeForegroundCallback *ChangeFGProc() {return &fgProc;}
|
||||
BOOL ChangeFG(CommandMode *oldMode) {return oldMode->ChangeFGProc()!= &fgProc;}
|
||||
void EnterMode();
|
||||
void ExitMode();
|
||||
};
|
||||
|
||||
|
||||
class FlipNormMouseProc : public MouseCallBack {
|
||||
public:
|
||||
EditTriObject *et;
|
||||
IObjParam *ip;
|
||||
|
||||
FlipNormMouseProc(EditTriObject* e, IObjParam *i)
|
||||
{et=e;ip=i;}
|
||||
HitRecord *HitTestFaces(IPoint2 &m, ViewExp *vpt);
|
||||
int proc(
|
||||
HWND hwnd,
|
||||
int msg,
|
||||
int point,
|
||||
int flags,
|
||||
IPoint2 m );
|
||||
};
|
||||
|
||||
class FlipNormCMode : public CommandMode {
|
||||
public:
|
||||
ChangeFGObject fgProc;
|
||||
FlipNormMouseProc proc;
|
||||
EditTriObject* et;
|
||||
|
||||
FlipNormCMode(EditTriObject* e, IObjParam *i)
|
||||
: fgProc(e), proc(e,i ) {et=e;}
|
||||
|
||||
int Class() {return MODIFY_COMMAND;}
|
||||
int ID() {return CID_FLIPNORM;}
|
||||
MouseCallBack *MouseProc(int *numPoints) {*numPoints=1; return &proc;}
|
||||
ChangeForegroundCallback *ChangeFGProc() {return &fgProc;}
|
||||
BOOL ChangeFG(CommandMode *oldMode) {return oldMode->ChangeFGProc()!= &fgProc;}
|
||||
void EnterMode();
|
||||
void ExitMode();
|
||||
};
|
||||
|
||||
|
||||
|
||||
class PickEdgeMouseProc : public MouseCallBack {
|
||||
public:
|
||||
EditTriObject *et;
|
||||
IObjParam *ip;
|
||||
|
||||
PickEdgeMouseProc(EditTriObject* e, IObjParam *i)
|
||||
{et=e;ip=i;}
|
||||
HitRecord *HitTestEdges(IPoint2 &m, ViewExp *vpt);
|
||||
int proc(
|
||||
HWND hwnd,
|
||||
int msg,
|
||||
int point,
|
||||
int flags,
|
||||
IPoint2 m );
|
||||
virtual void EdgePick(DWORD edge)=0;
|
||||
};
|
||||
|
||||
class DivideEdgeProc : public PickEdgeMouseProc {
|
||||
public:
|
||||
DivideEdgeProc(EditTriObject* e, IObjParam *i) : PickEdgeMouseProc(e,i) {}
|
||||
void EdgePick(DWORD edge);
|
||||
};
|
||||
|
||||
class TurnEdgeProc : public PickEdgeMouseProc {
|
||||
public:
|
||||
TurnEdgeProc(EditTriObject* e, IObjParam *i) : PickEdgeMouseProc(e,i) {}
|
||||
void EdgePick(DWORD edge);
|
||||
};
|
||||
|
||||
class DivideEdgeCMode : public CommandMode {
|
||||
private:
|
||||
ChangeFGObject fgProc;
|
||||
DivideEdgeProc proc;
|
||||
EditTriObject* et;
|
||||
|
||||
public:
|
||||
DivideEdgeCMode(EditTriObject* e, IObjParam *i)
|
||||
: fgProc(e), proc(e,i) {et=e;}
|
||||
|
||||
int Class() { return MODIFY_COMMAND; }
|
||||
int ID() { return CID_DIVIDEEDGE; }
|
||||
MouseCallBack *MouseProc(int *numPoints) {*numPoints=1; return &proc;}
|
||||
ChangeForegroundCallback *ChangeFGProc() {return &fgProc;}
|
||||
BOOL ChangeFG(CommandMode *oldMode) {return oldMode->ChangeFGProc()!= &fgProc;}
|
||||
void EnterMode();
|
||||
void ExitMode();
|
||||
};
|
||||
|
||||
class TurnEdgeCMode : public CommandMode {
|
||||
private:
|
||||
ChangeFGObject fgProc;
|
||||
TurnEdgeProc proc;
|
||||
EditTriObject* et;
|
||||
|
||||
public:
|
||||
TurnEdgeCMode(EditTriObject* e, IObjParam *i)
|
||||
: fgProc(e), proc(e,i) {et=e;}
|
||||
|
||||
int Class() { return MODIFY_COMMAND; }
|
||||
int ID() { return CID_TURNEDGE; }
|
||||
MouseCallBack *MouseProc(int *numPoints) {*numPoints=1; return &proc;}
|
||||
ChangeForegroundCallback *ChangeFGProc() {return &fgProc;}
|
||||
BOOL ChangeFG(CommandMode *oldMode) {return oldMode->ChangeFGProc()!= &fgProc;}
|
||||
void EnterMode();
|
||||
void ExitMode();
|
||||
};
|
||||
|
||||
class CutEdgeProc : public MouseCallBack { // SCA -- derived from DivideEdgeProc.
|
||||
public:
|
||||
EditTriObject *et;
|
||||
IObjParam *ip;
|
||||
DWORD e1;
|
||||
bool e1set;
|
||||
float prop1;
|
||||
IPoint2 m1, oldm2;
|
||||
|
||||
CutEdgeProc(EditTriObject* e, IObjParam *i) { et=e; ip=i; e1set = FALSE;}
|
||||
HitRecord *HitTestEdges(IPoint2 &m, ViewExp *vpt);
|
||||
int proc(HWND hwnd, int msg, int point, int flags, IPoint2 m );
|
||||
void DrawCutter (HWND hWnd,IPoint2 &m);
|
||||
};
|
||||
|
||||
class CutEdgeCMode : public CommandMode { // SCA
|
||||
private:
|
||||
ChangeFGObject fgProc;
|
||||
CutEdgeProc proc;
|
||||
EditTriObject* et;
|
||||
|
||||
public:
|
||||
CutEdgeCMode(EditTriObject* e, IObjParam *i)
|
||||
: fgProc(e), proc(e,i) {et=e;}
|
||||
|
||||
int Class() { return MODIFY_COMMAND; }
|
||||
int ID() { return CID_CUTEDGE; }
|
||||
MouseCallBack *MouseProc(int *numPoints) {*numPoints=20; return &proc;}
|
||||
ChangeForegroundCallback *ChangeFGProc() {return &fgProc;}
|
||||
BOOL ChangeFG(CommandMode *oldMode) {return oldMode->ChangeFGProc()!= &fgProc;}
|
||||
void EnterMode();
|
||||
void ExitMode();
|
||||
};
|
||||
|
||||
// --- Restore objects ---------------------------------------------
|
||||
|
||||
class MeshSelRestore : public RestoreObj {
|
||||
public:
|
||||
BitArray undo, redo;
|
||||
EditTriObject *et;
|
||||
int level;
|
||||
|
||||
MeshSelRestore(EditTriObject *et);
|
||||
void Restore(int isUndo);
|
||||
void Redo();
|
||||
TSTR Description() {return TSTR(_T("Mesh Sel"));}
|
||||
};
|
||||
|
||||
class MeshVertRestore : public RestoreObj {
|
||||
public:
|
||||
Tab<Point3> undo, redo;
|
||||
EditTriObject *et;
|
||||
|
||||
MeshVertRestore(EditTriObject *et);
|
||||
void Restore(int isUndo);
|
||||
void Redo();
|
||||
void EndHold() {et->ClearAFlag(A_HELD);}
|
||||
TSTR Description() {return TSTR(_T("Mesh Vert"));}
|
||||
};
|
||||
|
||||
class MeshVertColorRestore : public RestoreObj {
|
||||
public:
|
||||
Tab<VertColor> undo, redo;
|
||||
EditTriObject *et;
|
||||
|
||||
MeshVertColorRestore(EditTriObject *et);
|
||||
void Restore(int isUndo);
|
||||
void Redo();
|
||||
void EndHold() {et->ClearAFlag(A_HELD);}
|
||||
TSTR Description() {return TSTR(_T("Mesh Vert Color"));}
|
||||
};
|
||||
|
||||
class MeshTopoRestore : public RestoreObj {
|
||||
public:
|
||||
EditTriObject *et;
|
||||
Tab<Point3> uverts, rverts;
|
||||
Tab<Point3> uTverts, rTverts;
|
||||
Tab<Face> ufaces, rfaces;
|
||||
Tab<TVFace> utvFaces, rtvFaces;
|
||||
Tab<VertColor> uvertCol, rvertCol;
|
||||
Tab<TVFace> uvcFaces, rvcFaces;
|
||||
BitArray uvertSel, ufaceSel, uedgeSel, uvertHide;
|
||||
BitArray rvertSel, rfaceSel, redgeSel, rvertHide;
|
||||
BOOL undone;
|
||||
Tab<Control*> ucont, rcont;
|
||||
|
||||
MeshTopoRestore(EditTriObject *et);
|
||||
void Restore(int isUndo);
|
||||
void Redo();
|
||||
void EndHold() {et->ClearAFlag(A_HELD);}
|
||||
TSTR Description() {return TSTR(_T("Mesh Topo"));}
|
||||
};
|
||||
|
||||
class MeshVertHideRestore : public RestoreObj {
|
||||
public:
|
||||
BitArray undo, redo;
|
||||
EditTriObject *et;
|
||||
|
||||
MeshVertHideRestore(EditTriObject *et);
|
||||
void Restore(int isUndo);
|
||||
void Redo();
|
||||
TSTR Description() {return TSTR(_T("Mesh Vert Hide"));}
|
||||
};
|
||||
|
||||
class MeshFaceHideRestore : public RestoreObj {
|
||||
public:
|
||||
BitArray undo, redo;
|
||||
EditTriObject *et;
|
||||
|
||||
MeshFaceHideRestore(EditTriObject *et);
|
||||
void Restore(int isUndo);
|
||||
void Redo();
|
||||
TSTR Description() {return TSTR(_T("Mesh Face Hide"));}
|
||||
};
|
||||
|
||||
class MeshFaceMatRestore : public RestoreObj {
|
||||
public:
|
||||
Tab<MtlID> undo, redo;
|
||||
EditTriObject *et;
|
||||
|
||||
MeshFaceMatRestore(EditTriObject *et);
|
||||
void Restore(int isUndo);
|
||||
void Redo();
|
||||
void EndHold() {et->ClearAFlag(A_HELD);}
|
||||
TSTR Description() {return TSTR(_T("Mesh Face Mat"));}
|
||||
};
|
||||
|
||||
class MeshFaceSmoothRestore : public RestoreObj {
|
||||
public:
|
||||
Tab<DWORD> undo, redo;
|
||||
EditTriObject *et;
|
||||
|
||||
MeshFaceSmoothRestore(EditTriObject *et);
|
||||
void Restore(int isUndo);
|
||||
void Redo();
|
||||
void EndHold() {et->ClearAFlag(A_HELD);}
|
||||
TSTR Description() {return TSTR(_T("Mesh Face Smooth"));}
|
||||
};
|
||||
|
||||
class MeshEdgeVisRestore : public RestoreObj {
|
||||
public:
|
||||
Tab<DWORD> undo, redo;
|
||||
EditTriObject *et;
|
||||
|
||||
MeshEdgeVisRestore(EditTriObject *et);
|
||||
void Restore(int isUndo);
|
||||
void Redo();
|
||||
void EndHold() {et->ClearAFlag(A_HELD);}
|
||||
TSTR Description() {return TSTR(_T("Mesh Edge Vis"));}
|
||||
};
|
||||
|
||||
class FaceIndexRec {
|
||||
public:
|
||||
DWORD v[3], flags;
|
||||
};
|
||||
class UVFaceIndexRec {
|
||||
public:
|
||||
DWORD v[3];
|
||||
};
|
||||
|
||||
|
||||
class MeshFaceIndexRestore : public RestoreObj {
|
||||
public:
|
||||
Tab<FaceIndexRec> undo, redo;
|
||||
Tab<UVFaceIndexRec> tundo, tredo;
|
||||
EditTriObject *et;
|
||||
|
||||
MeshFaceIndexRestore(EditTriObject *et);
|
||||
void Restore(int isUndo);
|
||||
void Redo();
|
||||
TSTR Description() {return TSTR(_T("Mesh Face Index"));}
|
||||
};
|
||||
|
||||
class AppendSetRestore : public RestoreObj {
|
||||
public:
|
||||
BitArray set;
|
||||
TSTR name;
|
||||
NamedSelSetList *setList;
|
||||
EditTriObject *et;
|
||||
|
||||
AppendSetRestore(NamedSelSetList *sl,EditTriObject *e) {
|
||||
setList = sl; et = e;
|
||||
}
|
||||
void Restore(int isUndo) {
|
||||
set = *setList->sets[setList->Count()-1];
|
||||
name = *setList->names[setList->Count()-1];
|
||||
setList->DeleteSet(setList->Count()-1);
|
||||
if (et->ip) et->ip->NamedSelSetListChanged();
|
||||
}
|
||||
void Redo() {
|
||||
setList->AppendSet(set,name);
|
||||
if (et->ip) et->ip->NamedSelSetListChanged();
|
||||
}
|
||||
|
||||
TSTR Description() {return TSTR(_T("Append Set"));}
|
||||
};
|
||||
|
||||
class DeleteSetRestore : public RestoreObj {
|
||||
public:
|
||||
BitArray set;
|
||||
TSTR name;
|
||||
int index;
|
||||
NamedSelSetList *setList;
|
||||
EditTriObject *et;
|
||||
|
||||
DeleteSetRestore(int i,NamedSelSetList *sl,EditTriObject *e) {
|
||||
setList = sl; et = e; index = i;
|
||||
set = *setList->sets[index];
|
||||
name = *setList->names[index];
|
||||
}
|
||||
void Restore(int isUndo) {
|
||||
BitArray *n = new BitArray(set);
|
||||
TSTR *nm = new TSTR(name);
|
||||
setList->sets.Insert(index,1,&n);
|
||||
setList->names.Insert(index,1,&nm);
|
||||
if (et->ip) et->ip->NamedSelSetListChanged();
|
||||
}
|
||||
void Redo() {
|
||||
setList->DeleteSet(index);
|
||||
if (et->ip) et->ip->NamedSelSetListChanged();
|
||||
}
|
||||
|
||||
TSTR Description() {return TSTR(_T("Delete Set"));}
|
||||
};
|
||||
|
||||
class SetNameRestore : public RestoreObj {
|
||||
public:
|
||||
TSTR undo, redo;
|
||||
int index;
|
||||
NamedSelSetList *setList;
|
||||
EditTriObject *et;
|
||||
SetNameRestore(int i,NamedSelSetList *sl,EditTriObject *e) {
|
||||
index = i; setList = sl; et = e;
|
||||
undo = *setList->names[index];
|
||||
}
|
||||
|
||||
void Restore(int isUndo) {
|
||||
redo = *setList->names[index];
|
||||
*setList->names[index] = undo;
|
||||
if (et->ip) et->ip->NamedSelSetListChanged();
|
||||
}
|
||||
void Redo() {
|
||||
*setList->names[index] = redo;
|
||||
if (et->ip) et->ip->NamedSelSetListChanged();
|
||||
}
|
||||
|
||||
TSTR Description() {return TSTR(_T("Set Name"));}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class AttachHitByName : public HitByNameDlgCallback {
|
||||
public:
|
||||
EditTriObject *eo;
|
||||
|
||||
AttachHitByName(EditTriObject *e) {eo=e;}
|
||||
TCHAR *dialogTitle();// {return GetString(IDS_RB_MULTIATTACH);}
|
||||
TCHAR *buttonText();// {return GetString(IDS_RB_ATTACH);}
|
||||
int filter(INode *node);
|
||||
void proc(INodeTab &nodeTab);
|
||||
};
|
||||
|
||||
|
||||
// --- tridata.cpp functions ---------------------------------------
|
||||
|
||||
float AffectRegionFunction(float dist,float falloff,float pinch,float bubble);
|
||||
Point3 FaceNormal(Mesh &mesh, DWORD fi);
|
||||
Point3 FaceCenter(Mesh &mesh, DWORD fi);
|
||||
BOOL AnyFaceVertSelected(Mesh &mesh, DWORD fi);
|
||||
Point3 AverageSelVertNormal(Mesh& mesh);
|
||||
Point3 AverageSelVertCenter(Mesh& mesh);
|
||||
void BuildAverageNormals(Mesh& mesh, Point3Tab& normals);
|
||||
void MatrixFromNormal(Point3& normal, Matrix3& mat);
|
||||
void BitArrayDeleteSet(BitArray &ba,BitArray &set,int m=1);
|
||||
void MeshDeleteVertices(Mesh &mesh,BitArray& set);
|
||||
void MeshDeleteFaces(Mesh &mesh,BitArray& set);
|
||||
void PolyFromFace(Mesh& mesh,AdjFaceList &al,DWORD f,BitArray &set,float thresh,BOOL ignoreVisEdge);
|
||||
void ElementFromFace(Mesh &mesh, AdjFaceList &al,DWORD f, BitArray &set);
|
||||
AdjFaceList *BuildAdjFaceList(Mesh &mesh);
|
||||
int GetEdgeIndex(Face &f,DWORD v0,DWORD v1);
|
||||
DWORD GetOtherIndex(Face *f,DWORD v0,DWORD v1);
|
||||
float AngleBetweenFaces(Mesh *mesh,DWORD f0, DWORD f1);
|
||||
void FaceCenterTessellate(Mesh *mesh);
|
||||
void EdgeTessellate(Mesh *mesh, AdjEdgeList *ae, AdjFaceList *af, float tens);
|
||||
BOOL IsEdgeSelected(MEdge edge,Face *faces,BitArray &esel);
|
||||
BOOL IsFaceSelected(MEdge edge,BitArray &fsel);
|
||||
BOOL IsEdgeVisible(MEdge edge,Face *faces);
|
||||
Point3 ButterFlySubdivide(MEdge edg,Mesh *mesh,AdjFaceList *af,float tens);
|
||||
Point3 EdgeCenter(MEdge edge,Point3 *verts);
|
||||
void ElemExplodeFaces(Mesh *mesh, float thresh, AdjFaceList *af);
|
||||
void ObjExplodeFaces(EditTriObject *eo,
|
||||
INode *node, TSTR &name, Interface *ip,
|
||||
Mesh *mesh, float thresh, AdjFaceList *af);
|
||||
void SwapEdgeVerts(Face *f,DWORD& v1,DWORD& v2);
|
||||
DWORD GetFaceVertIndex(Face &f,DWORD v);
|
||||
void EdgeTessellate(Mesh *mesh, AdjEdgeList *ae, AdjFaceList *af, float tens);
|
||||
void ExtrudeFaces(EditTriObject *eo, Mesh& mesh,
|
||||
BitArray& sel, AdjEdgeList& el, BOOL doFace);
|
||||
BOOL GetDetachObjectName(HWND hDlg,TSTR &name, BOOL &elem);
|
||||
void DeselectHiddenFaces(Mesh &mesh);
|
||||
void SyncSelectionSets(Mesh &mesh);
|
||||
|
||||
#endif //__TRIOBJED__
|
BIN
Utils/GinExp/asciiexp.aps
Normal file
BIN
Utils/GinExp/asciiexp.aps
Normal file
Binary file not shown.
8
Utils/GinExp/asciiexp.def
Normal file
8
Utils/GinExp/asciiexp.def
Normal file
|
@ -0,0 +1,8 @@
|
|||
LIBRARY GinExp
|
||||
EXPORTS
|
||||
LibDescription @1
|
||||
LibNumberClasses @2
|
||||
LibClassDesc @3
|
||||
LibVersion @4
|
||||
SECTIONS
|
||||
.data READ WRITE
|
201
Utils/GinExp/asciiexp.dsp
Normal file
201
Utils/GinExp/asciiexp.dsp
Normal file
|
@ -0,0 +1,201 @@
|
|||
# Microsoft Developer Studio Project File - Name="asciiexp" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=ASCIIEXP - WIN32 RELEASE
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "asciiexp.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "asciiexp.mak" CFG="ASCIIEXP - WIN32 RELEASE"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "asciiexp - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "asciiexp - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""$/KatBox/Project/asciiexp", VHBAAAAA"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "asciiexp - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir ".\Release"
|
||||
# PROP BASE Intermediate_Dir ".\Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir ".\Release"
|
||||
# PROP Intermediate_Dir ".\Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
|
||||
# ADD CPP /nologo /G6 /MD /W3 /GX /Od /I "..\..\..\include" /I "c:\3dsmax3_1\MaxSDK\INCLUDE" /I "c:\3dsmax3_1\cstudio\docs" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
|
||||
# ADD LINK32 KERNEL32.LIB USER32.LIB GDI32.LIB WINSPOOL.LIB COMDLG32.LIB ADVAPI32.LIB SHELL32.LIB OLE32.LIB OLEAUT32.LIB UUID.LIB ODBC32.LIB ODBCCP32.LIB COMCTL32.LIB /nologo /base:"0X02C60000" /subsystem:windows /dll /incremental:yes /machine:I386 /out:"C:\3dsmax3_1\plugins\GinExp.dle"
|
||||
|
||||
!ELSEIF "$(CFG)" == "asciiexp - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir ".\Debug"
|
||||
# PROP BASE Intermediate_Dir ".\Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir ".\Debug"
|
||||
# PROP Intermediate_Dir ".\Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
|
||||
# ADD CPP /nologo /G6 /MDd /W3 /Gm /GX /ZI /Od /I "c:\3dsmax3_1\MaxSDK\INCLUDE" /I "c:\3dsmax3_1\cstudio\docs" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
|
||||
# ADD LINK32 KERNEL32.LIB USER32.LIB GDI32.LIB WINSPOOL.LIB COMDLG32.LIB ADVAPI32.LIB SHELL32.LIB OLE32.LIB OLEAUT32.LIB UUID.LIB ODBC32.LIB ODBCCP32.LIB COMCTL32.LIB /nologo /base:"0X02C60000" /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"C:\3dsmax3_1\plugins\GinExp.dle"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "asciiexp - Win32 Release"
|
||||
# Name "asciiexp - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\asciiexp.def
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\asciiexp.rc
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ExpBone.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ExpCamLight.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ExpFFD.cpp
|
||||
|
||||
!IF "$(CFG)" == "asciiexp - Win32 Release"
|
||||
|
||||
!ELSEIF "$(CFG)" == "asciiexp - Win32 Debug"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ExpFileIo.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ExpFileIo.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ExpMain.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ExpMaterial.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ExpModel.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ExpTree.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ExpUProp.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\resource.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\asciiexp.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ffd.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Triobjed.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# Begin Group "Libraries"
|
||||
|
||||
# PROP Default_Filter "*.lib"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=\3dsmax3_1\MaxSDK\LIB\CORE.LIB
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=\3dsmax3_1\MaxSDK\LIB\GEOM.LIB
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=\3dsmax3_1\MaxSDK\LIB\MESH.LIB
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=\3dsmax3_1\Maxsdk\Lib\Bmm.lib
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=\3dsmax3_1\Maxsdk\lib\maxutil.lib
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
456
Utils/GinExp/asciiexp.h
Normal file
456
Utils/GinExp/asciiexp.h
Normal file
|
@ -0,0 +1,456 @@
|
|||
//**************************************************************************
|
||||
//* Asciiexp.h - Katana File Exporter
|
||||
//*
|
||||
//* By Tim Swann
|
||||
//* Climax Development
|
||||
//*
|
||||
//* July 7, 1998 TS Initial coding
|
||||
//*
|
||||
//* Class definition
|
||||
//*
|
||||
//* Copyright (c) 1998, All Rights Reserved.
|
||||
//***************************************************************************
|
||||
|
||||
#ifndef __ASCIIEXP__H
|
||||
#define __ASCIIEXP__H
|
||||
|
||||
#define MAXCOUNT (256*16)
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <Max.h>
|
||||
#include "Resource.h"
|
||||
#include "Istdplug.h"
|
||||
#include "Stdmat.h"
|
||||
#include "Decomp.h"
|
||||
#include "Shape.h"
|
||||
#include "Interpik.h"
|
||||
|
||||
//#include "Asciitok.h"
|
||||
|
||||
#include "PhyExp.h"
|
||||
#include "triobjed.h"
|
||||
#include "ffd.h"
|
||||
#include "Bmmlib.h"
|
||||
#include "bipexp.h"
|
||||
//#include <Kamui.h>
|
||||
//#include <NinjaWin.h>
|
||||
//#include <Nindows.h>
|
||||
//#include <NjDef.h>
|
||||
|
||||
typedef unsigned int Uint32;
|
||||
typedef unsigned short Uint16;
|
||||
typedef unsigned char Uint8;
|
||||
typedef bool Bool;
|
||||
|
||||
|
||||
extern ClassDesc * GetAsciiExpDesc();
|
||||
extern TCHAR * GetString(int id);
|
||||
extern HINSTANCE hInstance;
|
||||
extern DWORD WINAPI fn(LPVOID arg);
|
||||
|
||||
|
||||
//#define MAKE_LONG( a,b,c,d ) (a | (b<<8) | (c<<16) | (d<<24))
|
||||
#define MAKE_LONG(a,b,c,d) { a, b, c, d, 0}
|
||||
#define MAX_FILE_CHUNKS (4096*2)
|
||||
|
||||
#define OMNI_LIGHT 0 // Omnidirectional
|
||||
#define TSPOT_LIGHT 1 // Targeted
|
||||
#define DIR_LIGHT 2 // Directional
|
||||
#define FSPOT_LIGHT 3 // Free
|
||||
#define TDIR_LIGHT 4 // Targeted directional
|
||||
|
||||
#define GIN_FLAG_USE_TEXTURE 1
|
||||
#define GIN_FLAG_DOUBLE_SIDE 2
|
||||
#define GIN_FLAG_IGNORE_LIGHT 4
|
||||
#define GIN_FLAG_USE_ENVTEXTURE 32
|
||||
|
||||
const Uint32 MAX_NODES = 1000; // MAX NODES IN SCENE
|
||||
const Uint32 MAX_CHUNKFILE_CHUNK_DEPTH = 20; // MAXIMUM NESTED DEPTH OF CHUNKS IN A CHUNKFILE:
|
||||
const Uint32 MAX_NAME_LENGTH = 32; // MAXIMUM LENGTH OF A NAME STRING
|
||||
const Uint32 ID_SIZE = 4; // SIZE OF CHUNK ID
|
||||
|
||||
// ANIMATION CHANNEL DEFINITIONS
|
||||
const Uint32 CHANNEL_TYPE_NONE = 0; // NO CHANNEL APPLIED
|
||||
const Uint32 CHANNEL_TYPE_VERTEX = 1; // VERTEX ANIMATION
|
||||
const Uint32 CHANNEL_TYPE_BONE = 2; // BONE ANIMATION
|
||||
const Uint32 CHANNEL_TYPE_WEIGHTS = 3; // BONE VERTEX WEIGHT ANIMATION
|
||||
const Uint32 CHANNEL_TYPE_NORMALS = 4; // NORMAL ANIMATION
|
||||
const Uint32 CHANNEL_TYPE_FFD = 5; // FFD ANIMATION
|
||||
const Uint32 CHANNEL_TYPE_NODE = 6; // NODE ANIMATION
|
||||
const Uint32 CHANNEL_TYPE_TREE = 7; // NODE ANIMATION
|
||||
|
||||
|
||||
const Uint32 CHANNEL_INFO_POSITION = 0; // NO CHANNEL APPLIED
|
||||
const Uint32 CHANNEL_INFO_ROTATION = 1; // VERTEX ANIMATION
|
||||
const Uint32 CHANNEL_INFO_SCALE = 2; // BONE ANIMATION
|
||||
const Uint32 CHANNEL_INFO_ALL = 3; // BONE ANIMATION
|
||||
|
||||
// COUNT OF NUMBER OF FLOATS FOR EACH ANIMATION CHANNEL TYPE
|
||||
const Uint32 ChannelTypeSize[] = { 0, 3, 7, 1, 3 };
|
||||
|
||||
|
||||
const char FILE_ID[] = MAKE_LONG( 'G', 'I', 'N', '4' );
|
||||
const char OBJ_ID[] = MAKE_LONG( 'O', 'B', 'J', '4' );
|
||||
const char POLY_ID[] = MAKE_LONG( 'P', 'O', 'L', 'Y' );
|
||||
const char UV_ID[] = MAKE_LONG( 'M', 'A', 'P', '4' );
|
||||
const char MESH_ID[] = MAKE_LONG( 'M', 'E', 'S', 'H' );
|
||||
const char POINTS_ID[] = MAKE_LONG( 'P', 'T', 'S', '4' );
|
||||
const char NORMAL_ID[] = MAKE_LONG( 'N', 'O', 'R', 'M' );
|
||||
const char MODEL_ID[] = MAKE_LONG( 'M', 'O', 'D', '4' );
|
||||
const char TEXTURE_ID[] = MAKE_LONG( 'T', 'E', 'X', '4' );
|
||||
const char MATERIAL_ID[] = MAKE_LONG( 'M', 'A', 'T', '4' );
|
||||
const char CAMERA_ID[] = MAKE_LONG( 'C', 'A', 'M', '4' );
|
||||
const char LIGHT_ID[] = MAKE_LONG( 'L', 'G', 'H', 'T' );
|
||||
const char BONE_ID[] = MAKE_LONG( 'B', 'O', 'N', 'E' );
|
||||
const char ANIM_ID[] = MAKE_LONG( 'A', 'N', 'I', 'M' );
|
||||
const char FFD_ID[] = MAKE_LONG( 'F', 'F', 'D', '4' );
|
||||
const char VCOL_ID[] = MAKE_LONG( 'V', 'C', 'O', 'L' );
|
||||
const char PART_ID[] = MAKE_LONG( 'P', 'A', 'R', 'T' );
|
||||
const char VIS_ID[] = MAKE_LONG( 'V', 'I', 'S', '4' );
|
||||
const char KEY_ID[] = MAKE_LONG( 'K', 'E', 'Y', '4' );
|
||||
const char FACENORMAL_ID[] = MAKE_LONG( 'F', 'N', 'R', 'M' );
|
||||
const char OBJNODE_ID[] = MAKE_LONG( 'N', 'O', 'D', 'E' );
|
||||
const char ORIG_ID[] = MAKE_LONG( 'O', 'R', 'I', 'G' );
|
||||
const char VERSION_ID[] = MAKE_LONG( 'V', 'E', 'R', 'S' );
|
||||
const char KID_ID[] = MAKE_LONG( 'K', 'I', 'D', '4' );
|
||||
const char TREE_ID[] = MAKE_LONG( 'T', 'R', 'E', 'E' );
|
||||
const char VECT_ID[] = MAKE_LONG( 'V', 'E', 'C', 'T' );
|
||||
//const char MOTION_ID[] = MAKE_LONG( 'M', 'O', 'V', 'E' );
|
||||
const char TERMINATOR_ID[] = {0};
|
||||
|
||||
|
||||
|
||||
#define VERSION 131 // Version number * 100
|
||||
#define KATEXP_CLASS_ID Class_ID(0x37bf4fd7, 0x29976333) // CLASS_ID
|
||||
|
||||
|
||||
const float MPI = 3.1415926535897932384626433932795028841792f;
|
||||
const float HALF_PI = (MPI / 2);
|
||||
const float ONE_DEGREE = 0.0174532925199432957692369076848861271344f;
|
||||
const float INV_ONE_DEGREE = 1/ONE_DEGREE;
|
||||
|
||||
#define DELTA 1e-6 // error tolerance
|
||||
|
||||
|
||||
enum {VX, VY, VZ, VW}; // axes
|
||||
|
||||
inline float DEG2RAD (float dval) { return(dval*ONE_DEGREE); }
|
||||
inline float RAD2DEG (float dval) { return(dval*(INV_ONE_DEGREE)); }
|
||||
|
||||
|
||||
#define NJD_PI 3.14159265358979323846
|
||||
#define NJM_DEG_RAD(n) ((n) * NJD_PI / 180.0) // deg -> rad
|
||||
#define NJM_DEG_ANG(n) (((Angle)(((n) * 65536.0) / 360.0)) & 0x0000ffff) // deg -> ang
|
||||
#define NJM_RAD_ANG(n) (((Angle)(((n) * 65536.0) / (2 * NJD_PI))) & 0xffff) // rad -> ang
|
||||
#define NJM_RAD_DEG(n) ((n) * 180.0 / NJD_PI) // rad -> deg
|
||||
#define NJM_ANG_DEG(n) ((n) * 360.0 / 65536.0) // ang -> deg
|
||||
#define NJM_ANG_RAD(n) ((n) * (2 * NJD_PI) / 65536.0) // ang -> rad
|
||||
|
||||
|
||||
const float UV_X = 255.f;
|
||||
const float UV_Y = -255.f;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
INode *N;
|
||||
int Id;
|
||||
} NODE_ID;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MtlID MatId;
|
||||
Uint16 nbFaces;
|
||||
} MESH_SET;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Color colour;
|
||||
float alpha;
|
||||
} COLOURDEF;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
COLOURDEF diffuse;
|
||||
COLOURDEF specular;
|
||||
float exponent;
|
||||
Uint32 tex_flags;
|
||||
Uint32 attr_flags;
|
||||
} MATERIAL;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[256];
|
||||
MATERIAL material;
|
||||
Uint16 TexID;
|
||||
Uint16 SubTex[256];
|
||||
} MATLIST;
|
||||
|
||||
|
||||
|
||||
#define MAX_BONE_NODES 64
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int nodecount;
|
||||
int vertno;
|
||||
char names[MAX_BONE_NODES][256];
|
||||
float weights[MAX_BONE_NODES];
|
||||
int NodeId[MAX_BONE_NODES];
|
||||
Point3 Offsets[MAX_BONE_NODES];
|
||||
} WEIGHTS;
|
||||
|
||||
|
||||
class MtlKeeper
|
||||
{
|
||||
public:
|
||||
int MtlCount;
|
||||
int GetSubMtlCount(Mtl* mtl, bool recurse);
|
||||
BOOL AddMtl(Mtl* mtl);
|
||||
int GetMtlID(Mtl* mtl);
|
||||
int Count();
|
||||
Mtl* GetMtl(int id);
|
||||
|
||||
Tab<Mtl*> mtlTab;
|
||||
};
|
||||
|
||||
|
||||
class TimeList {
|
||||
|
||||
TimeValue Value[1000];
|
||||
int count;
|
||||
|
||||
public:
|
||||
|
||||
TimeList() {
|
||||
count = 0;
|
||||
}
|
||||
|
||||
void Add(TimeValue t) {
|
||||
int i,j;
|
||||
for (i = 0 ;i<count; i++) {
|
||||
if (Value[i] == t) {
|
||||
return;
|
||||
}
|
||||
if (Value[i]>t) {
|
||||
for (j = count; j>i; j--) {
|
||||
Value[j] = Value[j-1];
|
||||
}
|
||||
Value[i] = t;
|
||||
count++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
Value[count] = t;
|
||||
count++;
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
count = 0;
|
||||
}
|
||||
|
||||
int Count() {
|
||||
return count;
|
||||
}
|
||||
|
||||
TimeValue Get(int p) {
|
||||
return Value[p];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class AsciiExp : public SceneExport
|
||||
{
|
||||
public:
|
||||
AsciiExp();
|
||||
~AsciiExp();
|
||||
|
||||
// SceneExport methods
|
||||
int ExtCount(); // Number of extensions supported
|
||||
const TCHAR * Ext(int n); // Extension #n (i.e. "ASC")
|
||||
const TCHAR * LongDesc(); // Long ASCII description (i.e. "Ascii Export")
|
||||
const TCHAR * ShortDesc(); // Short ASCII description (i.e. "Ascii")
|
||||
const TCHAR * AuthorName(); // ASCII Author name
|
||||
const TCHAR * CopyrightMessage(); // ASCII Copyright message
|
||||
const TCHAR * OtherMessage1(); // Other message #1
|
||||
const TCHAR * OtherMessage2(); // Other message #2
|
||||
unsigned int Version(); // Version number * 100 (i.e. v3.01 = 301)
|
||||
void ShowAbout(HWND hWnd); // Show DLL's "About..." box
|
||||
#if MAX_RELEASE == 2500
|
||||
int DoExport(const TCHAR *name,ExpInterface *ei,Interface *i, BOOL suppressPrompts=FALSE); // Export file
|
||||
#else
|
||||
int DoExport(const TCHAR *name,ExpInterface *ei,Interface *i, BOOL suppressPrompts=FALSE,DWORD options=0); // Export file
|
||||
#endif
|
||||
|
||||
// Node enumeration
|
||||
BOOL nodeEnum(INode* node);
|
||||
void BoneProcess(INode* node, int& nodeCount);
|
||||
void FfdProcess(INode* node, int& nodeCount);
|
||||
void PreProcessBone( INode* node );
|
||||
void NodePreProcess(INode *node);
|
||||
|
||||
// High level export
|
||||
void ExportNode(INode * node);
|
||||
void ExportMaterialList();
|
||||
void ExportModel(INode* node);
|
||||
void ExportAnimMesh(INode* node);
|
||||
void ExportCamera(INode* node);
|
||||
void ExportLight(INode* node);
|
||||
|
||||
void ExportTree();
|
||||
// Mid level export
|
||||
void ExportMesh(INode* node);
|
||||
void ExportBones( INode* node );
|
||||
void ExportMaterial(INode* node);
|
||||
void ExportAnimKeys(INode* node);
|
||||
void ExportFFD( INode* node , FFDMod *FfdMod, ModContext *mc, Mesh *);
|
||||
|
||||
// Low level export
|
||||
void ExportBoneKeyAnim( INode* node );
|
||||
void ExportBoneKeyAnimPos( INode* node );
|
||||
void ExportBoneKeyAnimRot( INode* node );
|
||||
void ExportBoneKeyAnimScl( INode* node );
|
||||
void ExportBoneKeyAnimPos( INode* node , TimeList tl);
|
||||
void ExportBoneKeyAnimRot( INode* node , TimeList tl);
|
||||
void ExportBoneKeyAnimScl( INode* node , TimeList tl);
|
||||
void ExportNodeKeyAnim( INode *node);
|
||||
void ExportNodeKeyPos( INode *node);
|
||||
void ExportNodeKeyRot( INode *node);
|
||||
void ExportNodeKeyScl( INode *node);
|
||||
void ExportMeshList(INode * node, Mesh * mesh);
|
||||
void ExportPoints(INode * node, Mesh * mesh);
|
||||
void ExportVectors(INode * node, Mesh * mesh);
|
||||
void ExportNormals(INode * node, Mesh * mesh);
|
||||
void ExportVertCols(INode * node, Mesh * mesh);
|
||||
void ExportVisTrack( INode* node );
|
||||
void ExportBoneAnim( INode* node );
|
||||
void ExportLimb( INode* nodeptr );
|
||||
void ExportWeights( INode* nodeptr );
|
||||
void ExportNodeAnimMesh( INode* node );
|
||||
void ExportMeshVertAnim(INode *node, EditTriObject *e);
|
||||
void DumpMeshAnim(INode* node, TimeValue t);
|
||||
void CalcMeshAnimInfo(INode* node, TimeValue t);
|
||||
void DumpPoly(PolyLine* line, Matrix3 tm);
|
||||
void DumpMatrix3(Matrix3* m);
|
||||
void DumpMaterial(Mtl* mtl, int matno, int subno , bool recurse = false);
|
||||
void DumpJointParams(JointParams* joint);
|
||||
void DumpUVGen(StdUVGen* uvGen);
|
||||
void DumpCamPosSample(INode* node);
|
||||
void DumpPosSample(INode* node);
|
||||
void DumpPosQuatSample(INode* node);
|
||||
void DumpRotSample(INode* node);
|
||||
void DumpScaleSample(INode* node);
|
||||
void DumpPoint3Keys(Control* cont);
|
||||
void DumpFloatKeys(Control* cont);
|
||||
void DumpPosKeys(Control* cont);
|
||||
void DumpRotKeys(Control* cont);
|
||||
void DumpScaleKeys(Control* cont);
|
||||
void DumpTexture( Mtl* mtl, int matno, int subno );
|
||||
void ExportTreeNodes( INode * node );
|
||||
void ExportTreeAnim( INode* node );
|
||||
void ExportTreeKeyAnim( INode* node);
|
||||
void ExportMotionAnim( INode* node);
|
||||
|
||||
// Erm, dunno export
|
||||
void ExportProp( INode* node );
|
||||
|
||||
// Misc methods
|
||||
int getTextureId( Mtl *mtl );
|
||||
void SubAnims(Animatable *a);
|
||||
bool IsBoned(INode *node);
|
||||
bool WriteChunkHdr( char* ChunkID, long Size );
|
||||
void CalcChunkSizes( void );
|
||||
void GetNoFrames( void );
|
||||
int ValidateBoneKids( INode * nodeptr );
|
||||
Modifier * FindPhysiqueModifier (INode* node, ModContext**mc);
|
||||
Modifier * FindPhysiqueModifier (INode* nodePtr);
|
||||
bool FindFFDModifier (INode* node);
|
||||
void FindEditableMesh(INode *node);
|
||||
TCHAR * GetMapID(Class_ID cid, int subNo);
|
||||
Point3 GetVertexNormal(Mesh* mesh, int faceNo, RVertex* rv);
|
||||
BOOL CheckForAndExportFaceMap(Mtl* mtl, Mesh* mesh, int matno);
|
||||
void make_face_uv(Face *f, Point3 *tv);
|
||||
BOOL TMNegParity(Matrix3 &m);
|
||||
TCHAR * FixupName(TCHAR* name);
|
||||
BOOL CheckForAnimation(INode* node, BOOL& pos, BOOL& rot, BOOL& scale);
|
||||
TriObject * GetTriObjectFromNode(INode *node, TimeValue t, int &deleteIt);
|
||||
TriObject * GetTriObjectFromObject(Object *obj, TimeValue t, int &deleteIt);
|
||||
BOOL IsKnownController(Control* cont);
|
||||
Point3 GetAverageVertNormal(INode *node, Mesh* mesh, int VertNo);
|
||||
void OrigProcess(INode *node);
|
||||
TSTR FindTextureFName(TSTR MapName);
|
||||
void ExportParticles();
|
||||
void ExportParticleNodes(INode *node);
|
||||
// Interface to member variables
|
||||
inline Interface * GetInterface() { return ip; }
|
||||
// void SetExportAnimFlag(int State) {ExportAnimFlag=State;}
|
||||
// int GetExportAnimFlag() {return(ExportAnimFlag);}
|
||||
private:
|
||||
// int ExportAnimFlag;
|
||||
char drive[_MAX_DRIVE];
|
||||
char dir[_MAX_DIR];
|
||||
char fname[_MAX_FNAME];
|
||||
char ext[_MAX_EXT];
|
||||
char filename[_MAX_DRIVE+_MAX_DIR+_MAX_FNAME+_MAX_EXT];
|
||||
|
||||
int Export[MAX_NODES];
|
||||
|
||||
char SceneName[256];
|
||||
char MeshFname[256];
|
||||
|
||||
Interface * ip;
|
||||
ModContext *PhyMc;
|
||||
|
||||
FILE * tempStream; // Temp debug file
|
||||
FILE * expStream; // EXPORT file
|
||||
|
||||
int nbChunks;
|
||||
long SizeTab[MAX_FILE_CHUNKS];
|
||||
|
||||
int nTotalNodeCount;
|
||||
int nCurNode;
|
||||
int nCurObj;
|
||||
int nbFrames;
|
||||
Uint32 totFrames;
|
||||
int CurBone;
|
||||
int NbEmmitters;
|
||||
|
||||
float radius;
|
||||
|
||||
int nbBones;
|
||||
int nbWeights;
|
||||
WEIGHTS * Weights;
|
||||
|
||||
int FfdNum;
|
||||
|
||||
int nbTexs;
|
||||
char TexList[MAXCOUNT][64];
|
||||
|
||||
int nbMats;
|
||||
MATLIST MatList[MAXCOUNT];
|
||||
|
||||
int nbMeshs;
|
||||
MESH_SET MeshSet[MAXCOUNT];
|
||||
|
||||
|
||||
HWND MAX_hWnd;
|
||||
// char BoxString[MAXCOUNT];
|
||||
MtlKeeper mtlList;
|
||||
|
||||
// NODE_ID NodeList[MAXCOUNT];
|
||||
// int NodeCount;
|
||||
};
|
||||
|
||||
|
||||
class AsciiExpClassDesc : public ClassDesc
|
||||
{
|
||||
public:
|
||||
int IsPublic() { return 1; }
|
||||
void * Create(BOOL loading = FALSE) { return new AsciiExp; }
|
||||
const TCHAR* ClassName() { return GetString(IDS_ASCIIEXP); }
|
||||
SClass_ID SuperClassID() { return SCENE_EXPORT_CLASS_ID; }
|
||||
Class_ID ClassID() { return KATEXP_CLASS_ID; }
|
||||
const TCHAR* Category() { return GetString(IDS_CATEGORY); }
|
||||
};
|
||||
|
||||
#endif // __ASCIIEXP__H
|
||||
|
BIN
Utils/GinExp/asciiexp.ncb
Normal file
BIN
Utils/GinExp/asciiexp.ncb
Normal file
Binary file not shown.
174
Utils/GinExp/asciiexp.rc
Normal file
174
Utils/GinExp/asciiexp.rc
Normal file
|
@ -0,0 +1,174 @@
|
|||
//Microsoft Developer Studio generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
#ifndef _MAC
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 2,0,0,0
|
||||
PRODUCTVERSION 2,0,0,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "Comments", "KATANA file exporter (plugin)\0"
|
||||
VALUE "CompanyName", "Climax\0"
|
||||
VALUE "FileDescription", "katexp\0"
|
||||
VALUE "FileVersion", "2, 0, 0, 0\0"
|
||||
VALUE "InternalName", "KatExp\0"
|
||||
VALUE "LegalCopyright", "Copyright © 1998 Climax.\0"
|
||||
VALUE "OriginalFilename", "KatExp.dle\0"
|
||||
VALUE "ProductName", "3D Studio MAX\0"
|
||||
VALUE "ProductVersion", "2, 0, 0, 0\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // !_MAC
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// String Table
|
||||
//
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
IDS_ASCIIEXP "GinExp"
|
||||
IDS_CATEGORY "Standard"
|
||||
IDS_EXTENSION1 "GIN"
|
||||
IDS_LONGDESC "3D Studio MAX Climax Scene Exporter"
|
||||
IDS_SHORTDESC "Climax Export"
|
||||
IDS_COPYRIGHT "Copyight (c) 1998 by Climax"
|
||||
IDS_PROGRESS_MSG1 "Please wait skinning up"
|
||||
IDS_VERSIONSTRING "Climax Export Version"
|
||||
IDS_LIBDESCRIPTION "Climax file exporter (Climax)"
|
||||
IDS_PROGRESS_MSG2 "Please wait skinning up2"
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.K.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_ASCIIEXPORT_DLG DIALOG DISCARDABLE 0, 0, 186, 95
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "GinExport Options"
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "OK",IDOK,129,7,50,14
|
||||
CONTROL "Check1",IDC_ANIMCHECK,"Button",BS_AUTOCHECKBOX |
|
||||
WS_TABSTOP,16,22,9,11
|
||||
LTEXT "Export Anim",IDC_ANIMTEXT,26,23,76,12
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DESIGNINFO
|
||||
//
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
GUIDELINES DESIGNINFO DISCARDABLE
|
||||
BEGIN
|
||||
IDD_ASCIIEXPORT_DLG, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 179
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 88
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // English (U.K.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
104
Utils/GinExp/ffd.h
Normal file
104
Utils/GinExp/ffd.h
Normal file
|
@ -0,0 +1,104 @@
|
|||
#ifndef FFD_H
|
||||
#define FFD_H
|
||||
|
||||
#include "iparamm.h"
|
||||
#include "istdplug.h"
|
||||
|
||||
// This is the FFD Modifier's class ID.
|
||||
#define FFD44_CLASS_ID Class_ID(0x21325596, 0x2cd10bd8)
|
||||
#define FFD33_CLASS_ID Class_ID(0x21325596, 0x2cd10bd9)
|
||||
#define FFD22_CLASS_ID Class_ID(0x21325596, 0x2cd10bd0)
|
||||
|
||||
class FFDMod : public Modifier {
|
||||
public:
|
||||
// An addition transformation from "Mod Space".
|
||||
// Let's the user move/rotate/scale the source box
|
||||
Control *tmControl;
|
||||
|
||||
// Parameter block to store parameters
|
||||
IParamBlock *pblock;
|
||||
|
||||
// This BitArray will be set to a length of 64. 1 bit for
|
||||
// each point indicating its selection state.
|
||||
BitArray sel;
|
||||
|
||||
// A cache of the input object's bounding box.
|
||||
Box3 lbox;
|
||||
|
||||
// Class variables -- these are only used by one instance
|
||||
// of this class at a time while it is being edited in
|
||||
// the command panel.
|
||||
static IObjParam *ip;
|
||||
static IParamMap *pmapParam;
|
||||
static MoveModBoxCMode *moveMode;
|
||||
static RotateModBoxCMode *rotMode;
|
||||
static UScaleModBoxCMode *uscaleMode;
|
||||
static NUScaleModBoxCMode *nuscaleMode;
|
||||
static SquashModBoxCMode *squashMode;
|
||||
static SelectModBoxCMode *selectMode;
|
||||
|
||||
FFDMod();
|
||||
~FFDMod();
|
||||
|
||||
// From Animatable
|
||||
void DeleteThis() {delete this;}
|
||||
void BeginEditParams(IObjParam *ip, ULONG flags,Animatable *prev);
|
||||
void EndEditParams(IObjParam *ip,ULONG flags,Animatable *next);
|
||||
CreateMouseCallBack* GetCreateMouseCallBack() {return NULL;}
|
||||
BOOL AssignController(Animatable *control,int subAnim);
|
||||
int SubNumToRefNum(int subNum);
|
||||
BOOL SelectSubAnim(int subNum);
|
||||
|
||||
// From BaseObject/Object
|
||||
int Display(TimeValue t, INode* inode, ViewExp *vpt, int flags, ModContext *mc);
|
||||
void GetWorldBoundBox(TimeValue t,INode* inode, ViewExp *vpt, Box3& box, ModContext *mc);
|
||||
int HitTest(TimeValue t, INode* inode, int type, int crossing, int flags, IPoint2 *p, ViewExp *vpt, ModContext* mc);
|
||||
void SelectSubComponent(HitRecord *hitRec, BOOL selected, BOOL all, BOOL invert=FALSE);
|
||||
void ClearSelection(int selLevel);
|
||||
void SelectAll(int selLevel);
|
||||
void InvertSelection(int selLevel);
|
||||
void ActivateSubobjSel(int level, XFormModes& modes);
|
||||
void Move(TimeValue t, Matrix3& partm, Matrix3& tmAxis, Point3& val, BOOL localOrigin);
|
||||
void Rotate(TimeValue t, Matrix3& partm, Matrix3& tmAxis, Quat& val, BOOL localOrigin);
|
||||
void Scale(TimeValue t, Matrix3& partm, Matrix3& tmAxis, Point3& val, BOOL localOrigin);
|
||||
void GetSubObjectCenters(SubObjAxisCallback *cb,TimeValue t,INode *node,ModContext *mc);
|
||||
void GetSubObjectTMs(SubObjAxisCallback *cb,TimeValue t,INode *node,ModContext *mc);
|
||||
void TransformStart(TimeValue t) {if (ip) ip->LockAxisTripods(TRUE);}
|
||||
void TransformFinish(TimeValue t) {if (ip) ip->LockAxisTripods(FALSE);}
|
||||
void TransformCancel(TimeValue t) {if (ip) ip->LockAxisTripods(FALSE);}
|
||||
|
||||
// From Modifier
|
||||
ChannelMask ChannelsUsed() {return PART_GEOM|PART_TOPO|PART_SELECT|PART_SUBSEL_TYPE;}
|
||||
ChannelMask ChannelsChanged() {return PART_GEOM;}
|
||||
Class_ID InputType() {return defObjectClassID;}
|
||||
Interval LocalValidity(TimeValue t);
|
||||
void ModifyObject(TimeValue t, ModContext &mc, ObjectState *os, INode *node);
|
||||
|
||||
// From ReferenceTarget/Maker
|
||||
int NumRefs() {return 66;}
|
||||
RefTargetHandle GetReference(int i);
|
||||
void SetReference(int i, RefTargetHandle rtarg);
|
||||
int NumSubs() {return 66;}
|
||||
Animatable* SubAnim(int i);
|
||||
TSTR SubAnimName(int i);
|
||||
|
||||
IOResult Load(ILoad *iload);
|
||||
IOResult Save(ISave *isave);
|
||||
|
||||
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message);
|
||||
|
||||
int DrawControlPoints(TimeValue t,ViewExp *vpt,GraphicsWindow *gw,Box3 box,BOOL ht=FALSE,INode *inode=NULL,ModContext *mc=NULL,int flags=0);
|
||||
Matrix3 CompTM(TimeValue t,INode *inode,ModContext *mc);
|
||||
void PlugControllers(TimeValue t);
|
||||
|
||||
virtual int NumCtrlPts()=0;
|
||||
virtual Control* GetPtCont(int i)=0;
|
||||
virtual void SetPtCont(int i,Control *c)=0;
|
||||
virtual Point3& GetPt(int i)=0;
|
||||
virtual Point3 *GetPtPtr()=0;
|
||||
virtual int GridWidth()=0;
|
||||
virtual int GridIndex(int i,int j,int k)=0;
|
||||
virtual Point3 GetControlPoint(TimeValue t, int i, int src=FALSE)=0;
|
||||
};
|
||||
|
||||
#endif
|
68
Utils/GinExp/resource.h
Normal file
68
Utils/GinExp/resource.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Developer Studio generated include file.
|
||||
// Used by asciiexp.rc
|
||||
//
|
||||
#define IDS_VERSION 1
|
||||
#define IDS_ASCIIEXP 1
|
||||
#define IDS_CATEGORY 2
|
||||
#define IDS_EXTENSION1 3
|
||||
#define IDS_LONGDESC 4
|
||||
#define IDS_SHORTDESC 5
|
||||
#define IDS_COPYRIGHT 6
|
||||
#define IDS_PROGRESS_MSG 7
|
||||
#define IDS_PROGRESS_MSG1 7
|
||||
#define IDS_VERSIONSTRING 8
|
||||
#define IDS_LIBDESCRIPTION 9
|
||||
#define IDS_PROGRESS_MSG2 10
|
||||
#define IDD_PANEL 101
|
||||
#define IDD_ABOUTBOX 102
|
||||
#define IDD_ASCIIEXPORT_DLG 103
|
||||
#define IDB_BITMAP1 108
|
||||
#define IDB_BITMAP2 110
|
||||
#define IDB_BITMAP3 113
|
||||
#define IDD_ENDDIALOG 115
|
||||
#define IDB_BITMAP4 116
|
||||
#define IDC_CLOSEBUTTON 1000
|
||||
#define IDC_MESHDATA 1002
|
||||
#define IDC_ANIMKEYS 1003
|
||||
#define IDC_MATERIAL 1004
|
||||
#define IDC_MESHANIM 1005
|
||||
#define IDC_NORMALS 1006
|
||||
#define IDC_SPRITEPAGE 1006
|
||||
#define IDC_TEXCOORDS 1007
|
||||
#define IDC_CAMERAANIM 1007
|
||||
#define IDC_OBJ_GEOM 1008
|
||||
#define IDC_SPRITEPAGE3 1008
|
||||
#define IDC_BONEDATA 1008
|
||||
#define IDC_OBJ_SHAPE 1009
|
||||
#define IDC_BONEANIM 1009
|
||||
#define IDC_OBJ_CAMLIGHT 1010
|
||||
#define IDC_OBJ_CAMERA 1010
|
||||
#define IDC_OBJ_HELPER 1011
|
||||
#define IDC_CAMLIGHTANIM 1013
|
||||
#define IDC_RADIO_USEKEYS 1016
|
||||
#define IDC_RADIO_SAMPLE 1017
|
||||
#define IDC_IKJOINTS 1018
|
||||
#define IDC_OBJ_LIGHT 1019
|
||||
#define IDC_VERTEXCOLORS 1020
|
||||
#define IDC_ANIMCHECK 1023
|
||||
#define IDC_ANIMTEXT 1024
|
||||
#define IDC_CONT_STEP 1155
|
||||
#define IDC_CONT_STEP_SPIN 1156
|
||||
#define IDC_MESH_STEP 1157
|
||||
#define IDC_MESH_STEP_SPIN 1158
|
||||
#define IDC_STATIC_FRAME 1161
|
||||
#define IDC_STATIC_FRAME_SPIN 1162
|
||||
#define IDC_PREC 1163
|
||||
#define IDC_PREC_SPIN 1164
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 118
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1025
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
|
@ -4,11 +4,39 @@
|
|||
|
||||
#include "system\global.h"
|
||||
#include "Game\Thing.h"
|
||||
#include "Gfx\Skel.h"
|
||||
#include "gfx\anim.h"
|
||||
#include "Player\Player.h"
|
||||
|
||||
// to be removed
|
||||
#include "fileio\fileio.h"
|
||||
#include "utils\utils.h"
|
||||
#include "gfx\tpage.h"
|
||||
#include "gfx\prim.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/*****************************************************************************/
|
||||
/*****************************************************************************/
|
||||
CPlayer::CPlayer()
|
||||
{
|
||||
SetRenderObj(&Skel);
|
||||
SetAnimateObj(&Skel);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
CPlayer::~CPlayer()
|
||||
{
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void CPlayer::init()
|
||||
{
|
||||
sActor3dHdr *Hdr=Skel.Load(ACTORS_SPONGEBOB_A3D);
|
||||
Skel.Init(Hdr);
|
||||
TPLoadTex(ACTORS_SPONGEBOB_TEX);
|
||||
Skel.setAnimDatabase(CAnimDB::GetPlayerAnimBank());
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -17,14 +45,7 @@ void CPlayer::shutdown()
|
|||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void CPlayer::think()
|
||||
void CPlayer::Animate()
|
||||
{
|
||||
Skel.Animate(this);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void CPlayer::render()
|
||||
{
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
|
@ -5,9 +5,12 @@
|
|||
#ifndef __PLAYER_H__
|
||||
#define __PLAYER_H__
|
||||
|
||||
#include <dstructs.h>
|
||||
#include "Game/Thing.h"
|
||||
#include "Gfx/Skel.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class CPlayer : public CThing
|
||||
{
|
||||
public:
|
||||
|
@ -16,10 +19,12 @@ virtual ~CPlayer();
|
|||
|
||||
void init();
|
||||
void shutdown();
|
||||
void think();
|
||||
void render();
|
||||
|
||||
void Animate();
|
||||
|
||||
protected:
|
||||
|
||||
CSkel Skel;
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue