📄 render.cpp
字号:
// 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 + -