diff --git a/Utils/GinExp/ASCIIEXP.DSW b/Utils/GinExp/ASCIIEXP.DSW new file mode 100644 index 000000000..d5b4bf918 --- /dev/null +++ b/Utils/GinExp/ASCIIEXP.DSW @@ -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> +{{{ +}}} + +############################################################################### + diff --git a/Utils/GinExp/ASCIIEXP.opt b/Utils/GinExp/ASCIIEXP.opt new file mode 100644 index 000000000..66eb4776f Binary files /dev/null and b/Utils/GinExp/ASCIIEXP.opt differ diff --git a/Utils/GinExp/ExpAnimKeys.cpp b/Utils/GinExp/ExpAnimKeys.cpp new file mode 100644 index 000000000..3403fae30 --- /dev/null +++ b/Utils/GinExp/ExpAnimKeys.cpp @@ -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; iGetNumKeys(); 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; iGetNumKeys(); 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; iGetNumKeys(); 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; iGetNumKeys(); 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; iGetNumKeys(); 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; iGetNumKeys(); 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; iGetKey(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; iGetKey(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; iGetKey(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; iGetKey(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; iGetKey(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; iGetKey(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; iGetKey(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; iGetKey(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; iGetKey(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; +} diff --git a/Utils/GinExp/ExpBone.cpp b/Utils/GinExp/ExpBone.cpp new file mode 100644 index 000000000..77490345d --- /dev/null +++ b/Utils/GinExp/ExpBone.cpp @@ -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;iGetName(), 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;iGetName(), 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;cGetChildNode(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;cGetChildNode(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; iClassID() == 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; iClassID() == 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; kClassID() == 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; iClassID() == 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 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;cnGetChildNode(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; iClassID() == 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 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;cnGetChildNode(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; iClassID() == 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 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;cnGetChildNode(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; iClassID() == 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 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;cnGetChildNode(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;iGetVertexInterface( 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;nGetNode( 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(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(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 */ diff --git a/Utils/GinExp/ExpCamLight.cpp b/Utils/GinExp/ExpCamLight.cpp new file mode 100644 index 000000000..a9c131a21 --- /dev/null +++ b/Utils/GinExp/ExpCamLight.cpp @@ -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 */ diff --git a/Utils/GinExp/ExpFFD.cpp b/Utils/GinExp/ExpFFD.cpp new file mode 100644 index 000000000..5ee24ee29 --- /dev/null +++ b/Utils/GinExp/ExpFFD.cpp @@ -0,0 +1,550 @@ +#include "max.h" +#include "asciiexp.h" + +#define EDITMESH_CLASS_ID 0x00050 + +typedef Tab Point3Tab; +//typedef Tab AnimPoint3Tab; +typedef Tab 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 TopoOpTab; + +class FaceMap { + public: + DWORD v[3]; + }; +typedef Tab 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 nfaces; // New faces + Tab 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; iGetPoint(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; dwGetPoint(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; iGetObjTMBeforeWSM(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; iGetPtCont(i); + if (c) { + ikeys = GetKeyControlInterface(c); + int blah = c->IsKeyable(); + if (ikeys) { + num = ikeys->GetNumKeys(); + if (num >0) + { + for (int j = 0; jClassID() == 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; jGetObjTMBeforeWSM(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(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(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; +} + diff --git a/Utils/GinExp/ExpFileIo.cpp b/Utils/GinExp/ExpFileIo.cpp new file mode 100644 index 000000000..a727edc1c --- /dev/null +++ b/Utils/GinExp/ExpFileIo.cpp @@ -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 */ diff --git a/Utils/GinExp/ExpFileIo.h b/Utils/GinExp/ExpFileIo.h new file mode 100644 index 000000000..962638c6d --- /dev/null +++ b/Utils/GinExp/ExpFileIo.h @@ -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 */ diff --git a/Utils/GinExp/ExpMain.cpp b/Utils/GinExp/ExpMain.cpp new file mode 100644 index 000000000..9312fa924 --- /dev/null +++ b/Utils/GinExp/ExpMain.cpp @@ -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; idxGetCancel()) 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]]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 */ diff --git a/Utils/GinExp/ExpMaterial.cpp b/Utils/GinExp/ExpMaterial.cpp new file mode 100644 index 000000000..0de6a6bd4 --- /dev/null +++ b/Utils/GinExp/ExpMaterial.cpp @@ -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= 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 (iGetMapDirCount()) + { + 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= MAXCOUNT) MessageBox( MAX_hWnd, "nbTexs Overflow", "ERROR", MB_OK); + } + MatList[matno].SubTex[(subno+1)] = texidx; + } + } + } + + + if (mtl->NumSubMtls() > 0) + { + for (int i=0; iNumSubMtls(); 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= 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; iGetSubMtl(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; iEvalWorldState( 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; icont.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; icont.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; jClassID() == 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; jGetObjTMAfterWSM(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; iGetSubMtl(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; igetNumFaces(); 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= MAXCOUNT) MessageBox( MAX_hWnd, "nbMeshs Overflow", "ERROR", MB_OK); + + } + } + + + // Sort material id's for ease of access + + for (m=0;m MeshSet[m2+1].MatId) + { + MESH_SET meshset = MeshSet[m2]; + MeshSet[m2] = MeshSet[m2+1]; + MeshSet[m2+1] = meshset; + } + } + } + + + for (m=0;mgetNumFaces(); 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; igetNumFaces(); 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; igetNumFaces(); 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; igetNumFaces(); 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;mvertCol) + 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; igetNumFaces(); 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; iGetObjTMAfterWSM( 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; iverts[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; igetNumVerts(); 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; ifaces[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; igetNumFaces(); 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; igetNumVerts(); 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 */ diff --git a/Utils/GinExp/ExpTree.cpp b/Utils/GinExp/ExpTree.cpp new file mode 100644 index 000000000..b1bea22b8 --- /dev/null +++ b/Utils/GinExp/ExpTree.cpp @@ -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;cGetChildNode(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;cGetChildNode(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;cGetChildNode(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;cGetChildNode(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; iNumSubs(); i++) + { + Animatable *a = c->SubAnim(i); + int k = a->NumKeys(); + for (int j=0; jGetKeyTime(j); + if (time > start && time < end) + tl.Add( time ); + } + } + int k = c->NumKeys(); + for (int j=0; jGetKeyTime(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; iClassID() == 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; iClassID() == 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; kClassID() == 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; iClassID() == 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 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;cnGetChildNode(cn); + if (ChildNode) ExportTreeKeyAnim( ChildNode); + } +} + diff --git a/Utils/GinExp/ExpUProp.cpp b/Utils/GinExp/ExpUProp.cpp new file mode 100644 index 000000000..720f420c5 --- /dev/null +++ b/Utils/GinExp/ExpUProp.cpp @@ -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 ); +} diff --git a/Utils/GinExp/Triobjed.h b/Utils/GinExp/Triobjed.h new file mode 100644 index 000000000..a1702308d --- /dev/null +++ b/Utils/GinExp/Triobjed.h @@ -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 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 sets; + Tab 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 *distTab; + Point3Tab &CoordCenters(); + Point3Tab &CoordNormals(); + DWORDTab &VertClusters(); + Tab *EdgeDistTab(int iterations); + void FreeDistTab(); + void FreeCoordCaches(); + void MakeClusterList(); + void InvalidateCoordCaches(BOOL selChange=FALSE); + + NamedSelSetList vselSet; + NamedSelSetList fselSet; + NamedSelSetList eselSet; + Tab 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 &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 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 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 uverts, rverts; + Tab uTverts, rTverts; + Tab ufaces, rfaces; + Tab utvFaces, rtvFaces; + Tab uvertCol, rvertCol; + Tab uvcFaces, rvcFaces; + BitArray uvertSel, ufaceSel, uedgeSel, uvertHide; + BitArray rvertSel, rfaceSel, redgeSel, rvertHide; + BOOL undone; + Tab 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 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 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 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 undo, redo; + Tab 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__ diff --git a/Utils/GinExp/asciiexp.aps b/Utils/GinExp/asciiexp.aps new file mode 100644 index 000000000..53d290ccd Binary files /dev/null and b/Utils/GinExp/asciiexp.aps differ diff --git a/Utils/GinExp/asciiexp.def b/Utils/GinExp/asciiexp.def new file mode 100644 index 000000000..4b0c5eec5 --- /dev/null +++ b/Utils/GinExp/asciiexp.def @@ -0,0 +1,8 @@ +LIBRARY GinExp +EXPORTS + LibDescription @1 + LibNumberClasses @2 + LibClassDesc @3 + LibVersion @4 +SECTIONS + .data READ WRITE diff --git a/Utils/GinExp/asciiexp.dsp b/Utils/GinExp/asciiexp.dsp new file mode 100644 index 000000000..29df88b19 --- /dev/null +++ b/Utils/GinExp/asciiexp.dsp @@ -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 diff --git a/Utils/GinExp/asciiexp.h b/Utils/GinExp/asciiexp.h new file mode 100644 index 000000000..e0b498956 --- /dev/null +++ b/Utils/GinExp/asciiexp.h @@ -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 +#include +#include +#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 +//#include +//#include +//#include + +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 mtlTab; +}; + + +class TimeList { + + TimeValue Value[1000]; + int count; + +public: + + TimeList() { + count = 0; + } + + void Add(TimeValue t) { + int i,j; + for (i = 0 ;it) { + 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 + diff --git a/Utils/GinExp/asciiexp.ncb b/Utils/GinExp/asciiexp.ncb new file mode 100644 index 000000000..5ce0a65d6 Binary files /dev/null and b/Utils/GinExp/asciiexp.ncb differ diff --git a/Utils/GinExp/asciiexp.rc b/Utils/GinExp/asciiexp.rc new file mode 100644 index 000000000..01da49435 --- /dev/null +++ b/Utils/GinExp/asciiexp.rc @@ -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 + diff --git a/Utils/GinExp/ffd.h b/Utils/GinExp/ffd.h new file mode 100644 index 000000000..e97491326 --- /dev/null +++ b/Utils/GinExp/ffd.h @@ -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 \ No newline at end of file diff --git a/Utils/GinExp/resource.h b/Utils/GinExp/resource.h new file mode 100644 index 000000000..ba30c4a5c --- /dev/null +++ b/Utils/GinExp/resource.h @@ -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 diff --git a/source/player/player.cpp b/source/player/player.cpp index 281571a7b..9fd4e84fb 100644 --- a/source/player/player.cpp +++ b/source/player/player.cpp @@ -4,11 +4,39 @@ #include "system\global.h" #include "Game\Thing.h" +#include "Gfx\Skel.h" +#include "gfx\anim.h" #include "Player\Player.h" +// to be removed +#include "fileio\fileio.h" +#include "utils\utils.h" +#include "gfx\tpage.h" +#include "gfx\prim.h" + +/*****************************************************************************/ +/*****************************************************************************/ +/*****************************************************************************/ +CPlayer::CPlayer() +{ + SetRenderObj(&Skel); + SetAnimateObj(&Skel); + +}; + +/*****************************************************************************/ +CPlayer::~CPlayer() +{ +} + /*****************************************************************************/ void CPlayer::init() { +sActor3dHdr *Hdr=Skel.Load(ACTORS_SPONGEBOB_A3D); + Skel.Init(Hdr); + TPLoadTex(ACTORS_SPONGEBOB_TEX); + Skel.setAnimDatabase(CAnimDB::GetPlayerAnimBank()); + } /*****************************************************************************/ @@ -17,14 +45,7 @@ void CPlayer::shutdown() } /*****************************************************************************/ -void CPlayer::think() +void CPlayer::Animate() { + Skel.Animate(this); } - -/*****************************************************************************/ -void CPlayer::render() -{ -} - -/*****************************************************************************/ - diff --git a/source/player/player.h b/source/player/player.h index 1d775cf74..2e66613d4 100644 --- a/source/player/player.h +++ b/source/player/player.h @@ -5,21 +5,26 @@ #ifndef __PLAYER_H__ #define __PLAYER_H__ +#include #include "Game/Thing.h" +#include "Gfx/Skel.h" /*****************************************************************************/ + class CPlayer : public CThing { public: CPlayer(); -virtual ~CPlayer(); + virtual ~CPlayer(); void init(); void shutdown(); - void think(); - void render(); + void Animate(); + protected: + + CSkel Skel; }; /*****************************************************************************/