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

📄 render.cpp

📁 游戏《家园》源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
// Copyright (c) 1998-99 Relic Entertainment Inc.
// Written by Janik Joire
//
// $History: $

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <ddraw.h>
#include "render.h"
#include "directdraw.h"
#include "matrix.h"
#include "lwob.h"
#include "euler.h"

// Global variables
float aAxisx[3]={1.0F,0.0F,0.0F};
float aAxisy[3]={0.0F,1.0F,0.0F};
float aAxisz[3]={0.0F,0.0F,1.0F};

// Default object (cube, 1 cubic kilometer)
float REND_DAORIG[3]={0.0F,0.0F,0.0F};
float REND_DASIZE[3]={1000.0F,1000.0F,1000.0F};

float REND_DAVERTS[REND_DNVERTS]=
{
	-500.0F,-500.0F,-500.0F,	// 0
	-500.0F, 500.0F, 500.0F,	// 1
	-500.0F, 500.0F,-500.0F,	// 2
	-500.0F,-500.0F, 500.0F,	// 3
	 500.0F,-500.0F,-500.0F,	// 4
	 500.0F, 500.0F, 500.0F,	// 5
	 500.0F, 500.0F,-500.0F,	// 6
	 500.0F,-500.0F, 500.0F		// 7
};

short REND_DAPOLYS[REND_DNPOLYS]=
{
	2,0,3,3,1,2,	// side
	6,4,0,0,2,6,	// side
	5,6,2,2,1,5,	// side
	7,5,1,1,3,7,	// side
	4,7,3,3,0,4,	// side
	7,4,6,6,5,7		// side
};

unsigned long nSizeOfFloatTimes3;

float fOneOver3;

RENDOBJ *pFirst;
RENDOBJ *pLast;

__declspec(dllexport) int __stdcall rendInit(void)
{
	// Reset first and last object
	pFirst=NULL;
	pLast=NULL;

	// Reset common operatoins
	nSizeOfFloatTimes3=sizeof(float)*3;
	fOneOver3=1.0F/3.0F;

	return(OK);
}

__declspec(dllexport) int __stdcall rendClean(void)
{
	while(1)
	{
		// Check first object
		if(pFirst == NULL) break;

		// Delete first object
		rendDelObj(pFirst);
	}

	return(OK);
}

__declspec(dllexport) int __stdcall rendAngCheck(float *x,float *y,float *z)
{
	// Check angles for exceptions
	if(((*x < REND_AMIN+0.5F) && (*z < REND_AMIN+0.5F)) || ((*x > REND_AMAX-0.5F) && (*z > REND_AMAX-0.5F)))
	{
		// Adjust angles
		*x=0.0F;
		if(*y > 0.0F) *y=180.0F-*y;
		else *y=-(180.0F+*y);
		*z=0.0F;

		return(ERR);
	}

	return(OK);
}

__declspec(dllexport) int __stdcall rendAngConv(float *fAngh,float *fAngv,float x,float y,float z)
{
	float aTransform[16],aWork[3];
	
	// Check angles
	if(x > REND_AMAX) x=REND_AMIN;
	if(x < REND_AMIN) x=REND_AMAX;
	if(y > REND_AMAX) y=REND_AMIN;
	if(y < REND_AMIN) y=REND_AMAX;
	if(z > REND_AMAX) z=REND_AMIN;
	if(z < REND_AMIN) z=REND_AMAX;

	// Set transformation matrix to identity matrix
	matIdentity(aTransform);

	// Set rotation
	matRotate(aTransform,aAxisx,x);
	matRotate(aTransform,aAxisy,y);
	matRotate(aTransform,aAxisz,z);

	// Set data
	memcpy(aWork,aAxisx,nSizeOfFloatTimes3);

	// Transform to world
	matVectProduct(NULL,aWork,aTransform);
	
	// Calc horizontal angle
	*fAngh=(float)((aWork[2] >= 0.0F)?1.0F:-1.0F)*(float)acos(aWork[0]/(float)sqrt(aWork[0]*aWork[0]+aWork[2]*aWork[2]))*180.0F/PI;

	// Calc vertical angle
	*fAngv=(float)asin(aWork[1]/(float)sqrt(aWork[0]*aWork[0]+aWork[1]*aWork[1]+aWork[2]*aWork[2]))*180.0F/PI;

	return(OK);
}

__declspec(dllexport) int __stdcall rendNewObj(RENDOBJ **pObj,int nKey,char *szUID)
{
	short n,m,nTn,nTno,nTnt,nVert;

	float fWork;
	float aVerts[LWOB_SIZE][3],aNorm[3],aMin[3],aMax[3];
	
	FILE *pStream;
	
	RENDOBJ *pCur;

	// Reset object
	*pObj=NULL;

	// Check UID
	if((szUID == NULL) || (strlen(szUID) == 0)) return(OK);
		
	// Allocate memory for new object
	*pObj=(RENDOBJ *)malloc(sizeof(RENDOBJ));
	if(*pObj == NULL) return(ERR);

	// Set UID
	strncpy((*pObj)->szUID,szUID,255);

	// Set key, default mode, default color
	(*pObj)->nKey=nKey;
	(*pObj)->nMode=REND_OSHOW;
	(*pObj)->nCol=REND_WHITE;

	// Reset translation and rotation data
	memset(&((*pObj)->aTrans),0,nSizeOfFloatTimes3);
	memset(&((*pObj)->aRot),0,nSizeOfFloatTimes3);

	// Set scale data to default
	(*pObj)->aScale[0]=REND_OSCALE;
	(*pObj)->aScale[1]=REND_OSCALE;
	(*pObj)->aScale[2]=REND_OSCALE;
	
	// Set transformation matrix to identity matrix
	matIdentity((*pObj)->aTransform);
	
	// Set prev, next and link objects
	(*pObj)->pPrev=pLast;
	(*pObj)->pNext=NULL;
	(*pObj)->pLink=NULL;

	// Set first and last object
	if(pLast == NULL) pFirst=*pObj;
	else pLast->pNext=*pObj;
	pLast=*pObj;

	// Set pointer to first object
	pCur=pFirst;
	
	// Find other objects with same polys/vertices
	while(1)
	{
		// Check pointer
		if(pCur == NULL) break;

		// Check UID
		if((*pObj != pCur) && (strcmp((*pObj)->szUID,pCur->szUID) == 0)) break;

		// Set pointer to next object
		pCur=pCur->pNext;
	}

	// Check temp object
	if(pCur == NULL)
	{
		// Open LWOB file
		pStream=fopen((*pObj)->szUID,"rb");
		if(pStream == NULL)
		{
			// Reset UID
			strcpy((*pObj)->szUID," ");
 
			// Set number of polys and  vertices to default
			(*pObj)->nPolys=REND_DNPOLYS/LWOB_SIZE;
			(*pObj)->nVerts=REND_DNVERTS/3;

			// Set origin, size and selection average to default
			memcpy((*pObj)->aOrig,REND_DAORIG,nSizeOfFloatTimes3);
			memcpy((*pObj)->aSize,REND_DASIZE,nSizeOfFloatTimes3);
			(*pObj)->fSel=REND_DFSEL;

			// Set pointers to polys and vertices to default
			(*pObj)->pPolys=REND_DAPOLYS;
			(*pObj)->pVerts=REND_DAVERTS;
		}
		else
		{
			// Get polys and vertices from LOB file
			if(GetLwobData(pStream,&((*pObj)->nVerts),&((*pObj)->nPolys),
				&((*pObj)->pVerts),&((*pObj)->pPolys)) < 0)
			{
				// Reset UID
				strcpy((*pObj)->szUID," ");
 
				// Set number of polys and  vertices to default
				(*pObj)->nPolys=REND_DNPOLYS/LWOB_SIZE;
				(*pObj)->nVerts=REND_DNVERTS/3;

				// Set origin, size and selection average to default
				memcpy((*pObj)->aOrig,REND_DAORIG,nSizeOfFloatTimes3);
				memcpy((*pObj)->aSize,REND_DASIZE,nSizeOfFloatTimes3);
				(*pObj)->fSel=REND_DFSEL;

				// Set pointers to polys and vertices to default
				(*pObj)->pPolys=REND_DAPOLYS;
				(*pObj)->pVerts=REND_DAVERTS;
			}

			// Close LWOB file
			fclose(pStream);
		}

		// Set minimum
		aMin[0]=0.0F;
		aMin[1]=0.0F;
		aMin[2]=0.0F;

		// Set maximum
		aMax[0]=0.0F;
		aMax[1]=0.0F;
		aMax[2]=0.0F;

		// Loop thru vertices
		for(n=0;n<(*pObj)->nVerts;n++)
		{
			nTn=3*n;
			nTno=nTn+1;
			nTnt=nTn+2;

			// Check X coordinate
			if(aMax[0] < (*pObj)->pVerts[nTn]) aMax[0]=(*pObj)->pVerts[nTn];
			if(aMin[0] > (*pObj)->pVerts[nTn]) aMin[0]=(*pObj)->pVerts[nTn];

			// Check Y coordinate
			if(aMax[1] < (*pObj)->pVerts[nTno]) aMax[1]=(*pObj)->pVerts[nTno];
			if(aMin[1] > (*pObj)->pVerts[nTno]) aMin[1]=(*pObj)->pVerts[nTno];

			// Check Z coordinate
			if(aMax[2] < (*pObj)->pVerts[nTnt]) aMax[2]=(*pObj)->pVerts[nTnt];
			if(aMin[2] > (*pObj)->pVerts[nTnt]) aMin[2]=(*pObj)->pVerts[nTnt];
		}

		// Set origin
		(*pObj)->aOrig[0]=(aMax[0]+aMin[0])/2.0F;
		(*pObj)->aOrig[1]=(aMax[1]+aMin[1])/2.0F;
		(*pObj)->aOrig[2]=(aMax[2]+aMin[2])/2.0F;

		// Set size
		(*pObj)->aSize[0]=(float)rfabs(aMax[0])+(float)rfabs(aMin[0]);
		(*pObj)->aSize[1]=(float)rfabs(aMax[1])+(float)rfabs(aMin[1]);
		(*pObj)->aSize[2]=(float)rfabs(aMax[2])+(float)rfabs(aMin[2]);

		// Set maximum
		aMax[0]=0.0F;
		aMax[1]=0.0F;
		aMax[2]=0.0F;

		// Loop thru vertices
		for(n=0;n<(*pObj)->nVerts;n++)
		{
			// Check X coordinate
			fWork=(float)rfabs((*pObj)->pVerts[n*3]-(*pObj)->aOrig[0]);
			if(aMax[0] < fWork) aMax[0]=fWork;

			// Check Y coordinate
			fWork=(float)rfabs((*pObj)->pVerts[n*3+1]-(*pObj)->aOrig[1]);
			if(aMax[1] < fWork) aMax[1]=fWork;

			// Check Z coordinate
			fWork=(float)rfabs((*pObj)->pVerts[n*3+2]-(*pObj)->aOrig[2]);
			if(aMax[2] < fWork) aMax[2]=fWork;
		}

		// Set selection average
		(*pObj)->fSel=(aMax[0]+aMax[1]+aMax[2])*fOneOver3;

		// Allocate memory for normals
		(*pObj)->pNorms=(float *)calloc((*pObj)->nPolys*3,sizeof(float));
		if((*pObj)->pNorms == NULL) return(ERR);

		// Loop thru polys
		for(n=0;n<(*pObj)->nPolys;n++)
		{
			// Loop thru vertices
			for(m=0;m<LWOB_SIZE;m++)
			{
				// Get vertices
				nVert=(*pObj)->pPolys[n*LWOB_SIZE+m];

				// Handle invalid vertices
				if(nVert > (*pObj)->nVerts-1) memset(aVerts[m],0,nSizeOfFloatTimes3);
				else memcpy(aVerts[m],&((*pObj)->pVerts[nVert*3]),nSizeOfFloatTimes3);
			}

			// Calculate vectors
			aVerts[1][0]=aVerts[0][0]-aVerts[1][0];
			aVerts[1][1]=aVerts[0][1]-aVerts[1][1];
			aVerts[1][2]=aVerts[0][2]-aVerts[1][2];

			aVerts[2][0]=aVerts[0][0]-aVerts[2][0];
			aVerts[2][1]=aVerts[0][1]-aVerts[2][1];
			aVerts[2][2]=aVerts[0][2]-aVerts[2][2];

			// Calculate normal
			matCrossProduct(aNorm,aVerts[1],aVerts[2]);
			memcpy(&((*pObj)->pNorms[n*3]),aNorm,nSizeOfFloatTimes3);
		}
	}	
	else
	{
		// Set number of polys and vertices to same as current object
		(*pObj)->nPolys=pCur->nPolys;
		(*pObj)->nVerts=pCur->nVerts;

		// Set origin and selection average to same as current object
		memcpy((*pObj)->aOrig,pCur->aOrig,nSizeOfFloatTimes3);
		memcpy((*pObj)->aSize,pCur->aSize,nSizeOfFloatTimes3);
		(*pObj)->fSel=pCur->fSel;

		// Set pointers to polys, vertices and normals to same as current object
		(*pObj)->pPolys=pCur->pPolys;
		(*pObj)->pVerts=pCur->pVerts;
		(*pObj)->pNorms=pCur->pNorms;
	}
	
	return(OK);
}

__declspec(dllexport) int __stdcall rendFindObj(RENDOBJ **pObj,int nKey)
{
	// Set pointer to first object
	*pObj=pFirst;
	
	while(1)
	{
		// Check pointer
		if(*pObj == NULL) return(ERR);

		// Check key
		if(nKey == (*pObj)->nKey) break;

		// Set pointer to next object
		*pObj=(*pObj)->pNext;
	}

	return(OK);
}

__declspec(dllexport) int __stdcall rendDelObj(RENDOBJ *pObj)
{
	RENDOBJ *pCur;

	// Check object
	if(pObj == NULL) return(ERR);

	// Set pointer to first object
	pCur=pFirst;
	
	// Find other objects with same polys/vertices
	while(1)
	{
		// Check pointer
		if(pCur == NULL) break;

		// Check UID and pointer
		if((pObj != pCur) && (strcmp(pObj->szUID,pCur->szUID) == 0)) break;

		// Set pointer to next object
		pCur=pCur->pNext;
	}

	// Check UID and pointer
	if((strcmp(pObj->szUID," ") != 0) && (pCur == NULL))
	{
		// Free polys, vertices and normals
		if(pObj->pPolys != NULL) free(pObj->pPolys);
		if(pObj->pVerts != NULL) free(pObj->pVerts);
		if(pObj->pNorms != NULL) free(pObj->pNorms);
	}
	
	// Check prev object
	if(pObj->pPrev == NULL) pFirst=pObj->pNext;
	else pObj->pPrev->pNext=pObj->pNext;

	// Check next object
	if(pObj->pNext == NULL) pLast=pObj->pPrev;
	else pObj->pNext->pPrev=pObj->pPrev;

	// Set pointer to first object
	pCur=pFirst;
	
	// Find objects with links
	while(1)
	{
		// Check pointer
		if(pCur == NULL) break;

		// Check and set link
		if(pCur->pLink == pObj) pCur->pLink=pObj->pLink;

		// Set pointer to next object
		pCur=pCur->pNext;
	}

	// Set first and last object
	if(pFirst == pObj)
	{
		pFirst=NULL;
		pLast=NULL;
	}

	// Free object
	free(pObj);

	return(OK);
}

__declspec(dllexport) int __stdcall rendResetObj(RENDOBJ *pObj)
{
	// Check object
	if(pObj == NULL) return(ERR);

	// Set default mode, default color
	pObj->nMode=REND_OSHOW;
	pObj->nCol=REND_WHITE;

	// Reset translation and rotation data
	memset(&(pObj->aTrans),0,nSizeOfFloatTimes3);
	memset(&(pObj->aRot),0,nSizeOfFloatTimes3);

	// Set scale data to default
	pObj->aScale[0]=REND_OSCALE;
	pObj->aScale[1]=REND_OSCALE;
	pObj->aScale[2]=REND_OSCALE;
	
	// Set transformation matrix to identity matrix
	matIdentity(pObj->aTransform);

	return(OK);
}

__declspec(dllexport) int __stdcall rendSetObjLink(RENDOBJ *pObj,long pLink)
{
	// Check object
	if(pObj == NULL) return(ERR);

	// Set link
	pObj->pLink=(RENDOBJ *)pLink;

	return(OK);
}

__declspec(dllexport) int __stdcall rendGetObjTrans(RENDOBJ *pObj,float *x,float *y,float *z)
{
	// Check object
	if(pObj == NULL) return(ERR);

	// Get translation
	*x=pObj->aTrans[0];
	*y=pObj->aTrans[1];
	*z=pObj->aTrans[2];

	return(OK);
}

__declspec(dllexport) int __stdcall rendTransObj(RENDOBJ *pObj,float x,float y,float z)
{
	// Check object
	if(pObj == NULL) return(ERR);

	// Set translation
	pObj->aTrans[0]+=x;
	pObj->aTrans[1]+=y;
	pObj->aTrans[2]+=z;

	// Translate object
	pObj->aTransform[12]+=x;
	pObj->aTransform[13]+=y;
	pObj->aTransform[14]+=z;
	return(OK);
}

__declspec(dllexport) int __stdcall rendGetObjScale(RENDOBJ *pObj,float *x,float *y,float *z)
{
	// Check object
	if(pObj == NULL) return(ERR);

	// Get scale
	*x=pObj->aScale[0];
	*y=pObj->aScale[1];
	*z=pObj->aScale[2];

	return(OK);
}

__declspec(dllexport) int __stdcall rendGetObjSize(RENDOBJ *pObj,float *x,float *y,float *z)
{
	// Check object
	if(pObj == NULL)
	{
		*x=0.0F;
		*y=0.0F;
		*z=0.0F;
		return(ERR);
	}

	// Get scale
	*x=pObj->aSize[0];
	*y=pObj->aSize[1];
	*z=pObj->aSize[2];

	return(OK);
}

__declspec(dllexport) int __stdcall rendScaleObj(RENDOBJ *pObj,float x,float y,float z)
{
	// Check object
	if(pObj == NULL) return(ERR);

	// Set scale
	pObj->aScale[0]*=x;
	pObj->aScale[1]*=y;
	pObj->aScale[2]*=z;

	// Scale object
	matScale(pObj->aTransform,x,y,z);
	return(OK);
}

__declspec(dllexport) int __stdcall rendGetObjRot(RENDOBJ *pObj,float *x,float *y,float *z)
{
	// Check object
	if(pObj == NULL) return(ERR);

	// Get rotation
	*x=pObj->aRot[0];
	*y=pObj->aRot[1];
	*z=pObj->aRot[2];

	return(OK);
}

__declspec(dllexport) int __stdcall rendRotObj(RENDOBJ *pObj,float x,float y,float z)
{
	// Check object
	if(pObj == NULL) return(ERR);

	// Set rotation
	pObj->aRot[0]+=x;
	pObj->aRot[1]+=y;
	pObj->aRot[2]+=z;

	// Check angles
	if(pObj->aRot[0] > REND_AMAX) pObj->aRot[0]=REND_AMIN;
	if(pObj->aRot[0] < REND_AMIN) pObj->aRot[0]=REND_AMAX;
	if(pObj->aRot[1] > REND_AMAX) pObj->aRot[1]=REND_AMIN;
	if(pObj->aRot[1] < REND_AMIN) pObj->aRot[1]=REND_AMAX;
	if(pObj->aRot[2] > REND_AMAX) pObj->aRot[2]=REND_AMIN;
	if(pObj->aRot[2] < REND_AMIN) pObj->aRot[2]=REND_AMAX;

	// Set transformation matrix to identity matrix
	matIdentity(pObj->aTransform);

	// Rotate object
	matRotate(pObj->aTransform,aAxisx,pObj->aRot[0]);
	matRotate(pObj->aTransform,aAxisy,pObj->aRot[1]);
	matRotate(pObj->aTransform,aAxisz,pObj->aRot[2]);

	// Scale object
	matScale(pObj->aTransform,pObj->aScale[0],pObj->aScale[1],pObj->aScale[2]);

	// Translate object
	pObj->aTransform[12]=pObj->aTrans[0];
	pObj->aTransform[13]=pObj->aTrans[1];
	pObj->aTransform[14]=pObj->aTrans[2];
	return(OK);
}

__declspec(dllexport) int __stdcall rendGetObjMode(RENDOBJ *pObj,int *nMode)
{
	// Check object

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -