📄 model.c
字号:
pPath = NewPath;
gePath_Destroy (&pPath);
pPath = geMotion_GetPath (m->pMotion, 0);
// Get the keys from the original path, transform them, and add to the new path
for (iKey = 0; iKey < gePath_GetKeyframeCount (pPath, GE_PATH_TRANSLATION_CHANNEL); ++iKey)
{
geXForm3d XfmXlate;
geXForm3d XfmRotate;
geFloat Time;
// get rotation element
gePath_GetKeyframe (pPath, iKey, GE_PATH_ROTATION_CHANNEL, &Time, &XfmRotate);
// get translation element
gePath_GetKeyframe (pPath, iKey, GE_PATH_TRANSLATION_CHANNEL, &Time, &XfmXlate);
// Make the transform relative to the model's current orientation
{
/*
geXForm3d XfmWork;
geXForm3d XfmObjWldRot;
geVec3d *VecX = &(m->XfmObjectToWorld.Translation);
XfmObjWldRot = m->XfmObjectToWorld;
geVec3d_Clear (&XfmObjWldRot.Translation);
#if 1
geXForm3d_Translate (&XfmRotate, -VecX->X, -VecX->Y, -VecX->Z);
geXForm3d_Multiply (&XfmObjWldRot, &XfmRotate, &XfmRotate);
geXForm3d_Multiply (&XfmObjWldRot, &XfmXlate, &XfmXlate);
geXForm3d_Multiply (&XfmXlate, &XfmRotate, &XfmRotate);
#else
geXForm3d_GetTranspose (&m->XfmObjectToWorld, &XfmWork);
geXForm3d_Multiply (&XfmRotate, &XfmWork, &XfmRotate);
geXForm3d_Multiply (&XfmXlate, &XfmRotate, &XfmRotate);
geXForm3d_Multiply (&m->XfmObjectToWorld, &XfmRotate, &XfmRotate);
#endif
*/
geXForm3d_Multiply (&XfmXlate, &XfmRotate, &XfmRotate);
gePath_InsertKeyframe (NewPath, GE_PATH_ALL_CHANNELS, Time, &XfmRotate);
}
}
// Add events from original motion to the new motion
{
geFloat StartTime = -100000.0f;
geFloat EndTime = 100000.0f;
geFloat EventTime;
char const *EventString;
geMotion_SetupEventIterator (m->pMotion, StartTime, EndTime);
while (geMotion_GetNextEvent (m->pMotion, &EventTime, &EventString) != GE_FALSE)
{
geMotion_InsertEvent (NewMotion, EventTime, EventString);
}
}
// write newly-created motion.
Model_WriteMotionToFile (NewMotion, f);
// geMotion_WriteToFile (NewMotion, f);
// Seems like a lot of work just to destroy it here, huh?
geMotion_Destroy (&NewMotion);
}
}
}
// Write key/value pairs
TypeIO_WriteInt (f, 3); // model
TypeIO_WriteString (f, "classname");
TypeIO_WriteString (f, "%Model%");
TypeIO_WriteString (f, "%name%");
TypeIO_WriteString (f, m->Name);
{
char ValueString[100];
geVec3d const *pVec;
// rotation origin
pVec = &(m->XfmObjectToWorld.Translation);
sprintf (ValueString, "%f %f %f", pVec->X, pVec->Y, pVec->Z);
TypeIO_WriteString (f, "origin");
TypeIO_WriteString (f, ValueString);
}
return 1;
}
struct tag_ModelList
{
Model *First;
};
/////////////// List operations
ModelList *ModelList_Create
(
void
)
// Create and initialize a model list
{
return List_Create ();
}
#ifndef NDEBUG
static geBoolean ModelList_IsInOrder
(
const ModelList *pList
)
{
int LastId;
Model *pModel;
ListIterator li;
LastId = -1;
pModel = (Model *)List_GetFirst ((ModelList *)pList, &li);
while (pModel != NULL)
{
assert (pModel->Id > 0);
if (LastId >= pModel->Id)
{
return GE_FALSE;
}
LastId = pModel->Id;
pModel = List_GetNext ((ModelList *)pList, &li);
}
return GE_TRUE;
}
#endif
static void ModelList_DestroyCallback (void *pData)
{
Model_Destroy ((Model **)&pData);
}
void ModelList_Destroy
(
ModelList **ppList
)
{
List_Destroy (ppList, ModelList_DestroyCallback);
}
static geBoolean FindById_Callback (void *pData, void *lParam)
{
Model *m = (Model *)pData;
int *pId = (int *)lParam;
return (m->Id == *pId);
}
Model *ModelList_FindById
(
ModelList const *pList,
int ModelId
)
{
Model *m;
ListIterator li;
assert (pList != NULL);
if (List_Search ((List *)pList, FindById_Callback, &ModelId, (void **)&m, &li))
{
return m;
}
return NULL;
}
static geBoolean FindByName_Callback (void *pData, void *lParam)
{
Model *m = (Model *)pData;
char *Name = (char *)lParam;
return (stricmp (m->Name, Name) == 0);
}
Model *ModelList_FindByName
(
ModelList const *pList,
char const *Name
)
{
Model *m;
ListIterator li;
assert (pList != NULL);
assert (Name != NULL);
if (List_Search ((List *)pList, FindByName_Callback, (void *)Name, (void **)&m, &li))
{
return m;
}
return NULL;
}
#pragma warning (disable:4100)
static geBoolean IsAnimating_Callback (void *pData, void *lParam)
{
Model *m = (Model *)pData;
return (m->Animating);
}
#pragma warning (default:4100)
Model *ModelList_GetAnimatingModel
(
ModelList const *pList
)
{
Model *pModel;
ListIterator li;
assert (pList != NULL);
if (List_Search ((List *)pList, IsAnimating_Callback, NULL, (void **)&pModel, &li))
{
return pModel;
}
return NULL;
}
static geBoolean ClearBrushModelId (Brush *pBrush, void *lParam)
{
int *pId = (int *)lParam;
if (Brush_GetModelId (pBrush) == *pId)
{
Brush_SetModelId (pBrush, 0);
}
return GE_TRUE;
}
void ModelList_Remove
(
ModelList *pList,
int ModelId,
BrushList *ppBList
)
{
Model *m;
ListIterator li;
assert (pList != NULL);
if (List_Search (pList, FindById_Callback, &ModelId, (void **)&m, &li))
{
BrushList_Enum (ppBList, &ModelId, ClearBrushModelId);
List_Remove (pList, li, NULL);
Model_Destroy (&m);
assert (ModelList_IsInOrder (pList));
}
}
static geBoolean FindNextId_Callback (void *pData, void *lParam)
{
Model *m = (Model *)pData;
int *pId = (int *)lParam;
if (m->Id > *pId)
{
return GE_TRUE;
}
++(*pId);
return GE_FALSE;
}
static Model *ModelList_AddIt
(
ModelList *pList,
char const *Name
)
{
Model *pParent;
Model *NewModel;
ListIterator li;
int ModelId;
assert (pList != NULL);
assert (Name != NULL);
ModelId = 1;
if (!List_Search (pList, FindNextId_Callback, &ModelId, (void **)&pParent, &li))
{
pParent = NULL;
}
NewModel = Model_Create (ModelId, Name);
if (NewModel != NULL)
{
if (pParent == NULL)
{
List_Append (pList, NewModel);
}
else
{
List_InsertBefore (pList, li, NewModel);
}
}
return NewModel;
}
// Creates a model from all of the selected brushes
geBoolean ModelList_Add
(
ModelList *pList,
char const *Name,
SelBrushList *pSelList
)
{
Model *NewModel;
BrushList *pBrushList;
assert (pList != NULL);
assert (ModelList_IsInOrder (pList));
NewModel = ModelList_AddIt (pList, Name);
assert (ModelList_IsInOrder (pList));
if (NewModel != NULL)
{
int ModelId;
ModelId = Model_GetId (NewModel);
// build a brush list from the selected list
// tag all selected brushes with this model id...
pBrushList = BrushList_Create ();
{
int i;
int NumBrushes;
NumBrushes = SelBrushList_GetSize (pSelList);
for (i = 0; i < NumBrushes; i++)
{
Brush *pBrush, *pNewBrush;
pBrush = SelBrushList_GetBrush (pSelList, i);
Brush_SetModelId (pBrush, ModelId);
pNewBrush = Brush_Clone (pBrush);
BrushList_Append (pBrushList, pNewBrush);
}
}
// compute object-to-world transform and save it
Model_ComputeObjectToWorldXfm (NewModel, pBrushList, &NewModel->XfmObjectToWorld);
BrushList_Destroy (&pBrushList);
return GE_TRUE;
}
return GE_FALSE;
}
Model *ModelList_AddFromBrushList
(
ModelList *pList,
char const *Name,
BrushList *pBrushList
)
{
Model *NewModel;
assert (pList != NULL);
assert (Name != NULL);
assert (pBrushList != NULL);
assert (ModelList_IsInOrder (pList));
NewModel = ModelList_AddIt (pList, Name);
assert (ModelList_IsInOrder (pList));
if (NewModel != NULL)
{
int ModelId;
BrushIterator bi;
Brush *pBrush;
ModelId = Model_GetId (NewModel);
pBrush = BrushList_GetFirst (pBrushList, &bi);
while (pBrush != NULL)
{
Brush_SetModelId (pBrush, ModelId);
pBrush = BrushList_GetNext (&bi);
}
Model_ComputeObjectToWorldXfm (NewModel, pBrushList, &NewModel->XfmObjectToWorld);
}
return NewModel;
}
int ModelList_GetCount
(
ModelList const *pList
)
// I guess I could maintain a count, but it seems easier
// to just go through and count 'em here...
{
Model *pModel;
ModelIterator mi;
int Count;
assert (pList != NULL);
Count = 0;
pModel = ModelList_GetFirst (pList, &mi);
while (pModel != NULL)
{
++Count;
pModel = ModelList_GetNext (pList, &mi);
}
return Count;
}
geBoolean ModelList_Write
(
ModelList const *pList,
FILE *f
)
{
Model const *m;
ListIterator li;
assert (pList != NULL);
assert (f != NULL);
m = (const Model *)List_GetFirst ((List *)pList, &li);
while (m != NULL)
{
if (!Model_Write (m, f)) return GE_FALSE;
m = (const Model *)List_GetNext ((List *)pList, &li);
}
return GE_TRUE;
}
static geBoolean FindInsertionSpot_Callback (void *pData, void *lParam)
{
Model *pInList = (Model *)pData;
Model *pNew = (Model *)lParam;
return (pInList->Id >= pNew->Id);
}
// Insert a model into the list in ascending order.
static void ModelList_Insert
(
ModelList *pList,
Model *pModel
)
{
Model *p; // parent
ListIterator li;
if (List_Search (pList, FindInsertionSpot_Callback, pModel, (void **)&p, &li))
{
List_InsertBefore (pList, li, pModel);
}
else
{
List_Append (pList, pModel);
}
}
void ModelList_AddModel
(
ModelList *pList,
Model *pModel
)
{
assert (pList != NULL);
assert (pModel != NULL);
ModelList_Insert (pList, pModel);
}
// Must ensure that models are inserted into the list in ascending order!
geBoolean ModelList_Read
(
ModelList *pList,
int nModels, // so we know how many to read
Parse3dt *Parser,
int VersionMajor,
int VersionMinor,
const char **Expected
)
{
int Count;
assert (pList != NULL);
// list end pointer for fast append
for (Count = 0; Count < nModels; Count++)
{
Model *m;
m = Model_CreateFromFile (Parser, VersionMajor, VersionMinor, Expected);
if (m == NULL)
{
return GE_FALSE;
}
ModelList_Insert (pList, m);
}
assert (ModelList_IsInOrder (pList));
return GE_TRUE;
}
geBoolean ModelList_WriteToMap
(
ModelList const *pList,
FILE *f,
BrushList const * ppBList,
geBoolean SuppressHidden,
geBoolean VisDetail
)
{
Model *m;
ListIterator li;
m = List_GetFirst ((List *)pList, &li);
while (m != NULL)
{
Model_WriteToMap (m, f, ppBList, SuppressHidden, VisDetail);
m = List_GetNext ((List *)pList, &li);
}
return GE_TRUE;;
}
void ModelList_ScaleAll
(
ModelList *pList,
geFloat ScaleFactor
)
{
Model *m;
ListIterator li;
assert (pList != NULL);
assert (ScaleFactor > 0.0f);
m = List_GetFirst (pList, &li);
while (m != NULL)
{
Model_Scale (m, ScaleFactor);
m = List_GetNext (pList, &li);
}
}
Model *ModelList_GetFirst
(
ModelList const *pList,
ModelIterator *mi
)
{
assert (pList != NULL);
assert (mi != NULL);
return (Model *)List_GetFirst ((List *)pList, mi);
}
Model *ModelList_GetNext
(
ModelList const *pList,
ModelIterator *mi
)
{
assert (pList != NULL);
assert (mi != NULL);
return (Model *)List_GetNext ((List *)pList, mi);
}
typedef struct
{
int OldId;
int NewId;
} Model_MapEntry;
static geBoolean Model_RenumBrush (Brush *pBrush, void *lParam)
{
Model_MapEntry *Mappings;
int i, ModelId;
Mappings = (Model_MapEntry *)lParam;
ModelId = Brush_GetModelId (pBrush);
for (i = 0; Mappings[i].OldId != 0; ++i)
{
if (Mappings[i].OldId == ModelId)
{
Brush_SetModelId (pBrush, Mappings[i].NewId);
break;
}
}
return GE_TRUE;
}
void ModelList_Collapse
(
ModelList *pList,
int StartingModel,
BrushList *Brushes
)
{
int nEntries;
assert (pList != NULL);
assert (StartingModel > 0);
assert (Brushes != NULL);
nEntries = ModelList_GetCount (pList);
if (nEntries > 0)
{
Model_MapEntry *Mappings;
Mappings = (Model_MapEntry *)geRam_Allocate ((nEntries + 1) * sizeof (Model_MapEntry));
if (Mappings != NULL)
{
int i;
Model *m;
ListIterator li;
m = (Model *)List_GetFirst (pList, &li);
i = 0;
while (m != NULL)
{
assert (m->Id != 0);
Mappings[i].OldId = m->Id;
Mappings[i].NewId = i+StartingModel;
m->Id = i+StartingModel;
++i;
m = (Model *)List_GetNext (pList, &li);
}
Mappings[i].OldId = 0; // stop sentinel
Mappings[i].NewId = 0;
BrushList_Enum (Brushes, Mappings, Model_RenumBrush);
geRam_Free (Mappings);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -