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

📄 mlrloadobj.cpp

📁 机甲指挥官2源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//===========================================================================//
// Copyright (C) Microsoft Corporation. All rights reserved.                 //
//===========================================================================//

#include "MLRStuff.hpp"

#include "ctype.h"

#if !defined(MSTRING_HPP)
	#include "MString.hpp"
#endif

#if !defined(MLRSTATE_HPP)
	#include "MLRState.hpp"
#endif

#if !defined(MLRPOLYMESH_HPP)
	#include "MLRPolyMesh.hpp"
#endif

#if !defined(MLRSHAPE_HPP)
	#include "MLRShape.hpp"
#endif

// #define	FORGETFUL	1

// length of longest input line in ".obj" file (including continuations) 
const int BUFFER_SIZE = 8192;

// maximum number of vertices in a single polygon 
const int FACE_SIZE = 4096;

// initial allocation size for growable arrays 
const int CHUNK = 4096;

// how many different material library files 
const int MAX_MTL_FILES = 512;

// case insensitive string equality test 
#define        SAME(_a, _b)        (stricmp(_a,_b) == 0)

// list of textures defined by Wavefront material files 
typedef struct TEX
{
	char        *name;

//	pfTexture   *texture;
//	float        su;                // u-axis texture scale factor 
//	float        sv;                // v-axis texture scale factor 
} TEX;

/* list of materials defined by Wavefront material files typedef struct MTL
{
	char		*name;
	MLRState	*state;
//	pfMaterial      *material;
//	pfTexture       *texture;
//	int              refl_mapped;
} MTL;
*/

typedef struct Polygon
{

	Polygon() {nr = 0; };
	int nr;
	int *vIndex;
	int *cIndex;
	int *nIndex;
	int *tIndex;
} Poly;

// number of input lines skipped (recognized but not processed) or unknown 
static int	numSkip			= 0;
static int	numOther		= 0;

int	numPrimitives	= 0;		
MLRState	currentState;

// function type and argument declarations 
static void loadMtl (char *fileName);
static void useMtl (char *name);

#ifdef        FORGETFUL
	static void forgetMaterials (void);
	static void forgetMaterialFiles (void);
#endif

#define        GROW(_v, _t) \
		if (_v == 0) \
		{ \
				_v ## Available = CHUNK; \
				_v = (_t *)malloc(sizeof(_t)*_v ## Available); \
		} \
		else \
		if (_v ## Count >= _v ## Available) \
		{ \
				_v ## Available *= 2; \
				_v = (_t *)realloc(_v, sizeof(_t)*_v ## Available); \
		}

MLRPolyMesh*
	BuildPolyMesh(Poly *p, unsigned int& pCount,
				  Point3D *v, Vector3D *n,
				  Vector2DOf<Scalar> *t, RGBAColor *c)
{
	if(pCount <= 0)
	{
		return NULL;
	}

	MLRPolyMesh *pm = new MLRPolyMesh;

	int *length = new int [pCount];

	pm->SetPrimitiveLength (length, pCount);

	int i, j, k, count[4] = {0, 0, 0, 0}, indexCount = 0;
	static int list[10000];
	memset(&list, 0, 10000*sizeof(int));

	for(i=0;i<pCount;i++)
	{
		length[i] = p[i].nr;
		indexCount += p[i].nr;

		for(j=0;j<p[i].nr;j++)
		{
			list[p[i].vIndex[j]] |= 1;

			if(p[i].cIndex)
			{
				list[p[i].cIndex[j]] |= 2;
			}

			if(p[i].nIndex)
			{
				list[p[i].nIndex[j]] |= 4;
			}

			if(p[i].tIndex)
			{
				list[p[i].tIndex[j]] |= 8;
			}
		}
	}

	pm->SetPrimitiveLength(length, pCount);

	for(i=0;i<10000;i++)
	{
		if(list[i] & 1)
		{
			count[0]++;
		}
		if(list[i] & 2)
		{
			count[1]++;
		}
		if(list[i] & 4)
		{
			count[2]++;
		}
		if(list[i] & 8)
		{
			count[3]++;
		}
	}
	
	Point3D *coords = new Point3D [count[0]];

	for(i=0,j=0;i<10000;i++)
	{
		if(list[i] & 1)
		{
			list[i] |= j<<4;
			coords[j] = v[i];
			j++;
		}
	}

	int *vIndex = new int [indexCount];

	for(i=0,k=0;i<pCount;i++)
	{
		for(j=0;j<p[i].nr;j++)
		{
			vIndex[k++] = list[p[i].vIndex[j]]>>4;
		}
	}

	pm->SetData(MLRPrimitive::CoordType, coords, count[0], vIndex, indexCount);

	if(p[0].nIndex)
	{
		Vector3D *normals = new Vector3D [count[2]];

		for(i=0,j=0;i<10000;i++)
		{
			list[i] &= 0xf;

			if(list[i] & 4)
			{
				list[i] |= j<<4;
				normals[j] = n[i];
				j++;
			}
		}

		int *nIndex = new int [indexCount];

		for(i=0,k=0;i<pCount;i++)
		{
			for(j=0;j<p[i].nr;j++)
			{
				nIndex[k++] = list[p[i].nIndex[j]]>>4;
			}
		}

		pm->SetData(MLRPrimitive::NormalType, normals, count[2], nIndex, indexCount);
	}

	if(p[0].cIndex)
	{
		RGBAColor *colors = new RGBAColor [count[1]];

		for(i=0,j=0;i<10000;i++)
		{
			list[i] &= 0xf;

			if(list[i] & 4)
			{
				list[i] |= j<<2;
				colors[j] = c[i];
				j++;
			}
		}

		int *cIndex = new int [indexCount];

		for(i=0,k=0;i<pCount;i++)
		{
			for(j=0;j<p[i].nr;j++)
			{
				cIndex[k++] = list[p[i].cIndex[j]]>>4;
			}
		}

		pm->SetData(MLRPrimitive::ColorType, colors, count[1], cIndex, indexCount);
	}

	if(p[0].tIndex)
	{
		Vector2DOf<Scalar> *texCoords = new Vector2DOf<Scalar> [count[3]];

		for(i=0,j=0;i<10000;i++)
		{
			list[i] &= 0xf;

			if(list[i] & 8)
			{
				list[i] |= j<<4;
				texCoords[j] = t[i];
				j++;
			}
		}

		int *tIndex = new int [indexCount];

		for(i=0,k=0;i<pCount;i++)
		{
			for(j=0;j<p[i].nr;j++)
			{
				tIndex[k++] = list[p[i].tIndex[j]]>>4;
			}
		}

		pm->SetData(MLRPrimitive::TexCoordType, texCoords, count[3], tIndex, indexCount);
	}

	for(i=0;i<pCount;i++)
	{
		delete [] p[i].vIndex;

		if(p[i].nIndex)
		{
			delete [] p[i].nIndex;
		}

		if(p[i].cIndex)
		{
			delete [] p[i].cIndex;
		}

		if(p[i].tIndex)
		{
			delete [] p[i].tIndex;
		}
	}

	pCount = 0;
	return pm;
}

//
// pfdLoadFile_obj -- Load Wavefront ".obj" files into IRIS Performer
//
MLRShape*
	MLRLoadObj (const char *fileName)
{
	
	FILE         *objFile;

	char          buffer[BUFFER_SIZE];
	char          token[BUFFER_SIZE];
	char         *next       = 0;
	char         *backslash  = 0;

	MLRShape	*shape       = new MLRShape;

	int           width      = 0;

	int           numTris    = 0;
	int           numPolys   = 0;
	int           numGroups  = 0;

//	int			  colorsDefined = 0;

// growable vertex coordinate list (X, Y, Z) 
	Point3D       *v          = 0;
	unsigned int  vCount     = 0;
	unsigned int  vAvailable = 0;

// growable vertex normal list (Nx, Ny, Nz) 
	Vector3D	*n          = 0;
	unsigned int  nCount     = 0;
	unsigned int  nAvailable = 0;

// growable texture coordinate list (S, T )
	Vector2DOf<Scalar> *t          = 0;
	unsigned int  tCount     = 0;
	unsigned int  tAvailable = 0;

// growable color list (Cr, Cg, Cb, Ca) 
	RGBAColor	*c          = 0;
	unsigned int  cCount     = 0;
	unsigned int  cAvailable = 0;

// growable polygon list
	Poly		*p			= 0;
	unsigned int  pCount     = 0;
	unsigned int  pAvailable = 0;

// tmp count vars 
	int                 i;

	if ((objFile = fopen(fileName, "rt")) == 0)
		return 0;

	Logical backface_following_polygons = False;

// read Wavefront ".obj" file 
	while (fgets(buffer, BUFFER_SIZE, objFile) != 0)
	{
// concatenate continuation lines 
		while ((backslash = strchr(buffer, '\\')) != 0)
		{
// replace backslash with space (thanks to Ken Sakai) 
			*backslash++ = ' ';
			*backslash   = '\0';

// keep reading 
			if (fgets(backslash, (int)(BUFFER_SIZE - strlen(buffer)), objFile) == 0)
				break;
		}

// find first non-"space" character in line 
		for (next = buffer; *next != '\0' && isspace(*next); next++) {};

// skip blank lines and comments ('$' is comment in "cow.obj") 
		if (*next == '\0' || *next == '#' || *next == '!' || *next == '$')
			continue;

// extract token 
		sscanf(next, "%s%n", token, &width);
			next += width;

// identify token 
		if (SAME(token, "v"))
		{
// enlarge vertex coordinate list 
			GROW(v, Point3D);

// Set default values for vertex coordinate 
			v[vCount][0] = v[vCount][1] = v[vCount][2] = 0.0f;

// read vertex coordinate into list 
			sscanf(next, "%f %f %f",
					         &v[vCount][0], &v[vCount][1], &v[vCount][2]);
					  
/* Added to correct our OWN obj format
			float f = v[vCount][PF_Y];
			v[vCount][PF_Y] = -v[vCount][PF_Z];
			v[vCount][PF_Z] = f;
*/

// advance vertex count 
			++vCount;
		} else if (SAME(token, "vn"))
		{
// enlarge vertex normal list 
			GROW(n, Vector3D);

// Set default values for vertex normal 
			n[nCount][0] = n[nCount][1] = n[nCount][2] = 0.0f;

// read vertex normal into list 
			sscanf(next, "%f %f %f",
					      &n[nCount][0], &n[nCount][1], &n[nCount][2]);

/*
			float f = n[nCount][PF_Y];
			n[nCount][PF_Y] = -n[nCount][PF_Z];
			n[nCount][PF_Z] = f;
*/

// advance normal count 
			++nCount;
		} else if (SAME(token, "vt"))
		{
// enlarge texture coordinate list 
			GROW(t, Vector2DOf<Scalar>);

// Set default values for vertex normal 
			t[tCount][0] = t[tCount][1] = 0.0f;

⌨️ 快捷键说明

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