Пример #1
0
// Saves the given mesh to the given file.
void SaveMesh(const utf8_ntri &file, const Mesh &mesh, uint4 flags)
{
	const MeshImpl &meshImpl = static_cast<const MeshImpl&>(mesh);

	lean::raw_file meshFile(file, lean::file::readwrite, lean::file::overwrite);

	// Mesh
	ChunkInfo meshChunk;
	BeginChunk(meshFile, beScene::MeshDataChunk::Header, meshChunk);
	
	// Mesh name
	{
		const aiNode &rootNode = *meshImpl.GetScene()->mRootNode;

		if (rootNode.mName.length > 0)
			meshChunk.Size += WriteStringChunk(meshFile, beScene::MeshDataChunk::Name, rootNode.mName.data, static_cast<uint4>(rootNode.mName.length));
	}

	// Mesh subsets
	{
		meshChunk.Size += SaveSubsets(meshFile, *meshImpl.GetScene(), flags);
	}

	EndChunk(meshFile, meshChunk);
}
Пример #2
0
/*************
 * DESCRIPTION: read a material-chunk
 * INPUT:       pointer to chunk
 * OUTPUT:      -
 *************/
static void ParsePropMat(HANDLER_DATA *data, CHUNK *mainchunk)
{
	CHUNK    chunk;
	SURFACE  *surf;
	float    perc;
	COLOR    color, diffuse;
	char     buf[80];

	surf = data->link->SurfaceAdd(data->rc);
	if (!surf)
	{
		data->err = ERR_MEM;
		return;
	}
	do
	{
		BeginChunk(data, &chunk);
		switch (chunk.id)
		{
			case ID_PROPNAME:
					ReadASCIIZ(data, buf);
					if (!data->link->SurfaceName(data->rc, surf,buf))
					{
						data->err = ERR_MEM;
						return;
					}
					break;
			case ID_AMBIENT:
					ParseColor(data, &color);
					data->link->SurfaceAmbient(data->rc, surf,color.r,color.g,color.b);
					break;
			case ID_DIFFUSE:
					ParseColor(data, &diffuse);
					data->link->SurfaceDiffuse(data->rc, surf,diffuse.r,diffuse.g,diffuse.b);
					break;
			case ID_SPECULAR:
					ParseColor(data, &color);
					data->link->SurfaceSpecular(data->rc, surf,color.r,color.g,color.b);
					break;
			case ID_SHININESS:
					perc = ParsePercentage(data);
					data->link->SurfaceRefPhong(data->rc, surf,perc*100.f);
					break;
			case ID_TRANSPARENCY:
					perc = ParsePercentage(data);
					data->link->SurfaceTranspar(data->rc, surf,perc*diffuse.r,perc*diffuse.g,perc*diffuse.b);
					break;
		}
		EndChunk(data, &chunk);
	}
	while (INCHUNK);
}
Пример #3
0
/*************
 * DESCRIPTION: parse a 3DS file
 * INPUT:       pointer to chunk
 * OUTPUT:      -
 *************/
static void Parse3DS(HANDLER_DATA *data, CHUNK *mainchunk)
{
	CHUNK chunk;

	do
	{
		BeginChunk(data, &chunk);
		switch (chunk.id)
		{
			case ID_MESHBLOCK:
				ParseMData(data, &chunk);
				break;
		}
		EndChunk(data, &chunk);
		if(data->SetProgress)
			data->SetProgress(data->rc, (float)ftell(data->hFile)/(float)data->filesize);
	}
	while (INCHUNK);
}
Пример #4
0
/*************
 * DESCRIPTION: parse main data
 * INPUT:       pointer to chunk
 * OUTPUT:      -
 *************/
static void ParseMData(HANDLER_DATA *data, CHUNK *mainchunk)
{
	CHUNK chunk;

	do
	{
		BeginChunk(data, &chunk);
		switch (chunk.id)
		{
			case ID_PROPMATENTRY:
				ParsePropMat(data, &chunk);
				break;
			case ID_OBJECTDESC:
				ParseNamedObject(data, &chunk);
				break;
		}
		EndChunk(data, &chunk);
	}
	while (INCHUNK);
}
Пример #5
0
/*************
 * DESCRIPTION: read a percent value
 * INPUT:       -
 * OUTPUT:      float (0..1)
 *************/
static float ParsePercentage(HANDLER_DATA *data)
{
	CHUNK chunk;
	float percent = 0.f;

	BeginChunk(data, &chunk);

	switch (chunk.id)
	{
		case ID_PERCENT100:
				ReadFloat(data, &percent, 1);
				percent*= 0.01f;
				break;
		case ID_PERCENT1:
				ReadChunkBytes(data, &percent, 1);
				break;
	}

	EndChunk(data, &chunk);

	return percent;
}
Пример #6
0
/*************
 * DESCRIPTION: read an object consisting of
 *              triangles
 * INPUT:       pointer to chunk
 * OUTPUT:      -
 *************/
static void ParseTriObject(HANDLER_DATA *data, CHUNK *mainchunk)
{
	CHUNK chunk;

	do
	{
		BeginChunk(data, &chunk);
		switch (chunk.id)
		{
			case ID_POINTS:
				ParsePoints(data);
				break;
			case ID_FACES:
				ParseFaces(data, &chunk);
				break;
			case ID_MAPPINGCOORS:
				ParseMapping(data);
				break;
			case ID_TRANSMATRIX:
				ReadFloat(data, &data->transm[0], 12);
				data->transmatrix.m[0] = data->transm[0];
				data->transmatrix.m[1] = data->transm[1];
				data->transmatrix.m[2] = data->transm[2];
				data->transmatrix.m[4] = data->transm[3];
				data->transmatrix.m[5] = data->transm[4];
				data->transmatrix.m[6] = data->transm[5];
				data->transmatrix.m[8] = data->transm[6];
				data->transmatrix.m[9] = data->transm[7];
				data->transmatrix.m[10] = data->transm[8];
				data->transmatrix.m[12] = data->transm[9];
				data->transmatrix.m[13] = data->transm[10];
				data->transmatrix.m[14] = data->transm[11];
				break;
		}
		EndChunk(data, &chunk);
	}
	while (INCHUNK);
}
Пример #7
0
/*************
 * DESCRIPTION: read a color
 * INPUT:       color   pointer to color
 * OUTPUT:      -
 *************/
static void ParseColor(HANDLER_DATA *data, COLOR *color)
{
	CHUNK chunk;
	UBYTE c[3];

	BeginChunk(data, &chunk);

	switch (chunk.id)
	{
		case ID_COLOR1:
				ReadFloat(data, &color->r, 1);
				ReadFloat(data, &color->g, 1);
				ReadFloat(data, &color->b, 1);
				break;

		case ID_COLOR255:
				ReadChunkBytes(data, &c, 3);
				color->r = c[0]/255.0f;
				color->g = c[1]/255.0f;
				color->b = c[2]/255.0f;
				break;
	}
	EndChunk(data, &chunk);
}
Пример #8
0
/*************
 * DESCRIPTION: read a 3DS-file
 * INPUT:       rc          context
 *              filename    name of 3DS-file
 *              link        link structure
 *              pos         object position
 *              ox, oy, oz  object orientation
 *              actor       pointer to actor
 *              replacesurf surface to replace object surface with
 *              version     version of file
 * OUTPUT:      NULL if ok, else error string
 *************/
extern "C" char* SAVEDS objRead(rsiCONTEXT *rc_, char* filename, OBJLINK *link_, const VECTOR *pos, const VECTOR *ox, const VECTOR *oy, const VECTOR *oz,
	const VECTOR *scale, ACTOR *actor, SURFACE *replacesurf, ULONG *version, void (*SetProgress)(rsiCONTEXT*, float))
{
	CHUNK chunk;
	HANDLER_DATA data;

	data.link = link_;
	data.rc = rc_;
	data.pointcount = 0;
	data.points = NULL;
	data.mapping = NULL;
	data.VertNorms = NULL;
	data.face = NULL;
	data.facecount = 0;
	data.material = NULL;
	data.defaultsurface = NULL;
	data.replacesurface = NULL;
	data.smooth_angle = 0.5235987f;
	data.TriNorms = NULL;
	data.TriSmooth = NULL;
	data.TriList = NULL;
	data.cos_smooth_angle = (float)cos(data.smooth_angle);
	data.mainactor = NULL;
	data.SetProgress = SetProgress;
	data.size_done = 0;

	data.transmatrix.IdentityMatrix();
	data.matrix.SetSOTMatrix(scale, ox, oy, oz, pos);
	data.alignmatrix.SetOMatrix(ox, oy, oz);

	data.err = OK;
	data.hFile = Open3DS(filename);
	if (!data.hFile)
	{
		Cleanup3DS(&data);
		return errors[ERR_OPEN];
	}

	BeginChunk(&data, &chunk);
	data.filesize = chunk.end;

	// test if 3ds file
	if (chunk.id != ID_PRIMARY)
	{
		Cleanup3DS(&data);
		return errors[ERR_NO3DS];
	}

	data.mainactor = actor;
	data.replacesurface = replacesurf;

	Parse3DS(&data, &chunk);

	EndChunk(&data, &chunk);

	if(data.SetProgress)
		data.SetProgress(data.rc, (float)ftell(data.hFile)/(float)data.filesize);

	Cleanup3DS(&data);

	return errors[data.err];
}
Пример #9
0
/*************
 * DESCRIPTION: -
 * INPUT:       pointer to chunk
 * OUTPUT:      -
 *************/
static void ParseNamedObject(HANDLER_DATA *data, CHUNK *mainchunk)
{
	CHUNK     chunk;
	TRIANGLE *triangle;
	TRILIST  *ph1,*ph2;
	float     angle;
	UWORD     p1, p2, p3;
	UWORD     *edges;
	int       i, h;

	ReadASCIIZ(data, data->ObjName);
	do
	{
		BeginChunk(data, &chunk);
		switch (chunk.id)
		{
			case ID_TRIANGLE:
				ParseTriObject(data, &chunk);
				break;
		}
		EndChunk(data, &chunk);
	}
	while (INCHUNK);

	if (data->TriList && (data->link->type == LINK_RENDERER))
	{
		// go through all vertices and calculate normals (only for renderer)
		for (i = 0; i < data->pointcount; i++)
		{
			data->VertNorms[i].x = data->VertNorms[i].y = data->VertNorms[i].z = 0.f;
			ph1 = data->TriList[i];
			while (ph1)
			{
				for (ph2 = ph1->next; ph2 != NULL; ph2 = ph2->next)
				{
					if (!ph1->flag || !ph2->flag)
					{
						// test angle between two triangles
						angle = VecAngle(data->TriNorms[ph1->tri], data->TriNorms[ph2->tri]);
//                if (angle < 2*PI && angle > /*cos_*/smooth_angle)
						if (angle >0 && angle < /*cos_*/data->smooth_angle)
						{
							if (!ph1->flag)
							{
								VecAdd(&data->VertNorms[i], &data->TriNorms[ph1->tri], &data->VertNorms[i]);
								ph1->flag = TRUE;
								data->TriSmooth[ph1->tri] = TRUE;
							}
							if (!ph2->flag)
							{
								VecAdd(&data->VertNorms[i], &data->TriNorms[ph2->tri], &data->VertNorms[i]);
								ph2->flag = TRUE;
								data->TriSmooth[ph2->tri] = TRUE;
							}
						}
					}
				}
				ph2 = ph1;
				ph1 = ph1->next;
				delete ph2;
			}
			VecNormalize(&data->VertNorms[i]);
		}
	}

	if (data->face)
	{
		data->link->ObjectBegin(data->rc);

		data->defaultsurface = data->link->SurfaceAdd(data->rc);
		if (!data->defaultsurface)
		{
			data->err = ERR_MEM;
			return;
		}

		data->link->SurfaceName(data->rc, data->defaultsurface, "default");
		data->link->SurfaceDiffuse(data->rc, data->defaultsurface, 0.9f, 0.9f, 0.9f);
		data->link->SurfaceAmbient(data->rc, data->defaultsurface, 0.1f, 0.1f, 0.1f);
		data->link->SurfaceRefPhong(data->rc, data->defaultsurface, 49.f);

		triangle = data->link->TriangleAdd(data->rc, data->facecount,data->defaultsurface,data->mainactor);
		if (!triangle)
		{
			data->err = ERR_MEM;
			return;
		}
		if (data->link->type == LINK_SCENARIO)
		{  // modeler needs points,edges and faces seperate
			if (data->link->TriangleAddPoints(data->rc, data->pointcount,data->points) == -1)
			{
				data->err = ERR_MEM;
				return;
			}
			edges = new UWORD[data->facecount*6];
			if (!edges)
			{
				data->err = ERR_MEM;
				return;
			}
			for (i = 0; i < data->facecount; i++)
			{
				h = i*6;
				edges[h++] = data->face[i].p1;
				edges[h++] = data->face[i].p2;
				edges[h++] = data->face[i].p2;
				edges[h++] = data->face[i].p3;
				edges[h++] = data->face[i].p3;
				edges[h++] = data->face[i].p1;
			}
			if (data->link->TriangleAddEdges(data->rc, data->facecount*3,edges) == -1)
			{
				delete edges;
				data->err = ERR_MEM;
				return;
			}
			delete edges;
		}
		for (i = 0; i < data->facecount; i++)
		{
			p1 = data->face[i].p1;
			p2 = data->face[i].p3;
			p3 = data->face[i].p2;

			if(data->replacesurface)
				data->link->TriangleSurface(data->rc, triangle, data->replacesurface);
			else
			{
				if(!data->material[i])
					data->link->TriangleSurface(data->rc, triangle, data->defaultsurface);
				else
					data->link->TriangleSurface(data->rc, triangle, data->material[i]);
			}

			if (data->link->type == LINK_SCENARIO)
			{  // modeler needs edges
				data->link->TriangleSetEdges(data->rc, triangle,i*3,i*3+1,i*3+2);
			}
			else
			{
				// raystorm renderer needs triangles and normals
				data->link->TrianglePoints(data->rc, triangle,&data->points[p1],&data->points[p2],&data->points[p3]);

				if (!VecZero(data->TriNorms[i]))
				{
					// generate smooth triangle when smooth flag is set
					if (data->TriSmooth[i])
					{
						data->link->TriangleVNorm(data->rc, triangle,
							VecZero(data->VertNorms[p1]) ? &data->TriNorms[i] : &data->VertNorms[p1],
							VecZero(data->VertNorms[p2]) ? &data->TriNorms[i] : &data->VertNorms[p2],
							VecZero(data->VertNorms[p3]) ? &data->TriNorms[i] : &data->VertNorms[p3]);
					}
				}
				if(data->mapping)
				{
					data->link->TriangleUV(data->rc, triangle,
						&data->mapping[p1], &data->mapping[p2], &data->mapping[p3]);
				}
			}

			// next triangle
			triangle = data->link->TriangleGetNext(data->rc, triangle);
		}
		data->link->ObjectEnd(data->rc);
	}

	CleanupMesh(data);
}
Пример #10
0
/*************
 * DESCRIPTION: read faces of object
 * INPUT:       pointer to chunk
 * OUTPUT:      -
 *************/
static void ParseFaces(HANDLER_DATA *data, CHUNK *mainchunk)
{
	CHUNK    chunk;
	UWORD    i, matcount, index, p1, p2, p3;
	VECTOR   e1, e2;
	SURFACE  *s;
	TRILIST  *hp;
	char     buf[80];

	ReadWord(data, (WORD *)&data->facecount, 1); // read number of faces

	if (data->facecount == 0)
		return;

	data->face = new FACE3DS[data->facecount];
	if (!data->face)
	{
		data->err = ERR_MEM;
		return;
	}
	if (!data->replacesurface)
	{
		data->material = (SURFACE **)malloc(sizeof(SURFACE *)*data->facecount);
		if (!data->material)
		{
			data->err = ERR_MEM;
			return;
		}
	}

	ReadWord(data, (WORD *)data->face, 4*data->facecount);   // read faces

	if (data->link->type == LINK_RENDERER)
	{
		// do it for renderer only

		data->VertNorms = new VECTOR[data->pointcount];
		if (!data->VertNorms)
		{
			data->err = ERR_MEM;
			return;
		}

		data->TriNorms = new VECTOR[data->facecount];
		if (!data->TriNorms)
		{
			data->err = ERR_MEM;
			return;
		}
		memset(data->VertNorms, 0, sizeof(VECTOR)*data->pointcount);   // Init normals

		data->TriSmooth = new UBYTE[data->facecount];
		if (!data->TriSmooth)
		{
			data->err = ERR_MEM;
			return;
		}

		for (i = 0; i < data->facecount; i++)
		{
			if (data->replacesurface)
				data->material[i] = data->replacesurface;
			else
				data->material[i] = NULL;

			data->TriSmooth[i] = FALSE;
			// get three points for the triangle
			p1 = data->face[i].p1;
			p2 = data->face[i].p3;
			p3 = data->face[i].p2;

			hp = new TRILIST;
			if (!hp)
			{
				data->err = ERR_MEM;
				return;
			}
			hp->next = data->TriList[p1];
			hp->tri = i;
			hp->flag = FALSE;
			data->TriList[p1] = hp;

			hp = new TRILIST;
			if (!hp)
			{
				data->err = ERR_MEM;
				return;
			}
			hp->next = data->TriList[p2];
			hp->tri = i;
			hp->flag = FALSE;
			data->TriList[p2] = hp;

			hp = new TRILIST;
			if (!hp)
			{
				data->err = ERR_MEM;
				return;
			}
			hp->next = data->TriList[p3];
			hp->tri = i;
			hp->flag = FALSE;
			data->TriList[p3] = hp;

			// calculate normal of triangle
			VecSub(&data->points[p3], &data->points[p1], &e1);
			VecSub(&data->points[p2], &data->points[p1], &e2);
			VecNormCross(&e1, &e2, &data->TriNorms[i]);
		}
	}
	do
	{
		BeginChunk(data, &chunk);
		switch (chunk.id)
		{
			case ID_MSHMATGROUP:
					if (!data->replacesurface)
					{
						ReadASCIIZ(data, buf);
						s = data->link->SurfaceGetByName(data->rc, buf);
						ReadWord(data, (WORD*)&matcount, 1);
						for (i = 0; i < matcount; i++)
						{
							ReadWord(data, (WORD*)&index, 1);
							data->material[index] = s;
						}
					}
					break;
			case ID_SMOOTHGROUP: // no info about this group
					break;
		}
		EndChunk(data, &chunk);
	}
	while (INCHUNK);
}