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

📄 face.cpp

📁 3D游戏场景编辑器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************************/
/*  face.c                                                                              */
/*                                                                                      */
/*  Author:       Jim Mischel, Ken Baird                                                */
/*  Description:  Face csg, management, io, etc...                                      */
/*                                                                                      */
/*  The contents of this file are subject to the Genesis3D Public License               */
/*  Version 1.01 (the "License"); you may not use this file except in                   */
/*  compliance with the License. You may obtain a copy of the License at                */
/*  http://www.genesis3d.com                                                            */
/*                                                                                      */
/*  Software distributed under the License is distributed on an "AS IS"                 */
/*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
/*  the License for the specific language governing rights and limitations              */
/*  under the License.                                                                  */
/*                                                                                      */
/*  The Original Code is Genesis3D, released March 25, 1999.                            */
/*Genesis3D Version 1.1 released November 15, 1999                            */
/*  Copyright (C) 1999 WildTangent, Inc. All Rights Reserved           */
/*                                                                                      */
/*  Prepared for GenEdit-Classic ver. 0.5, Dec. 15, 2000								*/
/****************************************************************************************/
#include "stdafx.h"
#include "face.h"
#include <assert.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include "basetype.h"
#include "units.h"
#include "box3d.h"
#include "typeio.h"
//#include "consoletab.h"

#include "ram.h"
#include "quatern.h"
#include "util.h"

#include "Globals.h"
const geVec3d	VecOrigin	={ 0.0f, 0.0f, 0.0f };

//temp buffers for splitting faces
//use caution in recursive code that uses these...
static	geVec3d		spf[256], spb[256];

#define	VCOMPARE_EPSILON			(0.001f)
#define MAX_POINTS					64
#define	ON_EPSILON					(0.1f)
#define	VectorToSUB(a, b)			(*((((geFloat *)(&a))) + (b)))
#define FACE_DEFAULT_LIGHT			300
#define FACE_DEFAULT_BIAS			(1.0f)
#define FACE_DEFAULT_TRANSLUCENCY	(255.0f)
#define FACE_DEFAULT_REFLECTIVITY	(1.0f)

enum FaceFlags
{
	FACE_MIRROR		= (1<<0),
	FACE_FULLBRIGHT	= (1<<1),
	FACE_SKY		= (1<<2),
	FACE_LIGHT		= (1<<3),
	FACE_SELECTED	= (1<<4),
	FACE_FIXEDHULL	= (1<<5),		//doesn't expand (rings)
	FACE_GOURAUD	= (1<<6),
	FACE_FLAT		= (1<<7),
	FACE_TEXTURELOCKED = (1<<8),
	FACE_VISIBLE	= (1<<9),
	FACE_SHEET		= (1<<10),		//visible from both sides
	FACE_TRANSPARENT= (1<<11)		//use transparency value for something
};

enum OldFaceFlags
{
	oldINSOLID		=1,
	oldSELECTED		=2,
	oldLIGHT		=4,
	oldMIRROR		=8,
	oldFULLBRIGHT	=16,
	oldSKY			=32
};

enum SideFlags
{
	SIDE_FRONT	=0,
	SIDE_BACK	=1,
	SIDE_ON		=2
};

typedef struct TexInfoTag
{
	geVec3d VecNormal;
	geFloat xScale, yScale;
	int xShift, yShift;
	geFloat	Rotate;			// texture rotation angle in degrees
	TexInfo_Vectors TVecs;
	int Dib;				// index into the wad
	char Name[16];
	geBoolean DirtyFlag;
	geVec3d Pos;
	int txSize, tySize;		// texture size (not currently used)
	geXForm3d XfmFaceAngle;	// face rotation angle
} TexInfo;

typedef struct FaceTag
{
	int			NumPoints;
	int			Flags;
	Plane		Face_Plane;
	int			LightIntensity;
	geFloat		Reflectivity;
	geFloat		Translucency;
	geFloat		MipMapBias;
	geFloat		LightXScale, LightYScale;
	TexInfo		Tex;
	geVec3d		*Points;
} Face;

enum NewFaceFlags
{
	ffMirror		= (1<<0),	// face is a mirror
	ffFullBright	= (1<<1),	// give face full brightness
	ffSky			= (1<<2),	// face is sky
	ffLight			= (1<<3),	// face emits light
	ffTranslucent	= (1<<4),	// internal to tools
	ffGouraud		= (1<<5),	// shading
	ffFlat			= (1<<6)
};

static void Face_SetTexInfoPlane
	(
	  TexInfo *t,
	  geVec3d const *pNormal
	)
{
	assert (t != NULL);
	assert (pNormal != NULL);
	assert (geVec3d_IsNormalized (pNormal));

	t->VecNormal = *pNormal;

	t->DirtyFlag = GE_TRUE;
}

static void Face_InitFaceAngle
	(
	  TexInfo *t,
	  geVec3d const *pNormal
	)
{
	geVec3d VecDest;
	geVec3d VecAxis;
	geFloat cosv, Theta;
	geVec3d		PosNormal;

	PosNormal = *pNormal;

	if (fabs(pNormal->X) > fabs(pNormal->Y))
	{
		if (fabs(pNormal->X) > fabs(pNormal->Z))
		{
			if (pNormal->X > 0)
				geVec3d_Inverse(&PosNormal);
		}
		else
		{
			if (pNormal->Z > 0)
				geVec3d_Inverse(&PosNormal);
		}

	}
	else 
	{
		if (fabs(pNormal->Y) > fabs(pNormal->Z))
		{
			if (pNormal->Y > 0)
				geVec3d_Inverse(&PosNormal);
		}
		else
		{
			if (pNormal->Z > 0)
				geVec3d_Inverse(&PosNormal);
		}
	}
	
	// Create rotation matrix that will put this face into the X,Y plane.
	geVec3d_Set (&VecDest, 0.0f, 0.0f, 1.0f);
	geVec3d_CrossProduct (&VecDest, &PosNormal, &VecAxis);
	cosv = geVec3d_DotProduct (&VecDest, &PosNormal);
	if (cosv > 1.0f)
	{
		cosv = 1.0f;
	}
	Theta = (geFloat)acos (cosv);
	if (geVec3d_Normalize (&VecAxis) == 0.0f)
	{
		// If the resulting vector is 0 length, 
		// then a rotation about X will put us where we need to be.
		geXForm3d_SetIdentity (&t->XfmFaceAngle);
		geXForm3d_RotateX (&t->XfmFaceAngle, -Theta);	//	old gedit
//		geXForm3d_RotateX (&t->XfmFaceAngle, Theta);	//	new g3dc
	}
	else
	{
		geQuaternion QRot;

		geQuaternion_SetFromAxisAngle (&QRot, &VecAxis, -Theta);	// old gedit
//		geQuaternion_SetFromAxisAngle (&QRot, &VecAxis, Theta);	// new g3dc
		geQuaternion_ToMatrix (&QRot, &t->XfmFaceAngle);
	}
}

static void Face_InitTexInfo
	(
	  TexInfo *t,
	  geVec3d const *pNormal
	)
{
	assert (t != NULL);
	assert (pNormal != NULL);

	t->Name[0] = '\0';
	t->xScale = 1.0f;
	t->yScale = 1.0f;
	t->xShift = 0;
	t->yShift = 0;
	t->Rotate = 0.0f;
	t->Dib = 0;
	t->DirtyFlag = GE_FALSE;
	t->txSize = 0;
	t->tySize = 0;
	geVec3d_Clear (&t->Pos);
	Face_SetTexInfoPlane (t, pNormal);
	Face_InitFaceAngle( t, pNormal );
}

static geBoolean	Face_SetPlaneFromFace(Face *f)
{
	int		i;
	geVec3d	v1, v2;

	assert(f != NULL);

	//catches colinear points now
	for(i=0;i < f->NumPoints;i++)
	{
		//gen a plane normal from the cross of edge vectors
		geVec3d_Subtract(&f->Points[i], &f->Points[(i+1) % f->NumPoints], &v1);
		geVec3d_Subtract(&f->Points[(i+2) % f->NumPoints], &f->Points[(i+1) % f->NumPoints], &v2);

		geVec3d_CrossProduct(&v1, &v2, &f->Face_Plane.Normal);
		if(!geVec3d_Compare(&f->Face_Plane.Normal, &VecOrigin, VCOMPARE_EPSILON))
		{
			break;
		}
		//try the next three if there are three
	}
	if(i >= f->NumPoints)
	{
//		ConPrintf("Face with no normal!\n");	//	old gedit
		CGlobals::GetActiveDocument()->mpMainFrame->ConPrintf("Face with no normal!\n");	//	new g3dc
		return	GE_FALSE;
	}
	geVec3d_Normalize(&f->Face_Plane.Normal);
	f->Face_Plane.Dist	=geVec3d_DotProduct(&f->Points[1], &f->Face_Plane.Normal);

	Face_SetTexInfoPlane(&f->Tex, &f->Face_Plane.Normal);
	return	GE_TRUE;
}

static void Face_SetTexturePos (Face *f)
{
//	Face_GetCenter (f, &f->Tex.Pos);
	geVec3d_Clear (&f->Tex.Pos);
	f->Tex.DirtyFlag = GE_TRUE;
}


Face	*Face_Create(int NumPnts, const geVec3d *pnts, int DibId)
{
	Face	*f;

	assert(NumPnts > 0);
	assert(NumPnts < MAX_POINTS);
	assert(pnts != NULL);

	f	=(Face*)geRam_Allocate(sizeof(Face));
	if(f)
	{
		memset(f, 0, sizeof(Face));

		f->NumPoints=NumPnts;
		f->LightIntensity = FACE_DEFAULT_LIGHT;
		f->MipMapBias = FACE_DEFAULT_BIAS;
		f->Translucency = FACE_DEFAULT_TRANSLUCENCY;
		f->Reflectivity = FACE_DEFAULT_REFLECTIVITY;
		f->LightXScale = 1.0f;
		f->LightYScale = 1.0f;

		Face_SetVisible(f, GE_TRUE);

		f->Points	= (geVec3d*)geRam_Allocate(sizeof(geVec3d) * NumPnts);
		if(f->Points)
		{
			memcpy(f->Points, pnts, sizeof(geVec3d) * NumPnts);

			if(Face_SetPlaneFromFace(f))
			{
				Face_InitTexInfo(&f->Tex, &f->Face_Plane.Normal);
				Face_SetTextureDibId (f, DibId);
				Face_SetTexturePos (f);
			}
			else
			{
				geRam_Free (f->Points);
				geRam_Free (f);
				f	=NULL;
			}
		}
		else
		{
			geRam_Free (f);
			f	=NULL;
		}
	}
	return	f;
}

//builds a large face based on p
Face	*Face_CreateFromPlane(const Plane *p, geFloat Radius, int DibId)
{
	geFloat	v;
	geVec3d	vup, vright, org, pnts[4];
	
	assert(p != NULL);

	//find the major axis of p->Normal
	geVec3d_Set (&vup, 0.0f, 0.0f, 1.0f);
	if((fabs(p->Normal.Z) > fabs(p->Normal.X))
		&&(fabs(p->Normal.Z) > fabs(p->Normal.Y)))
	{
	    geVec3d_Set(&vup, 1.0f, 0.0f, 0.0f);
	}

	v	=geVec3d_DotProduct(&vup, &p->Normal);
	geVec3d_AddScaled (&vup, &p->Normal, -v, &vup);
	geVec3d_Normalize(&vup);
		
	geVec3d_AddScaled (&VecOrigin, &p->Normal, p->Dist, &org);
	geVec3d_CrossProduct(&vup, &p->Normal, &vright);

	geVec3d_Scale(&vup, Radius, &vup);
	geVec3d_Scale(&vright, Radius, &vright);

	geVec3d_Subtract(&org, &vright, &pnts[0]);
	geVec3d_Add(&pnts[0], &vup, &pnts[0]);

	geVec3d_Add(&org, &vright, &pnts[1]);
	geVec3d_Add(&pnts[1], &vup, &pnts[1]);

	geVec3d_Add(&org, &vright, &pnts[2]);
	geVec3d_Subtract(&pnts[2], &vup, &pnts[2]);

	geVec3d_Subtract(&org, &vright, &pnts[3]);
	geVec3d_Subtract(&pnts[3], &vup, &pnts[3]);

	return	Face_Create(4, pnts, DibId);
}

void	Face_Destroy(Face **f)
{
	assert(f != NULL);
	assert(*f != NULL);

	if((*f)->Points)
	{
		geRam_Free ((*f)->Points);
	}

	geRam_Free (*f);
	*f	=NULL;
}

Face	*Face_Clone(const Face *src)
{
	Face	*dst;

	assert(src != NULL);
	assert(src->NumPoints > 0);
	assert(src->Points != NULL);

	dst	=Face_Create(src->NumPoints, src->Points, Face_GetTextureDibId (src));
	if(dst)
	{
		Face_CopyFaceInfo(src, dst);
	}
	return	dst;
}

Face	*Face_CloneReverse(const Face *src)
{
	int		i;
	Face	*dst;
	geVec3d	pt;

	assert(src != NULL);
	assert(src->NumPoints >0);
	assert(src->Points != NULL);

	dst	=Face_Clone(src);
	if(dst)
	{
		dst->Face_Plane.Dist=-dst->Face_Plane.Dist;
		geVec3d_Inverse(&dst->Face_Plane.Normal);

		for(i=0;i < dst->NumPoints/2;i++)
		{
			pt								=dst->Points[i];
			dst->Points[i]					=dst->Points[dst->NumPoints-i-1];
			dst->Points[dst->NumPoints-i-1] =pt;
		}
		Face_SetPlaneFromFace(dst);
	}
	return dst;
}

int	Face_GetNumPoints(const Face *f)
{
	assert(f != NULL);

	return	f->NumPoints;
}

const Plane	*Face_GetPlane(const Face *f)
{
	assert(f != NULL);

	return	&f->Face_Plane;
}

const geVec3d	*Face_GetPoints(const Face *f)
{
	assert(f != NULL);

	return	f->Points;
}

int Face_GetLightIntensity(const Face *f)
{
	assert (f != NULL);

	return f->LightIntensity;
}

void Face_GetLightScale(const Face *f, geFloat *pxScale, geFloat *pyScale)
{
	assert(f != NULL);
	assert(pxScale != NULL);
	assert(pyScale != NULL);

	*pxScale = f->LightXScale;
	*pyScale = f->LightYScale;
}


void	Face_GetTextureScale(const Face *f, geFloat *pxScale, geFloat *pyScale)
{
	assert(f != NULL);
	assert(pxScale != NULL);
	assert(pyScale != NULL);

	*pxScale = f->Tex.xScale;
	*pyScale = f->Tex.yScale;
}

void	Face_GetTextureShift(const Face *f, int *pxShift, int *pyShift)
{
	assert(f != NULL);
	assert(pxShift != NULL);
	assert(pyShift != NULL);

	*pxShift = f->Tex.xShift;
	*pyShift = f->Tex.yShift;
}

geFloat	Face_GetTextureRotate(const Face *f)
{
	assert(f != NULL);

	return	f->Tex.Rotate;
}


static void Face_UpdateLockedTextureVecs
	(
	  Face *f
	)
{
	geXForm3d XfmTexture;
	TexInfo *t = &f->Tex;

	assert (t != NULL);
//	assert (t->xScale != 0.0f);
//	assert (t->yScale != 0.0f);
#pragma message ("this is an ugly hack.  Values should never be == 0.")
	if (t->xScale == 0.0f) t->xScale = 1.0f;
	if (t->yScale == 0.0f) t->yScale = 1.0f;

	// the normal has to be normal, no?
	assert ((t->VecNormal.X != 0.0f) || 
			(t->VecNormal.Y != 0.0f) || 
			(t->VecNormal.Z != 0.0f));

	// Compute rotation
	geVec3d_Clear (&t->XfmFaceAngle.Translation);
//	g3dc tuning comment:	the old gedit line was causing texlocked faces to rotate
//							in the OPPOSITE direction... I'm not sure why.
//	geXForm3d_SetZRotation (&XfmTexture, Units_DegreesToRadians (-t->Rotate));	//	old gedit
//	geXForm3d_SetZRotation (&XfmTexture, Units_DegreesToRadians (t->Rotate));	//	new g3dc

	// new g3dc 
	//	This code implemented in order to increase the consistency of texture
	//	orientation when toggling a face between Locked and unlocked texture
	//	mode.The below code works best for cubes positined square along world
	//	xyz axes. But it fails when cubes are oriented otherwise. Also, more
	//	complex geomentric shapes receive almost no benefit from this code...

	// Must check x, y, z in order to match tools.
	int WhichAxis = 0;		//	sides
	if (fabs (t->VecNormal.Y) > fabs (t->VecNormal.X))
	{
		if (fabs (t->VecNormal.Z) > fabs (t->VecNormal.Y))
		{
			WhichAxis = 2;	// front / back
		}
		else
		{
			WhichAxis = 1;		//	top / bottom
		}
	}
	else if (fabs (t->VecNormal.Z) > fabs (t->VecNormal.X))
	{
		WhichAxis = 2;
	}

	switch (WhichAxis)
	{
		case 0:			//	sides
			geXForm3d_SetZRotation (&XfmTexture, Units_DegreesToRadians (t->Rotate));	//	new g3dc
			geXForm3d_Multiply (&t->XfmFaceAngle, &XfmTexture, &XfmTexture);	//	old gedit
			geVec3d_Set (&t->TVecs.uVec, XfmTexture.AX, -XfmTexture.BX, -XfmTexture.CX); // old gedit
			geVec3d_Set (&t->TVecs.vVec, XfmTexture.AY, -XfmTexture.BY, -XfmTexture.CY);	// old gedit

			break;
		case 1:			//	top / bottom
			geXForm3d_SetZRotation (&XfmTexture, Units_DegreesToRadians (-t->Rotate));	//	new g3dc
			geXForm3d_Multiply (&t->XfmFaceAngle, &XfmTexture, &XfmTexture);	//	old gedit
			geVec3d_Set (&t->TVecs.uVec, XfmTexture.AX, -XfmTexture.BX, -XfmTexture.CX); // old gedit
			geVec3d_Set (&t->TVecs.vVec, XfmTexture.AY, -XfmTexture.BY, -XfmTexture.CY);	// old gedit

			break;
		case 2:			// front / back
			geXForm3d_SetZRotation (&XfmTexture, Units_DegreesToRadians (t->Rotate));	//	new g3dc
			geXForm3d_Multiply (&t->XfmFaceAngle, &XfmTexture, &XfmTexture);	//	old gedit
			geVec3d_Set (&t->TVecs.uVec, XfmTexture.AX, XfmTexture.BX, XfmTexture.CX); // old gedit
			geVec3d_Set (&t->TVecs.vVec, XfmTexture.AY, XfmTexture.BY, XfmTexture.CY);	// old gedit

			break;
	}
	
	
//	geXForm3d_Multiply (&t->XfmFaceAngle, &XfmTexture, &XfmTexture);	//	old gedit
	// get info from transform into texture vectors.
//	geVec3d_Set (&t->TVecs.uVec, XfmTexture.AX, XfmTexture.BX, XfmTexture.CX); // old gedit
//	geVec3d_Set (&t->TVecs.vVec, XfmTexture.AY, XfmTexture.BY, XfmTexture.CY);	// old gedit

	// and scale accordingly
	geVec3d_Scale (&t->TVecs.uVec, 1.0f/t->xScale, &t->TVecs.uVec);
	geVec3d_Scale (&t->TVecs.vVec, 1.0f/t->yScale, &t->TVecs.vVec);

	// compute offsets...
	{
		geFloat uOffset, vOffset;

		uOffset = geVec3d_DotProduct (&t->TVecs.uVec, &f->Tex.Pos);
		vOffset = geVec3d_DotProduct (&t->TVecs.vVec, &f->Tex.Pos);

⌨️ 快捷键说明

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