⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 model.c

📁 3D游戏场景编辑器
💻 C
📖 第 1 页 / 共 3 页
字号:
				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 + -