Esempio n. 1
0
/**
 * @brief the meat and potatoes function
 */
picoModel_t *PicoLoadModel (char *fileName, int frameNum)
{
	const picoModule_t **modules, *pm;
	picoModel_t *model;
	picoByte_t *buffer;
	int bufSize;

	/* init */
	model = NULL;

	/* make sure we've got a file name */
	if (fileName == NULL) {
		_pico_printf(PICO_ERROR, "PicoLoadModel: No filename given (fileName == NULL)");
		return NULL;
	}

	/* load file data (buffer is allocated by host app) */
	_pico_load_file(fileName, &buffer, &bufSize);
	if (bufSize < 0) {
		_pico_printf(PICO_ERROR, "PicoLoadModel: Failed loading model %s", fileName);
		return NULL;
	}

	/* get ptr to list of supported modules */
	modules = PicoModuleList(NULL);

	/* run it through the various loader functions and try
	 * to find a loader that fits the given file data */
	for (; *modules != NULL; modules++) {
		/* get module */
		pm = *modules;

		/* sanity check */
		if (pm == NULL)
			break;

		/* module must be able to load */
		if (pm->canload == NULL || pm->load == NULL)
			continue;

		model = PicoModuleLoadModel(pm, fileName, buffer, bufSize, frameNum);
		if (model != NULL) {
			/* model was loaded, so break out of loop */
			break;
		}
	}

	/* free memory used by file buffer */
	if (buffer)
		_pico_free_file(buffer);

	/* return */
	return model;
}
Esempio n. 2
0
static picoModel_t *PicoModuleLoadModel (const picoModule_t* pm, const char* fileName, picoByte_t* buffer, int bufSize,
		int frameNum)
{
	/* see whether this module can load the model file or not */
	if (pm->canload(fileName, buffer, bufSize) == PICO_PMV_OK) {
		/* use loader provided by module to read the model data */
		picoModel_t* model = pm->load(fileName, frameNum, buffer, bufSize);
		if (model == NULL) {
			_pico_free_file(buffer);
			return NULL;
		}

		/* assign pointer to file format module */
		model->module = pm;

		return model;
	}

	return NULL;
}
Esempio n. 3
0
static picoModel_t *_terrain_load( PM_PARAMS_LOAD ){
	int i, j, v, pw[ 5 ], r;
	picoParser_t    *p;

	char            *shader, *heightmapFile, *colormapFile;
	picoVec3_t scale, origin;

	unsigned char   *imageBuffer;
	int imageBufSize, w, h, cw, ch;
	unsigned char   *heightmap, *colormap, *heightPixel, *colorPixel;

	picoModel_t     *picoModel;
	picoSurface_t   *picoSurface;
	picoShader_t    *picoShader;
	picoVec3_t xyz, normal;
	picoVec2_t st;
	picoColor_t color;


	/* create pico parser */
	p = _pico_new_parser( (const picoByte_t*) buffer, bufSize );
	if ( p == NULL ) {
		return NULL;
	}

	/* get first token */
	if ( _pico_parse_first( p ) == NULL ) {
		return NULL;
	}

	/* check first token */
	if ( _pico_stricmp( p->token, "picoterrain" ) ) {
		_pico_printf( PICO_ERROR, "Invalid PicoTerrain model" );
		_pico_free_parser( p );
		return NULL;
	}

	/* setup */
	shader = heightmapFile = colormapFile = NULL;
	_pico_set_vec( scale, 512, 512, 32 );

	/* parse ase model file */
	while ( 1 )
	{
		/* get first token on line */
		if ( !_pico_parse_first( p ) ) {
			break;
		}

		/* skip empty lines */
		if ( !p->token || !p->token[ 0 ] ) {
			continue;
		}

		/* shader */
		if ( !_pico_stricmp( p->token, "shader" ) ) {
			if ( _pico_parse( p, 0 ) && p->token[ 0 ] ) {
				if ( shader != NULL ) {
					_pico_free( shader );
				}
				shader = _pico_clone_alloc( p->token );
			}
		}

		/* heightmap */
		else if ( !_pico_stricmp( p->token, "heightmap" ) ) {
			if ( _pico_parse( p, 0 ) && p->token[ 0 ] ) {
				if ( heightmapFile != NULL ) {
					_pico_free( heightmapFile );
				}
				heightmapFile = _pico_clone_alloc( p->token );
			}
		}

		/* colormap */
		else if ( !_pico_stricmp( p->token, "colormap" ) ) {
			if ( _pico_parse( p, 0 ) && p->token[ 0 ] ) {
				if ( colormapFile != NULL ) {
					_pico_free( colormapFile );
				}
				colormapFile = _pico_clone_alloc( p->token );
			}
		}

		/* scale */
		else if ( !_pico_stricmp( p->token, "scale" ) ) {
			_pico_parse_vec( p, scale );
		}

		/* skip unparsed rest of line and continue */
		_pico_parse_skip_rest( p );
	}

	/* ----------------------------------------------------------------- */

	/* load heightmap */
	heightmap = imageBuffer = NULL;
	_pico_load_file( heightmapFile, &imageBuffer, &imageBufSize );
	_terrain_load_tga_buffer( imageBuffer, &heightmap, &w, &h );
	_pico_free( heightmapFile );
	_pico_free_file( imageBuffer );

	if ( heightmap == NULL || w < 2 || h < 2 ) {
		_pico_printf( PICO_ERROR, "PicoTerrain model with invalid heightmap" );
		if ( shader != NULL ) {
			_pico_free( shader );
		}
		if ( colormapFile != NULL ) {
			_pico_free( colormapFile );
		}
		_pico_free_parser( p );
		return NULL;
	}

	/* set origin (bottom lowest corner of terrain mesh) */
	_pico_set_vec( origin, ( w / -2 ) * scale[ 0 ], ( h / -2 ) * scale[ 1 ], -128 * scale[ 2 ] );

	/* load colormap */
	colormap = imageBuffer = NULL;
	_pico_load_file( colormapFile, &imageBuffer, &imageBufSize );
	_terrain_load_tga_buffer( imageBuffer, &colormap, &cw, &ch );
	_pico_free( colormapFile );
	_pico_free_file( imageBuffer );

	if ( cw != w || ch != h ) {
		_pico_printf( PICO_WARNING, "PicoTerrain colormap/heightmap size mismatch" );
		_pico_free( colormap );
		colormap = NULL;
	}

	/* ----------------------------------------------------------------- */

	/* create new pico model */
	picoModel = PicoNewModel();
	if ( picoModel == NULL ) {
		_pico_printf( PICO_ERROR, "Unable to allocate a new model" );
		return NULL;
	}

	/* do model setup */
	PicoSetModelFrameNum( picoModel, frameNum );
	PicoSetModelNumFrames( picoModel, 1 ); /* sea */
	PicoSetModelName( picoModel, fileName );
	PicoSetModelFileName( picoModel, fileName );

	/* allocate new pico surface */
	picoSurface = PicoNewSurface( picoModel );
	if ( picoSurface == NULL ) {
		_pico_printf( PICO_ERROR, "Unable to allocate a new model surface" );
		PicoFreeModel( picoModel ); /* sea */
		return NULL;
	}

	/* terrain surfaces are triangle meshes */
	PicoSetSurfaceType( picoSurface, PICO_TRIANGLES );

	/* set surface name */
	PicoSetSurfaceName( picoSurface, "picoterrain" );

	/* create new pico shader */
	picoShader = PicoNewShader( picoModel );
	if ( picoShader == NULL ) {
		_pico_printf( PICO_ERROR, "Unable to allocate a new model shader" );
		PicoFreeModel( picoModel );
		_pico_free( shader );
		return NULL;
	}

	/* detox and set shader name */
	_pico_setfext( shader, "" );
	_pico_unixify( shader );
	PicoSetShaderName( picoShader, shader );
	_pico_free( shader );

	/* associate current surface with newly created shader */
	PicoSetSurfaceShader( picoSurface, picoShader );

	/* make bogus normal */
	_pico_set_vec( normal, 0.0f, 0.0f, 0.0f );

	/* create mesh */
	for ( j = 0; j < h; j++ )
	{
		for ( i = 0; i < w; i++ )
		{
			/* get pointers */
			v = i + ( j * w );
			heightPixel = heightmap + v * 4;
			colorPixel = colormap
						 ? colormap + v * 4
						 : NULL;

			/* set xyz */
			_pico_set_vec( xyz, origin[ 0 ] + scale[ 0 ] * i,
						   origin[ 1 ] + scale[ 1 ] * j,
						   origin[ 2 ] + scale[ 2 ] * heightPixel[ 0 ] );
			PicoSetSurfaceXYZ( picoSurface, v, xyz );

			/* set normal */
			PicoSetSurfaceNormal( picoSurface, v, normal );

			/* set st */
			st[ 0 ] = (float) i;
			st[ 1 ] = (float) j;
			PicoSetSurfaceST( picoSurface, 0, v, st );

			/* set color */
			if ( colorPixel != NULL ) {
				_pico_set_color( color, colorPixel[ 0 ], colorPixel[ 1 ], colorPixel[ 2 ], colorPixel[ 3 ] );
			}
			else{
				_pico_set_color( color, 255, 255, 255, 255 );
			}
			PicoSetSurfaceColor( picoSurface, 0, v, color );

			/* set triangles (zero alpha in heightmap suppresses this quad) */
			if ( i < ( w - 1 ) && j < ( h - 1 ) && heightPixel[ 3 ] >= 128 ) {
				/* set indexes */
				pw[ 0 ] = i + ( j * w );
				pw[ 1 ] = i + ( ( j + 1 ) * w );
				pw[ 2 ] = i + 1 + ( ( j + 1 ) * w );
				pw[ 3 ] = i + 1 + ( j * w );
				pw[ 4 ] = i + ( j * w );  /* same as pw[ 0 ] */

				/* set radix */
				r = ( i + j ) & 1;

				/* make first triangle */
				PicoSetSurfaceIndex( picoSurface, ( v * 6 + 0 ), (picoIndex_t) pw[ r + 0 ] );
				PicoSetSurfaceIndex( picoSurface, ( v * 6 + 1 ), (picoIndex_t) pw[ r + 1 ] );
				PicoSetSurfaceIndex( picoSurface, ( v * 6 + 2 ), (picoIndex_t) pw[ r + 2 ] );

				/* make second triangle */
				PicoSetSurfaceIndex( picoSurface, ( v * 6 + 3 ), (picoIndex_t) pw[ r + 0 ] );
				PicoSetSurfaceIndex( picoSurface, ( v * 6 + 4 ), (picoIndex_t) pw[ r + 2 ] );
				PicoSetSurfaceIndex( picoSurface, ( v * 6 + 5 ), (picoIndex_t) pw[ r + 3 ] );
			}
		}
	}

	/* free stuff */
	_pico_free_parser( p );
	_pico_free( heightmap );
	_pico_free( colormap );

	/* return the new pico model */
	return picoModel;
}
Esempio n. 4
0
static int _obj_mtl_load (picoModel_t *model)
{
	picoParser_t *p;
	picoByte_t *mtlBuffer;
	int mtlBufSize;
	char *fileName;

	/* sanity checks */
	if (model == NULL || model->fileName == NULL)
	return 0;

	/* skip if we have a zero length model file name */
	if (!strlen(model->fileName))
	return 0;

	/* helper */
#define _obj_mtl_error_return \
	{ \
		_pico_free_parser( p ); \
		_pico_free_file( mtlBuffer ); \
		_pico_free( fileName ); \
		return 0; \
	}
	/* alloc copy of model file name */
	fileName = _pico_clone_alloc(model->fileName);
	if (fileName == NULL)
	return 0;

	/* change extension of model file to .mtl */
	_pico_setfext(fileName, "mtl");

	/* load .mtl file contents */
	_pico_load_file(fileName, &mtlBuffer, &mtlBufSize);

	/* check result */
	if (mtlBufSize == 0)
	return 1; /* file is empty: no error */
	if (mtlBufSize < 0)
	return 0; /* load failed: error */

	/* create a new pico parser */
	p = _pico_new_parser(mtlBuffer, mtlBufSize);
	if (p == NULL)
	_obj_mtl_error_return;

	/* doo teh .mtl parse */
	while (1) {
		/* get next token in material file */
		if (_pico_parse(p, 1) == NULL)
		break;
#if 0

		/* skip empty lines */
		if (p->token == NULL || !strlen(p->token))
		continue;

		/* skip comment lines */
		if (p->token[0] == '#') {
			_pico_parse_skip_rest(p);
			continue;
		}
		/* new material */
		if (!_pico_stricmp(p->token, "newmtl")) {
			picoShader_t *shader;
			char *name;

			/* get material name */
			name = _pico_parse(p, 0);

			/* validate material name */
			if (name == NULL || !strlen(name)) {
				_pico_printf(PICO_ERROR, "Missing material name in MTL, line %d.", p->curLine);
				_obj_mtl_error_return;
			}
			/* create a new pico shader */
			shader = PicoNewShader(model);
			if (shader == NULL)
			_obj_mtl_error_return;

			/* set shader name */
			PicoSetShaderName(shader, name);

			/* assign pointer to current shader */
			curShader = shader;
		}
		/* diffuse map name */
		else if (!_pico_stricmp(p->token, "map_kd")) {
			char *mapName;

			/* pointer to current shader must be valid */
			if (curShader == NULL)
			_obj_mtl_error_return;

			/* get material's diffuse map name */
			mapName = _pico_parse(p, 0);

			/* validate map name */
			if (mapName == NULL || !strlen(mapName)) {
				_pico_printf(PICO_ERROR, "Missing material map name in MTL, line %d.", p->curLine);
				_obj_mtl_error_return;
			}
			/* set shader map name */
			PicoSetShaderMapName(shader, mapName);
		}
		/* dissolve factor (pseudo transparency 0..1) */
		/* where 0 means 100% transparent and 1 means opaque */
		else if (!_pico_stricmp(p->token, "d")) {
			picoByte_t *diffuse;
			float value;

			/* get dissolve factor */
			if (!_pico_parse_float(p, &value))
			_obj_mtl_error_return;

			/* set shader transparency */
			PicoSetShaderTransparency(curShader, value);

			/* get shader's diffuse color */
			diffuse = PicoGetShaderDiffuseColor(curShader);

			/* set diffuse alpha to transparency */
			diffuse[3] = (picoByte_t) (value * 255.0);

			/* set shader's new diffuse color */
			PicoSetShaderDiffuseColor(curShader, diffuse);
		}
		/* shininess (phong specular component) */
		else if (!_pico_stricmp(p->token, "ns")) {
			/* remark:
			 * - well, this is some major obj spec fuckup once again. some
			 *   apps store this in 0..1 range, others use 0..100 range,
			 *   even others use 0..2048 range, and again others use the
			 *   range 0..128, some even use 0..1000, 0..200, 400..700,
			 *   honestly, what's up with the 3d app coders? happens when
			 *   you smoke too much weed i guess. -sea
			 */
			float value;

			/* pointer to current shader must be valid */
			if (curShader == NULL)
			_obj_mtl_error_return;

			/* get totally screwed up shininess (a random value in fact ;) */
			if (!_pico_parse_float(p, &value))
			_obj_mtl_error_return;

			/* okay, there is no way to set this correctly, so we simply */
			/* try to guess a few ranges (most common ones i have seen) */

			/* assume 0..2048 range */
			if (value > 1000)
			value = 128.0 * (value / 2048.0);
			/* assume 0..1000 range */
			else if (value > 200)
			value = 128.0 * (value / 1000.0);
			/* assume 0..200 range */
			else if (value > 100)
			value = 128.0 * (value / 200.0);
			/* assume 0..100 range */
			else if (value > 1)
			value = 128.0 * (value / 100.0);
			/* assume 0..1 range */
			else {
				value *= 128.0;
			}
			/* negative shininess is bad (yes, i have seen it...) */
			if (value < 0.0)
			value = 0.0;

			/* set the pico shininess value in range 0..127 */
			/* geez, .obj is such a mess... */
			PicoSetShaderShininess(curShader, value);
		}
		/* kol0r ambient (wut teh fuk does "ka" stand for?) */
		else if (!_pico_stricmp(p->token, "ka")) {
			picoColor_t color;
			picoVec3_t v;

			/* pointer to current shader must be valid */
			if (curShader == NULL)
			_obj_mtl_error_return;

			/* get color vector */
			if (!_pico_parse_vec(p, v))
			_obj_mtl_error_return;

			/* scale to byte range */
			color[0] = (picoByte_t) (v[0] * 255);
			color[1] = (picoByte_t) (v[1] * 255);
			color[2] = (picoByte_t) (v[2] * 255);
			color[3] = (picoByte_t) (255);

			/* set ambient color */
			PicoSetShaderAmbientColor(curShader, color);
		}
		/* kol0r diffuse */
		else if (!_pico_stricmp(p->token, "kd")) {
			picoColor_t color;
			picoVec3_t v;

			/* pointer to current shader must be valid */
			if (curShader == NULL)
			_obj_mtl_error_return;

			/* get color vector */
			if (!_pico_parse_vec(p, v))
			_obj_mtl_error_return;

			/* scale to byte range */
			color[0] = (picoByte_t) (v[0] * 255);
			color[1] = (picoByte_t) (v[1] * 255);
			color[2] = (picoByte_t) (v[2] * 255);
			color[3] = (picoByte_t) (255);

			/* set diffuse color */
			PicoSetShaderDiffuseColor(curShader, color);
		}
		/* kol0r specular */
		else if (!_pico_stricmp(p->token, "ks")) {
			picoColor_t color;
			picoVec3_t v;

			/* pointer to current shader must be valid */
			if (curShader == NULL)
			_obj_mtl_error_return;

			/* get color vector */
			if (!_pico_parse_vec(p, v))
			_obj_mtl_error_return;

			/* scale to byte range */
			color[0] = (picoByte_t) (v[0] * 255);
			color[1] = (picoByte_t) (v[1] * 255);
			color[2] = (picoByte_t) (v[2] * 255);
			color[3] = (picoByte_t) (255);

			/* set specular color */
			PicoSetShaderSpecularColor(curShader, color);
		}
#endif
		/* skip rest of line */
		_pico_parse_skip_rest(p);
	}

	/* free parser, file buffer, and file name */
	_pico_free_parser(p);
	_pico_free_file(mtlBuffer);
	_pico_free(fileName);

	/* return with success */
	return 1;
}