Example #1
0
/*!
 * Load shape level polygons
 * \param ppFileData Pointer to the data (usualy read from a file)
 * \param s Pointer to shape level
 * \return false on error (memory allocation failure/bad file format), true otherwise
 * \pre ppFileData loaded
 * \pre s allocated
 * \pre s->npolys set
 * \post s->polys allocated (iFSDPoly * s->npolys)
 * \post s->pindex allocated for each poly
 */
static bool _imd_load_polys( const char **ppFileData, iIMDShape *s )
{
	const char *pFileData = *ppFileData;
	int i, j, cnt;
	iIMDPoly *poly;

	s->numFrames = 0;
	s->animInterval = 0;

	s->polys = (iIMDPoly*)malloc(sizeof(iIMDPoly) * s->npolys);
	if (s->polys == NULL)
	{
		fprintf(stderr, "(_load_polys) Out of memory (polys)\n");
		return false;
	}

	for (i = 0, poly = s->polys; i < s->npolys; i++, poly++)
	{
		Uint32 flags, npnts;

		if (sscanf(pFileData, "%x %d%n", &flags, &npnts, &cnt) != 2)
		{
			fprintf(stderr, "(_load_polys) [poly %d] error loading flags and npoints", i);
		}
		pFileData += cnt;

		poly->flags = flags;
		poly->npnts = npnts;

		poly->pindex = (VERTEXID*)malloc(sizeof(VERTEXID) * poly->npnts);
		if (poly->pindex == NULL)
		{
			fprintf(stderr, "(_load_polys) [poly %d] memory alloc fail (poly indices)", i);
			return false;
		}

		for (j = 0; j < poly->npnts; j++)
		{
			int newID;

			if (sscanf(pFileData, "%d%n", &newID, &cnt) != 1)
			{
				fprintf(stderr, "failed poly %d. point %d", i, j);
				return false;
			}
			pFileData += cnt;
			poly->pindex[j] = vertexTable[newID];
		}

		// calc poly normal
		if (poly->npnts > 2)
		{
			Vector3f p0, p1, p2;

			//assumes points already set
			p0.x = s->points[poly->pindex[0]].x;
			p0.y = s->points[poly->pindex[0]].y;
			p0.z = s->points[poly->pindex[0]].z;

			p1.x = s->points[poly->pindex[1]].x;
			p1.y = s->points[poly->pindex[1]].y;
			p1.z = s->points[poly->pindex[1]].z;

			p2.x = s->points[poly->pindex[poly->npnts-1]].x;
			p2.y = s->points[poly->pindex[poly->npnts-1]].y;
			p2.z = s->points[poly->pindex[poly->npnts-1]].z;

			pie_SurfaceNormal3fv(&p0, &p1, &p2, &poly->normal);
		}
		else
		{
			Vector3f_Set(&poly->normal, 0.0f, 0.0f, 0.0f);
		}

		if (poly->flags & iV_IMD_TEXANIM)
		{
			unsigned int nFrames, pbRate, tWidth, tHeight;

			poly->pTexAnim = (iTexAnim*)malloc(sizeof(iTexAnim));
			if (poly->pTexAnim == NULL)
			{
				fprintf(stderr, "(_load_polys) [poly %d] memory alloc fail (iTexAnim struct)", i);
				return false;
			}

			// even the psx needs to skip the data
			if (sscanf(pFileData, "%d %d %d %d%n", &nFrames, &pbRate, &tWidth, &tHeight, &cnt) != 4)
			{
				fprintf(stderr, "(_load_polys) [poly %d] error reading texanim data", i);
				return false;
			}
			pFileData += cnt;

			//ASSERT( tWidth > 0, "_imd_load_polys: texture width = %i", tWidth );
			//ASSERT( tHeight > 0, "_imd_load_polys: texture height = %i", tHeight );

			/* Assumes same number of frames per poly */
			s->numFrames = nFrames;
			poly->pTexAnim->nFrames = nFrames;
			poly->pTexAnim->playbackRate =pbRate;

			/* Uses Max metric playback rate */
			s->animInterval = pbRate;
			poly->pTexAnim->textureWidth = tWidth;
			poly->pTexAnim->textureHeight = tHeight;
		}
		else
		{
			poly->pTexAnim = NULL;
		}

		// PC texture coord routine
		if (poly->flags & iV_IMD_TEX)
		{
			poly->texCoord = (Vector2f*)malloc(sizeof(Vector2f) * poly->npnts);
			if (poly->texCoord == NULL)
			{
				fprintf(stderr, "(_load_polys) [poly %d] memory alloc fail (vertex struct)", i);
				return false;
			}

			for (j = 0; j < poly->npnts; j++)
			{
				float VertexU, VertexV;
				if (sscanf(pFileData, "%f %f%n", &VertexU, &VertexV, &cnt) != 2)
				{
					fprintf(stderr, "(_load_polys) [poly %d] error reading tex outline", i);
					return false;
				}
				pFileData += cnt;

				poly->texCoord[j].x = VertexU;
				poly->texCoord[j].y = VertexV;
			}
		}
		else
		{
			poly->texCoord = NULL;
		}
	}

	*ppFileData = pFileData;

	return true;
}
Example #2
0
/*!
 * Load shape level polygons
 * \param ppFileData Pointer to the data (usualy read from a file)
 * \param s Pointer to shape level
 * \return false on error (memory allocation failure/bad file format), true otherwise
 * \pre ppFileData loaded
 * \pre s allocated
 * \pre s->npolys set
 * \post s->polys allocated (iFSDPoly * s->npolys)
 * \post s->pindex allocated for each poly
 */
static bool _imd_load_polys(const QString &filename, const char **ppFileData, iIMDShape *s, int pieVersion)
{
	const char *pFileData = *ppFileData;
	unsigned int i, j;
	iIMDPoly *poly;

	s->numFrames = 0;
	s->animInterval = 0;

	s->polys = (iIMDPoly *)malloc(sizeof(iIMDPoly) * s->npolys);
	if (s->polys == nullptr)
	{
		debug(LOG_ERROR, "(_load_polys) Out of memory (polys)");
		return false;
	}

	for (i = 0, poly = s->polys; i < s->npolys; i++, poly++)
	{
		unsigned int flags, npnts;
		int cnt;

		if (sscanf(pFileData, "%x %u%n", &flags, &npnts, &cnt) != 2)
		{
			debug(LOG_ERROR, "(_load_polys) [poly %u] error loading flags and npoints", i);
		}
		pFileData += cnt;

		poly->flags = flags;
		ASSERT_OR_RETURN(false, npnts == 3, "Invalid polygon size (%d)", npnts);
		if (sscanf(pFileData, "%d %d %d%n", &poly->pindex[0], &poly->pindex[1], &poly->pindex[2], &cnt) != 3)
		{
			debug(LOG_ERROR, "failed reading triangle, point %d", i);
			return false;
		}
		pFileData += cnt;

		// calc poly normal
		{
			Vector3f p0, p1, p2;

			//assumes points already set
			p0.x = s->points[poly->pindex[0]].x;
			p0.y = s->points[poly->pindex[0]].y;
			p0.z = s->points[poly->pindex[0]].z;

			p1.x = s->points[poly->pindex[1]].x;
			p1.y = s->points[poly->pindex[1]].y;
			p1.z = s->points[poly->pindex[1]].z;

			p2.x = s->points[poly->pindex[2]].x;
			p2.y = s->points[poly->pindex[2]].y;
			p2.z = s->points[poly->pindex[2]].z;

			poly->normal = pie_SurfaceNormal3fv(p0, p1, p2);
		}

		// texture coord routine
		if (poly->flags & iV_IMD_TEX)
		{
			int nFrames, framesPerLine, frame, pbRate;
			float tWidth, tHeight;

			if (poly->flags & iV_IMD_TEXANIM)
			{
				if (sscanf(pFileData, "%d %d %f %f%n", &nFrames, &pbRate, &tWidth, &tHeight, &cnt) != 4)
				{
					debug(LOG_ERROR, "(_load_polys) [poly %u] error reading texanim data", i);
					return false;
				}
				pFileData += cnt;

				ASSERT(tWidth > 0.0001f, "%s: texture width = %f", filename.toUtf8().constData(), tWidth);
				ASSERT(tHeight > 0.f, "%s: texture height = %f (width=%f)", filename.toUtf8().constData(), tHeight, tWidth);
				ASSERT(nFrames > 1, "%s: animation frames = %d", filename.toUtf8().constData(), nFrames);
				ASSERT(pbRate > 0, "%s: animation interval = %d ms", filename.toUtf8().constData(), pbRate);

				/* Must have same number of frames and same playback rate for all polygons */
				if (s->numFrames == 0)
				{
					s->numFrames = nFrames;
					s->animInterval = pbRate;
				}
				else
				{
					ASSERT(s->numFrames == nFrames,
					       "%s: varying number of frames within one PIE level: %d != %d",
					       filename.toUtf8().constData(), nFrames, s->numFrames);
					ASSERT(s->animInterval == pbRate,
					       "%s: varying animation intervals within one PIE level: %d != %d",
					       filename.toUtf8().constData(), pbRate, s->animInterval);
				}

				poly->texAnim.x = tWidth;
				poly->texAnim.y = tHeight;

				if (pieVersion != PIE_FLOAT_VER)
				{
					poly->texAnim.x /= OLD_TEXTURE_SIZE_FIX;
					poly->texAnim.y /= OLD_TEXTURE_SIZE_FIX;
				}
				framesPerLine = 1 / poly->texAnim.x;
			}
			else
			{
				nFrames = 1;
				framesPerLine = 1;
				pbRate = 1;
				tWidth = 0.f;
				tHeight = 0.f;
				poly->texAnim.x = 0;
				poly->texAnim.y = 0;
			}

			poly->texCoord = (Vector2f *)malloc(sizeof(*poly->texCoord) * nFrames * 3);
			ASSERT_OR_RETURN(false, poly->texCoord, "Out of memory allocating texture coordinates");
			for (j = 0; j < 3; j++)
			{
				float VertexU, VertexV;

				if (sscanf(pFileData, "%f %f%n", &VertexU, &VertexV, &cnt) != 2)
				{
					debug(LOG_ERROR, "(_load_polys) [poly %u] error reading tex outline", i);
					return false;
				}
				pFileData += cnt;

				if (pieVersion != PIE_FLOAT_VER)
				{
					VertexU /= OLD_TEXTURE_SIZE_FIX;
					VertexV /= OLD_TEXTURE_SIZE_FIX;
				}

				for (frame = 0; frame < nFrames; frame++)
				{
					const float uFrame = (frame % framesPerLine) * poly->texAnim.x;
					const float vFrame = (frame / framesPerLine) * poly->texAnim.y;
					Vector2f *c = &poly->texCoord[frame * 3 + j];

					c->x = VertexU + uFrame;
					c->y = VertexV + vFrame;
				}
			}
		}
		else
		{
			ASSERT_OR_RETURN(false, !(poly->flags & iV_IMD_TEXANIM), "Polygons with texture animation must have textures!");
			poly->texCoord = nullptr;
		}
	}

	*ppFileData = pFileData;

	return true;
}
Example #3
0
static void normalsOnTile(unsigned int tileX, unsigned int tileY, unsigned int quadrant, unsigned int *numNormals, Vector3f normals[])
{
	/* Get a pointer to our tile */
	/* And to the ones to the east, south and southeast of it */
	MAPTILE
		*psTile = mapTile(tileX,tileY),
		*tileRight = mapTile(tileX+1,tileY),
		*tileDownRight = mapTile(tileX+1,tileY+1),
		*tileDown = mapTile(tileX,tileY+1);
	unsigned int rMod = 0, drMod = 0, dMod = 0, nMod = 0;

	switch(quadrant)
	{
	case 0:
	case 2:
		/* Is it flipped? In this case one triangle  */
		if(TRI_FLIPPED(psTile))
		{
			if(quadrant==0)
			{
				Vector3f
					corner1 = {
						world_coord(tileX + 1),
						world_coord(tileY),
						tileRight->height - rMod
					},
					corner2 = {
						world_coord(tileX + 1),
						world_coord(tileY + 1),
						tileDownRight->height - drMod
					},
					corner3 = {
						world_coord(tileX),
						world_coord(tileY + 1),
						tileDown->height - dMod
					};

				normals[(*numNormals)++] = pie_SurfaceNormal3fv( corner1, corner2, corner3);
			}
			else
			{
				Vector3f
					corner1 = {
						world_coord(tileX),
						world_coord(tileY),
						psTile->height - nMod
					},
					corner2 = {
						world_coord(tileX + 1),
						world_coord(tileY),
						tileRight->height - rMod
					},
					corner3 = {
						world_coord(tileX),
						world_coord(tileY + 1),
						tileDown->height - dMod
					};

				normals[(*numNormals)++] = pie_SurfaceNormal3fv( corner1, corner2, corner3);
			}
		}
		else
		{
			/* Otherwise, it's not flipped and so two triangles*/
			{ // MSVC hack
			Vector3f
				corner1 = {
					world_coord(tileX),
					world_coord(tileY),
					psTile->height - nMod
				},
				corner2 = {
					world_coord(tileX + 1),
					world_coord(tileY),
					tileRight->height - rMod
				},
				corner3 = {
					world_coord(tileX + 1),
					world_coord(tileY + 1),
					tileDownRight->height - drMod
				};

			normals[(*numNormals)++] = pie_SurfaceNormal3fv( corner1, corner2, corner3);
			}

			{ // MSVC hack
			Vector3f
				corner1 = {
					world_coord(tileX),
					world_coord(tileY),
					psTile->height - nMod
				},
				corner2 = {
					world_coord(tileX + 1),
					world_coord(tileY + 1),
					tileDownRight->height - drMod
				},
				corner3 = {
					world_coord(tileX),
					world_coord(tileY + 1),
					tileDown->height - dMod
				};

			normals[(*numNormals)++] = pie_SurfaceNormal3fv( corner1, corner2, corner3);
			}
		}
		break;
	case 1:
	case 3:
		/* Is it flipped? In this case two triangles  */
		if(TRI_FLIPPED(psTile))
		{
			{ // MSVC hack
			Vector3f
				corner1 = {
					world_coord(tileX),
					world_coord(tileY),
					psTile->height - nMod
				},
				corner2 = {
					world_coord(tileX + 1),
					world_coord(tileY),
					tileRight->height - rMod
				},
				corner3 = {
					world_coord(tileX),
					world_coord(tileY + 1),
					tileDown->height - dMod
				};

			normals[(*numNormals)++] = pie_SurfaceNormal3fv( corner1, corner2, corner3);
			}

			{ // MSVC hack
			Vector3f
				corner1 = {
					world_coord(tileX + 1),
					world_coord(tileY),
					tileRight->height - rMod
				},
				corner2 = {
					world_coord(tileX + 1),
					world_coord(tileY + 1),
					tileDownRight->height - drMod
				},
				corner3 = {
					world_coord(tileX),
					world_coord(tileY + 1),
					tileDown->height - dMod
				};

			normals[(*numNormals)++] = pie_SurfaceNormal3fv( corner1, corner2, corner3);
			}
		}
		else
		{
			if(quadrant==1)
			{
				Vector3f
					corner1 = {
						world_coord(tileX),
						world_coord(tileY),
						psTile->height - nMod
					},
					corner2 = {
						world_coord(tileX + 1),
						world_coord(tileY + 1),
						tileDownRight->height - drMod
					},
					corner3 = {
						world_coord(tileX),
						world_coord(tileY + 1),
						tileDown->height - dMod
					};

				normals[(*numNormals)++] = pie_SurfaceNormal3fv( corner1, corner2, corner3);
			}
			else
			{
				Vector3f
					corner1 = {
						world_coord(tileX),
						world_coord(tileY),
						psTile->height - nMod
					},
					corner2 = {
						world_coord(tileX + 1),
						world_coord(tileY),
						tileRight->height - rMod
					},
					corner3 = {
						world_coord(tileX + 1),
						world_coord(tileY + 1),
						tileDownRight->height - drMod
					};

				normals[(*numNormals)++] = pie_SurfaceNormal3fv( corner1, corner2, corner3);
			}
		}
		break;
	default:
		ASSERT( false,"Invalid quadrant in lighting code" );
	} // end switch
}