SBSPSS/Utils/GinExp/ExpFFD.cpp
2001-01-12 22:40:39 +00:00

551 lines
14 KiB
C++

#include "max.h"
#include "asciiexp.h"
#define EDITMESH_CLASS_ID 0x00050
typedef Tab<Point3> Point3Tab;
//typedef Tab<AnimPoint3> AnimPoint3Tab;
typedef Tab<Face> FaceTab;
class XFormProc {
public:
virtual Point3 proc(Point3& p, Matrix3 &mat, Matrix3 &imat)=0;
virtual void SetMat( Matrix3& mat ) {}
};
class MoveXForm : public XFormProc {
private:
Point3 delta, tdelta;
public:
Point3 proc(Point3& p, Matrix3 &mat, Matrix3 &imat)
{ return p + tdelta; }
void SetMat( Matrix3& mat )
{ tdelta = VectorTransform(Inverse(mat),delta); }
MoveXForm(Point3 d) { delta = d; }
};
class RotateXForm : public XFormProc {
private:
Matrix3 rot, trot;
public:
Point3 proc(Point3& p, Matrix3 &mat, Matrix3 &imat)
{ return (trot*p)*imat; }
void SetMat( Matrix3& mat )
{ trot = mat * rot; }
RotateXForm(Quat q) { q.MakeMatrix(rot); }
};
class ScaleXForm : public XFormProc {
private:
Matrix3 scale, tscale;
public:
Point3 proc(Point3& p, Matrix3 &mat, Matrix3 &imat)
{ return (p*tscale)*imat; }
void SetMat( Matrix3& mat )
{ tscale = mat*scale; }
ScaleXForm(Point3 s) { scale = ScaleMatrix(s); }
};
class VertexDelta {
public:
Point3Tab deltas; //DS-- I needed this public
BitArray hide;
void SetSize(int size, BOOL clear=TRUE);
Point3 operator[](int i);
void Set(TimeValue t,int i, Point3& p);
void Move(TimeValue t,int i, const Point3& p);
void Apply(TimeValue t,Mesh& mesh);
void Scale(float f);
VertexDelta& operator=(VertexDelta& from);
~VertexDelta();
VertexDelta();
};
class TopoOp {
public:
virtual void Apply(Mesh& mesh)=0;
virtual TopoOp *Clone()=0;
virtual ~TopoOp() {}
};
typedef Tab<TopoOp*> TopoOpTab;
class FaceMap {
public:
DWORD v[3];
};
typedef Tab<FaceMap> FaceMapTab;
// Bits for attribs:
// First 3 bits are edge visibility
// 4th bit is face visibility
// 29,30 and 31 indicate which if any should be applied
#define ATTRIB_APPLY_EDGE (1<<31)
#define ATTRIB_APPLY_FACE (1<<30)
#define ATTRIB_APPLY_MATID (1<<29)
#define ATTRIB_APPLY_SMGROUP (1<<28)
// Mat ID takes bit 5-21
#define ATTRIB_MATID_SHIFT 5
#define ATTRIB_MATID_MASK 0xffff
class TopoDelta {
public:
DWORDTab cverts; // Clone verts
DWORDTab dverts; // Delete verts
Point3Tab nverts; // Add verts
Point3Tab nTverts; // Add texture verts
DWORDTab dfaces; // Delete faces
Tab<Face> nfaces; // New faces
Tab<TVFace> nTVfaces; // New texture vert faces
FaceMapTab map; // Remap faces
FaceMapTab tmap; // TVFace remap
DWORDTab attribs; // Changes attributes of a face.
DWORDTab smgroups; // Changes smooth groups for a face.
DWORD inputFaces; // Number of faces on input mesh
DWORD inputVerts; // Number of vertices input mesh has
};
class EditMeshData : public LocalModData {
public:
DWORD flags;
// These record the changes to the incomming object.
VertexDelta vdelta;
TopoDelta tdelta;
// The selection sets.
BitArray vsel;
BitArray fsel;
BitArray esel;
// Lists of named selection sets
NamedSelSetList vselSet;
NamedSelSetList fselSet;
NamedSelSetList eselSet;
// While an object is being edited, this exists.
// EMTempData *tempData;
};
inline float BPoly4(int i, float u)
{
float s = 1.0f-u;
switch (i) {
case 0: return s*s*s;
case 1: return 3.0f*u*s*s;
case 2: return 3.0f*u*u*s;
case 3: return u*u*u;
default: return 0.0f;
}
}
inline float BPoly3(int i, float u)
{
float s = 1.0f-u;
switch (i) {
case 0: return s*s;
case 1: return 2.0f*u*s;
case 2: return u*u;
default: return 0.0f;
}
}
inline float BPoly2(int i, float u)
{
switch (i) {
case 0: return 1.0f-u;
case 1: return u;
default: return 0.0f;
}
}
#define EPSILON 0.001f
Point3 FfdLatticeSize(Box3 box)
{
Point3 size = box.Max()-box.Min();
if (size.x==0.0f) size.x = 0.001f;
if (size.y==0.0f) size.y = 0.001f;
if (size.z==0.0f) size.z = 0.001f;
return size;
}
Matrix3 FFDMod::CompTM(TimeValue t,INode *inode,ModContext *mc)
{
// Compute a the transformation out of lattice space into world space
Matrix3 ntm = inode->GetObjTMBeforeWSM(t);
Matrix3 ctm(1);
if (mc && mc->tm) {
ntm = Inverse(*(mc->tm)) * ntm;
}
tmControl->GetValue(t,&ctm,FOREVER,CTRL_RELATIVE);
return ctm * ntm;
}
Box3 ComputeBBox(TimeValue t, INode *node) {
Box3 box; // The computed box
Matrix3 mat; // The Object TM
Matrix3 sclMat(1); // This will be used to apply the scaling
// Get the result of the pipeline at the current time
Object *obj = node->EvalWorldState(t).obj;
// Determine if the object is in world space or object space
// so we can get the correct TM. We can check this by getting
if (node->GetObjTMAfterWSM(t).IsIdentity()) {
mat = Inverse(node->GetObjTMBeforeWSM(t));
} else {
// It's in object space, get the Object TM.
mat = node->GetObjectTM(t);
}
// Extract just the scaling part from the TM
AffineParts parts;
decomp_affine(mat, &parts);
//ApplyScaling(sclMat, ScaleValue(parts.k*parts.f, parts.u));
// Get the bound box, and affect it by just
// the scaling portion
obj->GetDeformBBox(t, box, &sclMat);
return box;
}
void AsciiExp::ExportFFD( INode* node , FFDMod *FfdMod, ModContext *mc, Mesh *mesh)
{
TimeValue start = ip->GetAnimRange().Start();
TimeValue end = ip->GetAnimRange().End();
int delta = GetTicksPerFrame();
int nbCtrlPnts;
TimeValue t;
int i;
int Depth;
int Width;
int Height;
if (node->IsNodeHidden())
return;
if (FfdMod) {
ObjectState os;
Object * obj;
os = node->EvalWorldState( 0 );
obj = node->GetObjectRef();
while (obj && obj->SuperClassID() == GEN_DERIVOB_CLASS_ID) {
obj = ((IDerivedObject*)obj)->GetObjRef();
}
if (!obj) return;
if (FfdMod->ClassID() == FFD44_CLASS_ID) {
Depth = Width = Height = 4;
} else
if (FfdMod->ClassID() == FFD33_CLASS_ID) {
Depth = Width = Height = 3;
} else
if (FfdMod->ClassID() == FFD22_CLASS_ID) {
Depth = Width = Height = 2;
}
// Evaluate the TM controller
Matrix3 ctm(1);
FfdMod->tmControl->GetValue(start,&ctm,FOREVER,CTRL_RELATIVE);
// Get the ModContext TM (if there is one)
Matrix3 tm = mc->tm ? *mc->tm : Matrix3(1);
// Apply our TM to the MC TM
tm *= Inverse(ctm);
// The origin of the TM is the lower left corner of the
// box, not the center.
tm.SetTrans(tm.GetTrans()-mc->box->Min());
// Compute scale factors to normalize lattice space
// to the extents of the box.
Point3 s = FfdLatticeSize(*mc->box);
for (i=0; i<3; i++) {
if (s[i]==0.0f) s[i] = 1.0f;
else s[i] = 1.0f/s[i];
}
tm.Scale(s,TRUE);
Matrix3 itm = Inverse(tm);
AffineParts ap;
decomp_affine(tm, &ap);
nbCtrlPnts = FfdMod->NumCtrlPts();
WriteChunkHdr( (char*)FFD_ID, 0);
fwrite( &nCurObj, sizeof( Uint32 ), 1, expStream );
fwrite( &FfdNum, sizeof(Uint32), 1, expStream);
fwrite( &Width, sizeof( Uint32 ), 1, expStream );
fwrite( &Height, sizeof( Uint32 ), 1, expStream );
fwrite( &Depth, sizeof( Uint32 ), 1, expStream );
MRow *mr = tm.GetAddr();
fwrite( &mr[0][0], sizeof(MRow),1,expStream);
fwrite( &mr[1][0], sizeof(MRow),1,expStream);
fwrite( &mr[2][0], sizeof(MRow),1,expStream);
fwrite( &mr[3][0], sizeof(MRow),1,expStream);
int dd,dw,dh;
int nv = obj->NumPoints();
/* for (i=0; i<nv; i++) {
float tw = 0.f;
for (dw = 0; dw<Width; dw++) {
for (dd = 0; dd<Depth; dd++) {
for (dh = 0; dh<Height; dh++) {
float w;
Point3 pp = tm*obj->GetPoint(i);
if (pp.x>=-0.001f && pp.x<=1.001f && pp.y>=-0.001f && pp.y<=1.001f && pp.z>=-0.001f && pp.z<=1.001f) {
if (FfdMod->ClassID() == FFD44_CLASS_ID) {
w = BPoly4(dw,pp.x) * BPoly4(dd,pp.y) * BPoly4(dh,pp.z);
} else
if (FfdMod->ClassID() == FFD33_CLASS_ID) {
w = BPoly3(dw,pp.x) * BPoly3(dd,pp.y) * BPoly3(dh,pp.z);
} else
if (FfdMod->ClassID() == FFD22_CLASS_ID) {
w = BPoly2(dw,pp.x) * BPoly2(dd,pp.y) * BPoly2(dh,pp.z);
}
} else {
w = 0;
}
tw+=w;
}
}
}
}*/
fprintf( tempStream, "node = %s\n\n", node->GetName() );
fprintf( tempStream, "selected = ");
BitArray Selection = mesh->VertexTempSel();
for (dw = 0; dw<Width; dw++) {
for (dd = 0; dd<Depth; dd++) {
for (dh = 0; dh<Height; dh++) {
for (i=0; i<nv; i++) {
float w;
Point3 pp = tm*obj->GetPoint(i);
//if (pp.x>=-0.0001f && pp.x<=1.0001f && pp.y>=-0.0001f && pp.y<=1.0001f && pp.z>=-0.0001f && pp.z<=1.0001f) {
if (Selection[i])
{
if (FfdMod->ClassID() == FFD44_CLASS_ID) {
w = BPoly4(dw,pp.x) * BPoly4(dd,pp.y) * BPoly4(dh,pp.z);
} else
if (FfdMod->ClassID() == FFD33_CLASS_ID) {
w = BPoly3(dw,pp.x) * BPoly3(dd,pp.y) * BPoly3(dh,pp.z);
} else
if (FfdMod->ClassID() == FFD22_CLASS_ID) {
w = BPoly2(dw,pp.x) * BPoly2(dd,pp.y) * BPoly2(dh,pp.z);
}
fprintf( tempStream, "%d %f, ", i, w);
} else {
w = 0;
}
fwrite(&w, sizeof(float), 1, expStream);
}
fprintf( tempStream, "\nendselected\n");
}
}
}
WriteChunkHdr( (char*)ANIM_ID, 0);
fwrite( &CHANNEL_TYPE_FFD, sizeof( Uint32 ), 1, expStream );
fwrite( &nCurObj, sizeof( Uint32 ), 1, expStream );
fwrite( &totFrames, sizeof( Uint32 ), 1, expStream );
fwrite( &FfdNum, sizeof(Uint32), 1, expStream);
fwrite( &Width, sizeof( Uint32 ), 1, expStream );
fwrite( &Height, sizeof( Uint32 ), 1, expStream );
fwrite( &Depth, sizeof( Uint32 ), 1, expStream );
for (i=0; i<nbCtrlPnts; i++) {
for (t=start; t<=end; t+=delta) {
Matrix3 ntm = node->GetObjTMBeforeWSM(t);
Matrix3 ctm(1);
if (mc && mc->tm) {
ntm = Inverse(*(mc->tm)) * ntm;
}
FfdMod->tmControl->GetValue(t,&ctm,FOREVER,CTRL_RELATIVE);
Matrix3 mm = ctm * ntm;
Box3 lbox = *mc->box;
Matrix3 stm = ScaleMatrix(FfdLatticeSize(lbox));
stm.SetTrans(lbox.Min());
Point3 np = FfdMod->GetControlPoint(t,i);
Point3 p = stm*FfdMod->GetControlPoint(t, i);
Point3 p2 = mm * p;
fwrite(&p2.x, sizeof(float), 1, expStream);
fwrite(&p2.z, sizeof(float), 1, expStream);
fwrite(&p2.y, sizeof(float), 1, expStream);
}
}
TimeValue start = ip->GetAnimRange().Start();
TimeValue end = ip->GetAnimRange().End();
int delta = GetTicksPerFrame();
Control *c;
WriteChunkHdr( (char*)KEY_ID, 0);
fwrite( &CHANNEL_TYPE_FFD, sizeof( Uint32 ), 1, expStream );
fwrite( &CHANNEL_INFO_ALL, sizeof( Uint32) , 1, expStream);
fwrite( &nCurObj, sizeof( Uint32), 1, expStream );
fwrite( &FfdNum, sizeof(Uint32), 1, expStream);
fwrite( &nbCtrlPnts, sizeof( Uint32), 1, expStream );
for (i=0; i<nbCtrlPnts; i++) {
TimeList tl;
IKeyControl *ikeys;
ITCBPoint3Key tcbPosKey;
ITCBRotKey tcbRotKey;
ITCBScaleKey tcbSclKey;
IBezPoint3Key bezPosKey;
IBezQuatKey bezRotKey;
IBezScaleKey bezSclKey;
ILinPoint3Key linPosKey;
ILinRotKey linRotKey;
ILinScaleKey linSclKey;
int num;
TimeValue time;
tl.Clear();
c = FfdMod->GetPtCont(i);
if (c) {
ikeys = GetKeyControlInterface(c);
int blah = c->IsKeyable();
if (ikeys) {
num = ikeys->GetNumKeys();
if (num >0)
{
for (int j = 0; j<num; j++) {
if (c->ClassID() == Class_ID(TCBINTERP_POINT3_CLASS_ID, 0)) {
ikeys->GetKey(j, &tcbPosKey);
time = tcbPosKey.time;
} else
if (c->ClassID() == Class_ID(HYBRIDINTERP_POINT3_CLASS_ID, 0)) {
ikeys->GetKey(j, &bezPosKey);
time = bezPosKey.time;
}
tl.Add(time);
}
}
}
}
if (!tl.Count()) {
tl.Add(ip->GetAnimRange().Start());
}
num = tl.Count();
fwrite(&num, sizeof(int), 1, expStream);
for ( int j = 0; j<num; j++) {
time = tl.Get(j);
Matrix3 ntm = node->GetObjTMBeforeWSM(time);
Matrix3 ctm(1);
if (mc && mc->tm) {
ntm = Inverse(*(mc->tm)) * ntm;
}
FfdMod->tmControl->GetValue(time,&ctm,FOREVER,CTRL_RELATIVE);
Matrix3 mm = ctm * ntm;
Box3 lbox = *mc->box;
Matrix3 stm = ScaleMatrix(FfdLatticeSize(lbox));
stm.SetTrans(lbox.Min());
Point3 np = FfdMod->GetControlPoint(time,i);
Point3 p = stm*FfdMod->GetControlPoint(time, i);
Point3 p2 = mm * p;
time = (time - start)/delta;
fwrite(&time, sizeof(int), 1, expStream);
fwrite(&p2.x, sizeof(float), 1, expStream);
fwrite(&p2.z, sizeof(float), 1, expStream);
fwrite(&p2.y, sizeof(float), 1, expStream);
}
}
}
}
bool AsciiExp::FindFFDModifier (INode* node)
{
// Get object from node. Abort if no object.
Object* ObjectPtr = node->GetObjectRef();
FfdNum = 0;
bool Found= false;
if (!ObjectPtr)
return false;
// Is derived object ?
int needDel;
while (ObjectPtr->SuperClassID() == GEN_DERIVOB_CLASS_ID)
{
IDerivedObject* DerivedObjectPtr = static_cast<IDerivedObject*>(ObjectPtr);
ObjectPtr = DerivedObjectPtr->GetObjRef();
}
TriObject * tri = GetTriObjectFromObject(ObjectPtr, ip->GetAnimRange().Start(), needDel);
if (!tri) return false;
Mesh* mesh = &tri->mesh;
BitArray SaveVtx = mesh->vertSel;
BitArray SaveFce = mesh->faceSel;
BitArray SaveEdg = mesh->edgeSel;
ObjectPtr = node->GetObjectRef();
while (ObjectPtr->SuperClassID() == GEN_DERIVOB_CLASS_ID)
{
// Yes -> Cast.
IDerivedObject* DerivedObjectPtr = static_cast<IDerivedObject*>(ObjectPtr);
// Iterate over all entries of the modifier stack.
int ModStackIndex = DerivedObjectPtr->NumModifiers() - 1;
while (ModStackIndex >= 0 )
{
// Get current modifier.
Modifier* ModifierPtr = DerivedObjectPtr->GetModifier(ModStackIndex);
ModContext *modContext = DerivedObjectPtr->GetModContext(ModStackIndex);
// Is this FFD ?
if (ModifierPtr->ClassID() == FFD44_CLASS_ID ||
ModifierPtr->ClassID() == FFD33_CLASS_ID ||
ModifierPtr->ClassID() == FFD22_CLASS_ID)
{
// Yes -> Exit.
ExportFFD(node, (FFDMod*)ModifierPtr, modContext, mesh);
FfdNum++;
Found = true;
} else
if (ModifierPtr->ClassID() == Class_ID(EDITMESH_CLASS_ID,0))
{
EditMeshData *meshData = (EditMeshData*)modContext->localData;
mesh->vertSel = meshData->vsel;
mesh->faceSel = meshData->fsel;
mesh->edgeSel = meshData->esel;
}
// Next modifier stack entry.
ModStackIndex--;
}
ObjectPtr = DerivedObjectPtr->GetObjRef();
}
mesh->vertSel = SaveVtx;
mesh->faceSel = SaveFce;
mesh->edgeSel = SaveEdg;
if (needDel) delete tri;
return Found;
}