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 "system\global.h"
|
||||||
#include "Game\Thing.h"
|
#include "Game\Thing.h"
|
||||||
|
#include "Gfx\Skel.h"
|
||||||
|
#include "gfx\anim.h"
|
||||||
#include "Player\Player.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()
|
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,21 +5,26 @@
|
||||||
#ifndef __PLAYER_H__
|
#ifndef __PLAYER_H__
|
||||||
#define __PLAYER_H__
|
#define __PLAYER_H__
|
||||||
|
|
||||||
|
#include <dstructs.h>
|
||||||
#include "Game/Thing.h"
|
#include "Game/Thing.h"
|
||||||
|
#include "Gfx/Skel.h"
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
class CPlayer : public CThing
|
class CPlayer : public CThing
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CPlayer();
|
CPlayer();
|
||||||
virtual ~CPlayer();
|
virtual ~CPlayer();
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void shutdown();
|
void shutdown();
|
||||||
void think();
|
|
||||||
void render();
|
|
||||||
|
|
||||||
|
void Animate();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
CSkel Skel;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue