Exemple #1
0
/*
=================
ParseMapEntity

parses a single entity out of a map file
=================
*/
static bool ParseMapEntity( bool onlyLights )
{
	epair_t		*ep;
	token_t		token;
	const char	*classname, *value;
	float		lightmapScale;
	char		shader[ MAX_SHADERPATH ];
	shaderInfo_t	*celShader = NULL;
	brush_t		*brush;
	parseMesh_t	*patch;
	bool		funcGroup;
	int		castShadows, recvShadows;
	static bool	map_type = false;

	if( !Com_ReadToken( mapfile, SC_ALLOW_NEWLINES|SC_COMMENT_SEMICOLON, &token ))
		return false; // end of .map file
	if( com.stricmp( token.string, "{" ))  Sys_Break( "ParseEntity: found %s instead {\n", token.string );
	if( numEntities >= MAX_MAP_ENTITIES ) Sys_Break( "MAX_MAP_ENTITIES limit exceeded\n" );	

	entitySourceBrushes = 0;
	mapEnt = &entities[numEntities];
	numEntities++;
	memset( mapEnt, 0, sizeof( *mapEnt ));
	
	mapEnt->mapEntityNum = numMapEntities;
	numMapEntities++;
	
	while( 1 )
	{
		if( !Com_ReadToken( mapfile, SC_ALLOW_NEWLINES|SC_COMMENT_SEMICOLON, &token ))
			Sys_Break( "ParseEntity: EOF without closing brace\n" );

		if( !com.stricmp( token.string, "}" )) break;
		if( !com.stricmp( token.string, "{" ))
		{
			// parse a brush or patch
			if( !Com_ReadToken( mapfile, SC_ALLOW_NEWLINES, &token )) break;
			
			if( !com.stricmp( token.string, "patchDef2" ))
			{
				numMapPatches++;
				ParsePatch( onlyLights );
				g_bBrushPrimit = BRUSH_RADIANT;
			}
			else if( !com.stricmp( token.string, "terrainDef" ))
			{
				MsgDev( D_WARN, "Terrain entity parsing not supported in this build.\n" );
				Com_SkipBracedSection( mapfile, 0 );
				g_bBrushPrimit = BRUSH_RADIANT;
			}
			else if( !com.stricmp( token.string, "brushDef" ))
			{
				// parse brush primitive
				g_bBrushPrimit = BRUSH_RADIANT;
				ParseBrush( onlyLights );
			}
			else
			{
				if( g_bBrushPrimit == BRUSH_RADIANT )
					Sys_Break( "mixed brush primitive with another format\n" );
				if( g_bBrushPrimit == BRUSH_UNKNOWN ) g_bBrushPrimit = BRUSH_WORLDCRAFT_21;
				
				// QuArK or WorldCraft map (unknown at this point)
				Com_SaveToken( mapfile, &token );
				ParseBrush( onlyLights );
			}
			entitySourceBrushes++;
		}
		else
		{
			// parse a key / value pair
			ep = ParseEpair( mapfile, &token );

			if( !com.strcmp( ep->key, "mapversion" ))
			{
				if( com.atoi( ep->value ) == VALVE_FORMAT )
				{
					Msg( "Valve Format Map detected\n" );
					g_bBrushPrimit = BRUSH_WORLDCRAFT_22;
				}
				else if( com.atoi( ep->value ) == GEARBOX_FORMAT )
				{
					Msg( "Gearcraft Format Map detected\n" );
					g_bBrushPrimit = BRUSH_GEARCRAFT_40;
				}
				else g_bBrushPrimit = BRUSH_WORLDCRAFT_21;
			}
			if( ep->key[0] != '\0' && ep->value[0] != '\0' )
			{
				ep->next = mapEnt->epairs;
				mapEnt->epairs = ep;
			}
		}
	}

	if( !map_type && g_bBrushPrimit != BRUSH_UNKNOWN )
	{
		MAPTYPE();
		map_type = true;
	}
	
	classname = ValueForKey( mapEnt, "classname" );
	
	if( onlyLights && com.strnicmp( classname, "light", 5 ))
	{
		numEntities--;
		return true;
	}
	
	if( !com.stricmp( "func_group", classname ))
		funcGroup = true;
	else funcGroup = false;
	
	// worldspawn (and func_groups) default to cast/recv shadows in worldspawn group
	if( funcGroup || mapEnt->mapEntityNum == 0 )
	{
		castShadows = WORLDSPAWN_CAST_SHADOWS;
		recvShadows = WORLDSPAWN_RECV_SHADOWS;
	}
	else // other entities don't cast any shadows, but recv worldspawn shadows
	{
		castShadows = ENTITY_CAST_SHADOWS;
		recvShadows = ENTITY_RECV_SHADOWS;
	}
	
	// get explicit shadow flags
	GetEntityShadowFlags( mapEnt, NULL, &castShadows, &recvShadows );
	
	// get lightmap scaling value for this entity
	if( com.strcmp( "", ValueForKey( mapEnt, "lightmapscale" )) || com.strcmp( "", ValueForKey( mapEnt, "_lightmapscale" )))
	{
		// get lightmap scale from entity
		lightmapScale = FloatForKey( mapEnt, "lightmapscale" );
		if( lightmapScale <= 0.0f ) lightmapScale = FloatForKey( mapEnt, "_lightmapscale" );
		if( lightmapScale > 0.0f ) Msg( "Entity %d (%s) has lightmap scale of %.4f\n", mapEnt->mapEntityNum, classname, lightmapScale );
	}
	else lightmapScale = 0.0f;
	
	// get cel shader :) for this entity
	value = ValueForKey( mapEnt, "_celshader" );
	if( value[0] == '\0' ) value = ValueForKey( &entities[0], "_celshader" );
	if( value[0] != '\0' )
	{
		com.snprintf( shader, sizeof( shader ), "textures/%s", value );
		celShader = ShaderInfoForShader( shader );
		Msg( "Entity %d (%s) has cel shader %s\n", mapEnt->mapEntityNum, classname, celShader->shader );
	}
	else celShader = NULL;
	
	// attach stuff to everything in the entity
	for( brush = mapEnt->brushes; brush != NULL; brush = brush->next )
	{
		brush->entityNum = mapEnt->mapEntityNum;
		brush->castShadows = castShadows;
		brush->recvShadows = recvShadows;
		brush->lightmapScale = lightmapScale;
		brush->celShader = celShader;
	}
	
	for( patch = mapEnt->patches; patch != NULL; patch = patch->next )
	{
		patch->entityNum = mapEnt->mapEntityNum;
		patch->castShadows = castShadows;
		patch->recvShadows = recvShadows;
		patch->lightmapScale = lightmapScale;
		patch->celShader = celShader;
	}
	
	SetEntityBounds( mapEnt );
	
	// load shader index map (equivalent to old terrain alphamap)
	LoadEntityIndexMap( mapEnt );
	
	// get entity origin and adjust brushes
	GetVectorForKey( mapEnt, "origin", mapEnt->origin );
	if( mapEnt->origin[0] || mapEnt->origin[1] || mapEnt->origin[2] )
		AdjustBrushesForOrigin( mapEnt );

	// group_info entities are just for editor grouping
	if( !com.stricmp( "group_info", classname ))
	{
		numEntities--;
		return true;
	}
	
	// group entities are just for editor convenience, toss all brushes into worldspawn
	if( funcGroup )
	{
		MoveBrushesToWorld( mapEnt );
		numEntities--;
		return true;
	}
	return true;
}
Exemple #2
0
static void PopulateTraceNodes(void)
{
	int             i, m, frame, castShadows;
	float           temp;
	entity_t       *e;
	const char     *value;
	picoModel_t    *model;
	vec3_t          origin, scale, angles;
	matrix_t        rotation;
	matrix_t        transform;


	/* add worldspawn triangles */
	MatrixIdentity(transform);
	PopulateWithBSPModel(&bspModels[0], transform);

	/* walk each entity list */
	for(i = 1; i < numEntities; i++)
	{
		/* get entity */
		e = &entities[i];

		/* get shadow flags */
		castShadows = ENTITY_CAST_SHADOWS;
		GetEntityShadowFlags(e, NULL, &castShadows, NULL);

		/* early out? */
		if(!castShadows)
			continue;

		/* get entity origin */
		GetVectorForKey(e, "origin", origin);

		/* get "angle" (yaw) or "angles" (pitch yaw roll) */
		MatrixIdentity(rotation);
		angles[0] = angles[1] = angles[2] = 0.0f;

		value = ValueForKey(e, "angle");
		if(value[0] != '\0')
		{
			angles[1] = atof(value);
			MatrixFromAngles(rotation, angles[PITCH], angles[YAW], angles[ROLL]);
		}

		value = ValueForKey(e, "angles");
		if(value[0] != '\0')
		{
			sscanf(value, "%f %f %f", &angles[0], &angles[1], &angles[2]);
			MatrixFromAngles(rotation, angles[PITCH], angles[YAW], angles[ROLL]);
		}

		value = ValueForKey(e, "rotation");
		if(value[0] != '\0')
		{
			sscanf(value, "%f %f %f %f %f %f %f %f %f", &rotation[0], &rotation[1], &rotation[2],
				   &rotation[4], &rotation[5], &rotation[6], &rotation[8], &rotation[9], &rotation[10]);
		}

		/* get scale */
		scale[0] = scale[1] = scale[2] = 1.0f;
		temp = FloatForKey(e, "modelscale");
		if(temp != 0.0f)
			scale[0] = scale[1] = scale[2] = temp;
		value = ValueForKey(e, "modelscale_vec");
		if(value[0] != '\0')
			sscanf(value, "%f %f %f", &scale[0], &scale[1], &scale[2]);

		MatrixMultiplyScale(rotation, scale[0], scale[1], scale[2]);

		/* set transform matrix */
		MatrixIdentity(transform);
		MatrixSetupTransformFromRotation(transform, rotation, origin);

		//% m4x4_pivoted_transform_by_vec3(transform, origin, angles, eXYZ, scale, vec3_origin);

		/* get model */
		value = ValueForKey(e, "model");

		/* switch on model type */
		switch (value[0])
		{
				/* no model */
			case '\0':
				break;

				/* bsp model */
			case '*':
				m = atoi(&value[1]);
				if(m <= 0 || m >= numBSPModels)
					continue;
				PopulateWithBSPModel(&bspModels[m], transform);
				break;

				/* external model */
			default:
				frame = IntForKey(e, "_frame");
				model = LoadModel((char *)value, frame);
				if(model == NULL)
					continue;
				PopulateWithPicoModel(castShadows, model, transform);
				continue;
		}

		/* get model2 */
		value = ValueForKey(e, "model2");

		/* switch on model type */
		switch (value[0])
		{
				/* no model */
			case '\0':
				break;

				/* bsp model */
			case '*':
				m = atoi(&value[1]);
				if(m <= 0 || m >= numBSPModels)
					continue;
				PopulateWithBSPModel(&bspModels[m], transform);
				break;

				/* external model */
			default:
				frame = IntForKey(e, "_frame2");
				model = LoadModel((char *)value, frame);
				if(model == NULL)
					continue;
				PopulateWithPicoModel(castShadows, model, transform);
				continue;
		}
	}
}
Exemple #3
0
void AddTriangleModels(entity_t * e)
{
	int             num, frame, castShadows, recvShadows, spawnFlags;
	entity_t       *e2;
	const char     *targetName;
	const char     *target, *model, *value;
	char            shader[MAX_QPATH];
	shaderInfo_t   *celShader;
	float           temp, baseLightmapScale, lightmapScale;
	float           shadeAngle;
	int             lightmapSampleSize;
	vec3_t          origin, scale, angles;
	matrix_t        rotation, rotationScaled, transform;
	epair_t        *ep;
	remap_t        *remap, *remap2;
	char           *split;


	/* note it */
	Sys_FPrintf(SYS_VRB, "--- AddTriangleModels ---\n");

	/* get current brush entity targetname */
	if(e == entities)
		targetName = "";
	else
	{
		targetName = ValueForKey(e, "name");

		/* misc_model entities target non-worldspawn brush model entities */
		if(targetName[0] == '\0')
			return;
	}

	/* get lightmap scale */
	/* vortex: added _ls key (short name of lightmapscale) */
	baseLightmapScale = 0.0f;
	if(strcmp("", ValueForKey(e, "lightmapscale")) ||
	   strcmp("", ValueForKey(e, "_lightmapscale")) || strcmp("", ValueForKey(e, "_ls")))
	{
		baseLightmapScale = FloatForKey(e, "lightmapscale");
		if(baseLightmapScale <= 0.0f)
			baseLightmapScale = FloatForKey(e, "_lightmapscale");
		if(baseLightmapScale <= 0.0f)
			baseLightmapScale = FloatForKey(e, "_ls");
		if(baseLightmapScale < 0.0f)
			baseLightmapScale = 0.0f;
		if(baseLightmapScale > 0.0f)
			Sys_Printf("World Entity has lightmap scale of %.4f\n", baseLightmapScale);
	}

	/* walk the entity list */
	for(num = 1; num < numEntities; num++)
	{
		/* get e2 */
		e2 = &entities[num];

		/* convert misc_models into raw geometry */
		if(Q_stricmp("misc_model", ValueForKey(e2, "classname")))
			continue;

		/* ydnar: added support for md3 models on non-worldspawn models */
		target = ValueForKey(e2, "target");
		if(strcmp(target, targetName))
			continue;

		/* get model name */
		model = ValueForKey(e2, "model");
		if(model[0] == '\0')
		{
			Sys_Printf("WARNING: misc_model at %i %i %i without a model key\n", (int)origin[0], (int)origin[1], (int)origin[2]);
			continue;
		}

		/* get model frame */
		frame = IntForKey(e2, "_frame");

		/* worldspawn (and func_groups) default to cast/recv shadows in worldspawn group */
		if(e == entities)
		{
			castShadows = WORLDSPAWN_CAST_SHADOWS;
			recvShadows = WORLDSPAWN_RECV_SHADOWS;
		}

		/* other entities don't cast any shadows, but recv worldspawn shadows */
		else
		{
			castShadows = ENTITY_CAST_SHADOWS;
			recvShadows = ENTITY_RECV_SHADOWS;
		}

		/* get explicit shadow flags */
		GetEntityShadowFlags(e2, e, &castShadows, &recvShadows);

		/* get spawnflags */
		spawnFlags = IntForKey(e2, "spawnflags");

		/* Tr3B: added clipModel option */
		spawnFlags |= (IntForKey(e2, "clipModel") > 0) ? 2 : 0;

		/* Tr3B: added forceMeta option */
		spawnFlags |= (IntForKey(e2, "forceMeta") > 0) ? 4 : 0;

		/* get origin */
		GetVectorForKey(e2, "origin", origin);
		VectorSubtract(origin, e->origin, origin);	/* offset by parent */

		/* get "angle" (yaw) or "angles" (pitch yaw roll) */
		MatrixIdentity(rotation);
		angles[0] = angles[1] = angles[2] = 0.0f;

		value = ValueForKey(e2, "angle");
		if(value[0] != '\0')
		{
			angles[1] = atof(value);
			MatrixFromAngles(rotation, angles[PITCH], angles[YAW], angles[ROLL]);
		}

		value = ValueForKey(e2, "angles");
		if(value[0] != '\0')
		{
			sscanf(value, "%f %f %f", &angles[0], &angles[1], &angles[2]);
			MatrixFromAngles(rotation, angles[PITCH], angles[YAW], angles[ROLL]);
		}

		value = ValueForKey(e2, "rotation");
		if(value[0] != '\0')
		{
			sscanf(value, "%f %f %f %f %f %f %f %f %f", &rotation[0], &rotation[1], &rotation[2],
				   &rotation[4], &rotation[5], &rotation[6], &rotation[8], &rotation[9], &rotation[10]);
		}

		/* get scale */
		scale[0] = scale[1] = scale[2] = 1.0f;
		temp = FloatForKey(e2, "modelscale");
		if(temp != 0.0f)
			scale[0] = scale[1] = scale[2] = temp;
		value = ValueForKey(e2, "modelscale_vec");
		if(value[0] != '\0')
			sscanf(value, "%f %f %f", &scale[0], &scale[1], &scale[2]);

		MatrixCopy(rotation, rotationScaled);
		MatrixMultiplyScale(rotationScaled, scale[0], scale[1], scale[2]);

		/* set transform matrix */
		MatrixIdentity(transform);
		MatrixSetupTransformFromRotation(transform, rotationScaled, origin);

		/* get shader remappings */
		remap = NULL;
		for(ep = e2->epairs; ep != NULL; ep = ep->next)
		{
			/* look for keys prefixed with "_remap" */
			if(ep->key != NULL && ep->value != NULL &&
			   ep->key[0] != '\0' && ep->value[0] != '\0' && !Q_strncasecmp(ep->key, "_remap", 6))
			{
				/* create new remapping */
				remap2 = remap;
				remap = safe_malloc(sizeof(*remap));
				remap->next = remap2;
				strcpy(remap->from, ep->value);

				/* split the string */
				split = strchr(remap->from, ';');
				if(split == NULL)
				{
					Sys_Printf("WARNING: Shader _remap key found in misc_model without a ; character\n");
					free(remap);
					remap = remap2;
					continue;
				}

				/* store the split */
				*split = '\0';
				strcpy(remap->to, (split + 1));

				/* note it */
				//% Sys_FPrintf( SYS_VRB, "Remapping %s to %s\n", remap->from, remap->to );
			}
		}

		/* ydnar: cel shader support */
		value = ValueForKey(e2, "_celshader");
		if(value[0] == '\0')
			value = ValueForKey(&entities[0], "_celshader");
		if(value[0] != '\0')
		{
			sprintf(shader, "textures/%s", value);
			celShader = ShaderInfoForShader(shader);
		}
		else
			celShader = NULL;

		/* jal : entity based _samplesize */
		lightmapSampleSize = 0;
		if(strcmp("", ValueForKey(e2, "_lightmapsamplesize")))
			lightmapSampleSize = IntForKey(e2, "_lightmapsamplesize");
		else if(strcmp("", ValueForKey(e2, "_samplesize")))
			lightmapSampleSize = IntForKey(e2, "_samplesize");

		if(lightmapSampleSize < 0)
			lightmapSampleSize = 0;

		if(lightmapSampleSize > 0.0f)
			Sys_Printf("misc_model has lightmap sample size of %.d\n", lightmapSampleSize);

		/* get lightmap scale */
		/* vortex: added _ls key (short name of lightmapscale) */
		lightmapScale = 0.0f;
		if(strcmp("", ValueForKey(e2, "lightmapscale")) ||
		   strcmp("", ValueForKey(e2, "_lightmapscale")) || strcmp("", ValueForKey(e2, "_ls")))
		{
			lightmapScale = FloatForKey(e2, "lightmapscale");
			if(lightmapScale <= 0.0f)
				lightmapScale = FloatForKey(e2, "_lightmapscale");
			if(lightmapScale <= 0.0f)
				lightmapScale = FloatForKey(e2, "_ls");
			if(lightmapScale < 0.0f)
				lightmapScale = 0.0f;
			if(lightmapScale > 0.0f)
				Sys_Printf("misc_model has lightmap scale of %.4f\n", lightmapScale);
		}

		/* jal : entity based _shadeangle */
		shadeAngle = 0.0f;
		if(strcmp("", ValueForKey(e2, "_shadeangle")))
			shadeAngle = FloatForKey(e2, "_shadeangle");
		/* vortex' aliases */
		else if(strcmp("", ValueForKey(mapEnt, "_smoothnormals")))
			shadeAngle = FloatForKey(mapEnt, "_smoothnormals");
		else if(strcmp("", ValueForKey(mapEnt, "_sn")))
			shadeAngle = FloatForKey(mapEnt, "_sn");
		else if(strcmp("", ValueForKey(mapEnt, "_smooth")))
			shadeAngle = FloatForKey(mapEnt, "_smooth");

		if(shadeAngle < 0.0f)
			shadeAngle = 0.0f;

		if(shadeAngle > 0.0f)
			Sys_Printf("misc_model has shading angle of %.4f\n", shadeAngle);

		/* insert the model */
		InsertModel((char *)model, frame, transform, rotation, remap, celShader, mapEntityNum, castShadows, recvShadows, spawnFlags,
					lightmapScale, lightmapSampleSize, shadeAngle);

		/* free shader remappings */
		while(remap != NULL)
		{
			remap2 = remap->next;
			free(remap);
			remap = remap2;
		}
	}
}
Exemple #4
0
static void PopulateTraceNodes( void ){
	int i, m, frame, castShadows;
	float temp;
	entity_t        *e;
	const char      *value;
	picoModel_t     *model;
	vec3_t origin, scale, angles;
	m4x4_t transform;


	/* add worldspawn triangles */
	m4x4_identity( transform );
	PopulateWithBSPModel( &bspModels[ 0 ], transform );

	/* walk each entity list */
	for ( i = 1; i < numEntities; i++ )
	{
		/* get entity */
		e = &entities[ i ];

		/* get shadow flags */
		castShadows = ENTITY_CAST_SHADOWS;
		GetEntityShadowFlags( e, NULL, &castShadows, NULL );

		/* early out? */
		if ( !castShadows ) {
			continue;
		}

		/* get entity origin */
		GetVectorForKey( e, "origin", origin );

		/* get scale */
		scale[ 0 ] = scale[ 1 ] = scale[ 2 ] = 1.0f;
		temp = FloatForKey( e, "modelscale" );
		if ( temp != 0.0f ) {
			scale[ 0 ] = scale[ 1 ] = scale[ 2 ] = temp;
		}
		value = ValueForKey( e, "modelscale_vec" );
		if ( value[ 0 ] != '\0' ) {
			sscanf( value, "%f %f %f", &scale[ 0 ], &scale[ 1 ], &scale[ 2 ] );
		}

		/* get "angle" (yaw) or "angles" (pitch yaw roll) */
		angles[ 0 ] = angles[ 1 ] = angles[ 2 ] = 0.0f;
		angles[ 2 ] = FloatForKey( e, "angle" );
		value = ValueForKey( e, "angles" );
		if ( value[ 0 ] != '\0' ) {
			sscanf( value, "%f %f %f", &angles[ 1 ], &angles[ 2 ], &angles[ 0 ] );
		}

		/* set transform matrix (thanks spog) */
		m4x4_identity( transform );
		m4x4_pivoted_transform_by_vec3( transform, origin, angles, eXYZ, scale, vec3_origin );

		/* hack: Stable-1_2 and trunk have differing row/column major matrix order
		   this transpose is necessary with Stable-1_2
		   uncomment the following line with old m4x4_t (non 1.3/spog_branch) code */
		//%	m4x4_transpose( transform );

		/* get model */
		value = ValueForKey( e, "model" );

		/* switch on model type */
		switch ( value[ 0 ] )
		{
		/* no model */
		case '\0':
			break;

		/* bsp model */
		case '*':
			m = atoi( &value[ 1 ] );
			if ( m <= 0 || m >= numBSPModels ) {
				continue;
			}
			PopulateWithBSPModel( &bspModels[ m ], transform );
			break;

		/* external model */
		default:
			frame = 0;
			if ( strcmp( "", ValueForKey( e, "_frame" ) ) ) {
				frame = IntForKey( e, "_frame" );
			}
			else if ( strcmp( "", ValueForKey( e, "frame" ) ) ) {
				frame = IntForKey( e, "frame" );
			}
			model = LoadModel( value, frame );
			if ( model == NULL ) {
				continue;
			}
			PopulateWithPicoModel( castShadows, model, transform );
			continue;
		}

		/* get model2 */
		value = ValueForKey( e, "model2" );

		/* switch on model type */
		switch ( value[ 0 ] )
		{
		/* no model */
		case '\0':
			break;

		/* bsp model */
		case '*':
			m = atoi( &value[ 1 ] );
			if ( m <= 0 || m >= numBSPModels ) {
				continue;
			}
			PopulateWithBSPModel( &bspModels[ m ], transform );
			break;

		/* external model */
		default:
			frame = IntForKey( e, "_frame2" );
			model = LoadModel( value, frame );
			if ( model == NULL ) {
				continue;
			}
			PopulateWithPicoModel( castShadows, model, transform );
			continue;
		}
	}
}
Exemple #5
0
void AddTriangleModel(entity_t * e)
{
	int             frame, castShadows, recvShadows, spawnFlags;
	const char     *name, *model, *value;
	char            shader[MAX_QPATH];
	shaderInfo_t   *celShader;
	float           temp, baseLightmapScale, lightmapScale;
	float           shadeAngle;
	int             lightmapSampleSize;
	vec3_t          scale;
	matrix_t        rotation, transform;
	epair_t        *ep;
	remap_t        *remap, *remap2;
	char           *split;

	/* note it */
	Sys_FPrintf(SYS_VRB, "--- AddTriangleModel ---\n");

	/* get current brush entity name */
	name = ValueForKey(e, "name");

	/* misc_model entities target non-worldspawn brush model entities */
	if(name[0] == '\0')
		return;

	/* get model name */
	model = ValueForKey(e, "model");
	if(model[0] == '\0')
		return;

	/* Tr3B: skip triggers and other entities */
	if(!Q_stricmp(name, model))
		return;

	/* get model frame */
	frame = IntForKey(e, "_frame");

	/* worldspawn (and func_groups) default to cast/recv shadows in worldspawn group */
	if(e == entities)
	{
		castShadows = WORLDSPAWN_CAST_SHADOWS;
		recvShadows = WORLDSPAWN_RECV_SHADOWS;
	}

	/* other entities don't cast any shadows, but recv worldspawn shadows */
	else
	{
		castShadows = ENTITY_CAST_SHADOWS;
		recvShadows = ENTITY_RECV_SHADOWS;
	}

	/* get explicit shadow flags */
	GetEntityShadowFlags(NULL, e, &castShadows, &recvShadows);

	/* get spawnflags */
	spawnFlags = IntForKey(e, "spawnflags");

	/* Tr3B: added clipModel option */
	spawnFlags |= (IntForKey(e, "clipModel") > 0) ? 2 : 0;

	/* Tr3B: added forceMeta option */
	spawnFlags |= (IntForKey(e, "forceMeta") > 0) ? 4 : 0;

	/* get scale */
	scale[0] = scale[1] = scale[2] = 1.0f;
	temp = FloatForKey(e, "modelscale");
	if(temp != 0.0f)
		scale[0] = scale[1] = scale[2] = temp;
	value = ValueForKey(e, "modelscale_vec");
	if(value[0] != '\0')
		sscanf(value, "%f %f %f", &scale[0], &scale[1], &scale[2]);

	/* set transform matrix */
	MatrixIdentity(transform);
	MatrixMultiplyScale(transform, scale[0], scale[1], scale[2]);
	MatrixIdentity(rotation);

	/* get shader remappings */
	remap = NULL;
	for(ep = e->epairs; ep != NULL; ep = ep->next)
	{
		/* look for keys prefixed with "_remap" */
		if(ep->key != NULL && ep->value != NULL &&
		   ep->key[0] != '\0' && ep->value[0] != '\0' && !Q_strncasecmp(ep->key, "_remap", 6))
		{
			/* create new remapping */
			remap2 = remap;
			remap = safe_malloc(sizeof(*remap));
			remap->next = remap2;
			strcpy(remap->from, ep->value);

			/* split the string */
			split = strchr(remap->from, ';');
			if(split == NULL)
			{
				Sys_Printf("WARNING: Shader _remap key found in misc_model without a ; character\n");
				free(remap);
				remap = remap2;
				continue;
			}

			/* store the split */
			*split = '\0';
			strcpy(remap->to, (split + 1));

			/* note it */
			//% Sys_FPrintf( SYS_VRB, "Remapping %s to %s\n", remap->from, remap->to );
		}
	}

	/* ydnar: cel shader support */
	value = ValueForKey(e, "_celshader");
	if(value[0] == '\0')
		value = ValueForKey(&entities[0], "_celshader");
	if(value[0] != '\0')
	{
		sprintf(shader, "textures/%s", value);
		celShader = ShaderInfoForShader(shader);
	}
	else
		celShader = NULL;

	/* get lightmap scale */
	/* jal : entity based _samplesize */
	lightmapSampleSize = 0;
	if(strcmp("", ValueForKey(e, "_lightmapsamplesize")))
		lightmapSampleSize = IntForKey(e, "_lightmapsamplesize");
	else if(strcmp("", ValueForKey(e, "_samplesize")))
		lightmapSampleSize = IntForKey(e, "_samplesize");

	if(lightmapSampleSize < 0)
		lightmapSampleSize = 0;

	if(lightmapSampleSize > 0.0f)
		Sys_Printf(" has lightmap sample size of %.d\n", lightmapSampleSize);

	/* get lightmap scale */
	/* vortex: added _ls key (short name of lightmapscale) */
	lightmapScale = 0.0f;
	if(strcmp("", ValueForKey(e, "lightmapscale")) ||
	   strcmp("", ValueForKey(e, "_lightmapscale")) || strcmp("", ValueForKey(e, "_ls")))
	{
		lightmapScale = FloatForKey(e, "lightmapscale");
		if(lightmapScale <= 0.0f)
			lightmapScale = FloatForKey(e, "_lightmapscale");
		if(lightmapScale <= 0.0f)
			lightmapScale = FloatForKey(e, "_ls");
		if(lightmapScale < 0.0f)
			lightmapScale = 0.0f;
		if(lightmapScale > 0.0f)
			Sys_Printf("misc_model has lightmap scale of %.4f\n", lightmapScale);
	}

	/* jal : entity based _shadeangle */
	shadeAngle = 0.0f;
	if(strcmp("", ValueForKey(e, "_shadeangle")))
		shadeAngle = FloatForKey(e, "_shadeangle");
	/* vortex' aliases */
	else if(strcmp("", ValueForKey(e, "_smoothnormals")))
		shadeAngle = FloatForKey(e, "_smoothnormals");
	else if(strcmp("", ValueForKey(e, "_sn")))
		shadeAngle = FloatForKey(e, "_sn");
	else if(strcmp("", ValueForKey(e, "_smooth")))
		shadeAngle = FloatForKey(e, "_smooth");

	if(shadeAngle < 0.0f)
		shadeAngle = 0.0f;

	if(shadeAngle > 0.0f)
		Sys_Printf("misc_model has shading angle of %.4f\n", shadeAngle);

	/* insert the model */
	InsertModel((char *)model, frame, transform, rotation, remap, celShader, mapEntityNum, castShadows, recvShadows, spawnFlags,
				lightmapScale, lightmapSampleSize, shadeAngle);

	/* free shader remappings */
	while(remap != NULL)
	{
		remap2 = remap->next;
		free(remap);
		remap = remap2;
	}
}