// Scale object bounding box
void TrackMD3Scale(entity_t *e, LPCSTR key, LPCSTR value)
{
	float oldscale,scale;

	if (strcmpi(key, "scale") != 0)
	{
		return;
	}

	if (e->eclass->fixedsize && ((strnicmp(e->eclass->name, "misc_",5) == 0) ||
			(strnicmp(e->eclass->name, "light_",6) == 0)))
	{
		oldscale = FloatForKey (e, "scale");
		scale = atof(value);
		if (oldscale != scale)	// Value unchanged??????
		{
	      Brush_Scale2(e->eclass,e->brushes.onext, scale,e->origin,true);

			float a = FloatForKey (e, "angle");
			if (a)
			{
				// Re-rotate bbox
				vec3_t vAngle;
				vAngle[0] = vAngle[1] = 0;
				vAngle[2] = a;
				Brush_Rotate(e->brushes.onext, vAngle, e->origin, true);
			}
		} 
	}
}
Exemple #2
0
//===========================================================================
// this function sets the func_rotating_door in it's final position
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void AAS_PositionFuncRotatingBrush(entity_t *mapent, mapbrush_t *brush)
{
	int    spawnflags, i;
	float  distance;
	vec3_t movedir, angles, pos1, pos2;
	side_t *s;

	spawnflags = FloatForKey(mapent, "spawnflags");
	VectorClear(movedir);
	if (spawnflags & DOOR_X_AXIS)
	{
		movedir[2] = 1.0;       //roll
	}
	else if (spawnflags & DOOR_Y_AXIS)
	{
		movedir[0] = 1.0;       //pitch
	}
	else     // Z_AXIS
	{
		movedir[1] = 1.0;       //yaw

	}
	// check for reverse rotation
	if (spawnflags & DOOR_REVERSE)
	{
		VectorInverse(movedir);
	}

	distance = FloatForKey(mapent, "distance");
	if (!distance)
	{
		distance = 90;
	}

	GetVectorForKey(mapent, "angles", angles);
	VectorCopy(angles, pos1);
	VectorMA(angles, -distance, movedir, pos2);
	// if it starts open, switch the positions
	if (spawnflags & DOOR_START_OPEN)
	{
		VectorCopy(pos2, angles);
		VectorCopy(pos1, pos2);
		VectorCopy(angles, pos1);
		VectorInverse(movedir);
	} //end if
	  //
	for (i = 0; i < brush->numsides; i++)
	{
		s           = &brush->original_sides[i];
		s->planenum = AAS_TransformPlane(s->planenum, mapent->origin, pos2);
	} //end for
	  //
	FreeBrushWindings(brush);
	AAS_MakeBrushWindings(brush);
	AddBrushBevels(brush);
	FreeBrushWindings(brush);
} //end of the function AAS_PositionFuncRotatingBrush
Exemple #3
0
/*
==================
LoadEntities
==================
*/
void LoadEntities (void)
{
	char 		*s, *s2;
	entity_t	*e;
	lightentity_t	*le;
	int			i, j;

	ParseEntities ();
	
// go through all the entities
	for (i=1 ; i<num_entities ; i++)
	{
		e = &entities[i];

		s = ValueForKey (e, "classname");
		if (strncmp (s, "light", 5))
			continue;

		le = &lightentities[numlightentities];
		numlightentities++;

		strcpy (le->classname, s);
		le->light = FloatForKey (e, "light");
		if (!le->light)
			le->light = DEFAULTLIGHTLEVEL;
		le->style = FloatForKey (e, "style");
		le->angle = FloatForKey (e, "angle");
		GetVectorForKey (e, "origin", le->origin);

		s = ValueForKey (e, "target");
		if (!s[0])
			continue;

		// find matching targetname
		for (j=1 ; j<num_entities ; j++)
		{
			s2 = ValueForKey (&entities[j], "targetname");
			if (!strcmp (s, s2))
			{
				le->targetent = true;
				GetVectorForKey (&entities[j], "origin", le->targetorigin);
				break;
			}
		}
		if (j == num_entities)
			printf ("WARNING: entity %i has unmatched target %s\n", i, s);
	}

	qprintf ("%d lightentities\n", numlightentities);

}
void TrackMD3Angles(entity_t *e, LPCSTR key, LPCSTR value)
{
  if (strcmpi(key, "angle") != 0)
  {
    return;
  }

#ifdef SOF
  if (e->eclass->fixedsize && 
		(
			(strnicmp(e->eclass->name, "misc_",			5) == 0) ||
			(strnicmp(e->eclass->name, "light_",		6) == 0) || 
			(strnicmp(e->eclass->name, "m_",			2) == 0) ||
			(strnicmp(e->eclass->name, "item_weapon_",	12)== 0) ||
			(strnicmp(e->eclass->name, "item_ammo_",	10)== 0)
		)
	  )
#else
  if (e->eclass->fixedsize && strnicmp (e->eclass->name, "misc_model",10) == 0)
#endif
  {
    float a = FloatForKey (e, "angle");
    float b = atof(value);
    if (a != b)
    {
      vec3_t vAngle;
      vAngle[0] = vAngle[1] = 0;
      vAngle[2] = -a;
      Brush_Rotate(e->brushes.onext, vAngle, e->origin, true);
      vAngle[2] = b;
      Brush_Rotate(e->brushes.onext, vAngle, e->origin, true);

#ifdef QUAKE3
	  //
	  // auto assign new bounding box to model?
	  //
	  char *_p = ValueForKey(e, "mins");
	  char *_p2= ValueForKey(e, "maxs");
	  char *_p3= ValueForKey(e, sKEYFIELD_AUTOBOUND);
	  //
	  // if either key is missing then update both... (or if they do exist, but were only set by this code in the first place and therefore can be overwritten)
	  //
	  if ( ((strlen(_p) == 0) || (strlen(_p2) == 0)) || strlen(_p3) )
	  {
		SetKeyValue (e, sKEYFIELD_AUTOBOUND, "1");

		vec3_t vMins,vMaxs;

		VectorSubtract(e->brushes.onext->mins, e->origin, vMins);
		VectorSubtract(e->brushes.onext->maxs, e->origin, vMaxs);

		SetKeyValue (e, "mins", va("%i %i %i", (int)vMins[0], (int)vMins[1], (int)vMins[2]));
		SetKeyValue (e, "maxs", va("%i %i %i", (int)vMaxs[0], (int)vMaxs[1], (int)vMaxs[2]));
	  }
#endif


    }
  }
}
Exemple #5
0
void DrawBrushEntityName (brush_t *b)
{
	char	*name;
	float	a, s, c;
	vec3_t	mid;
	int		i;

	if (!b->owner)
		return;		// during contruction

	if (b->owner == world_entity)
		return;

	if (b != b->owner->brushes.onext)
		return;	// not key brush

	// draw the angle pointer
	a = FloatForKey (b->owner, "angle");
	if (a)
	{
		s = sin(a/180*pMath_PI);
		c = cos(a/180*pMath_PI);
		for (i=0 ; i<3 ; i++)
			mid[i] = (b->mins[i] + b->maxs[i])*0.5;

		glBegin (GL_LINE_STRIP);
		glVertex3fv (mid);
		mid[0] += c*8;
		mid[1] += s*8;
		glVertex3fv (mid);
		mid[0] -= c*4;
		mid[1] -= s*4;
		mid[0] -= s*4;
		mid[1] += c*4;
		glVertex3fv (mid);
		mid[0] += c*4;
		mid[1] += s*4;
		mid[0] += s*4;
		mid[1] -= c*4;
		glVertex3fv (mid);
		mid[0] -= c*4;
		mid[1] -= s*4;
		mid[0] += s*4;
		mid[1] -= c*4;
		glVertex3fv (mid);
		glEnd ();
	}

	if (!g_qeglobals.d_savedinfo.show_names)
		return;

	name = ValueForKey (b->owner, "classname");
	glRasterPos2f (b->mins[0]+4, b->mins[1]+4);
	glCallLists (strlen(name), GL_UNSIGNED_BYTE, name);
}
Exemple #6
0
//
// move the view to a start position
//
void Map_StartPosition(){
	entity_t *ent = AngledEntity();

	g_pParentWnd->GetCamWnd()->Camera()->angles[PITCH] = 0;
	if ( ent ) {
		GetVectorForKey( ent, "origin", g_pParentWnd->GetCamWnd()->Camera()->origin );
		GetVectorForKey( ent, "origin", g_pParentWnd->GetXYWnd()->GetOrigin() );
		g_pParentWnd->GetCamWnd()->Camera()->angles[YAW] = FloatForKey( ent, "angle" );
	}
	else
	{
		g_pParentWnd->GetCamWnd()->Camera()->angles[YAW] = 0;
		VectorCopy( vec3_origin, g_pParentWnd->GetCamWnd()->Camera()->origin );
		VectorCopy( vec3_origin, g_pParentWnd->GetXYWnd()->GetOrigin() );
	}
}
Exemple #7
0
/*
 =======================================================================================================================
 =======================================================================================================================
 */
void TrackMD3Angles(entity_t *e, const char *key, const char *value) {
	if ( idStr::Icmp(key, "angle") != 0 ) {
		return;
	}

	if ((e->eclass->fixedsize && e->eclass->nShowFlags & ECLASS_MISCMODEL) || EntityHasModel(e)) {
		float	a = FloatForKey(e, "angle");
		float	b = atof(value);
		if (a != b) {
			idVec3	vAngle;
			vAngle[0] = vAngle[1] = 0;
			vAngle[2] = -a;
			Brush_Rotate(e->brushes.onext, vAngle, e->origin, true);
			vAngle[2] = b;
			Brush_Rotate(e->brushes.onext, vAngle, e->origin, true);
		}
	}
}
Exemple #8
0
//-----------------------------------------------------------------------------
// Compute the bounding box, excluding 3D skybox + skybox, add it to keyvalues
//-----------------------------------------------------------------------------
float DetermineVisRadius( )
{
    float flRadius = -1;

    // Check the max vis range to determine the vis radius
    for (int i = 0; i < num_entities; ++i)
    {
        char* pEntity = ValueForKey(&entities[i], "classname");
        if (!stricmp(pEntity, "env_fog_controller"))
        {
            flRadius = FloatForKey (&entities[i], "farz");
            if (flRadius == 0.0f)
                flRadius = -1.0f;
            break;
        }
    }

    return flRadius;
}
Exemple #9
0
/*
================
Map_LoadFile
================
*/
void Map_LoadFile (char *filename)
{
    char		*buf;
	entity_t	*ent;
	char         temp[1024];

	Sys_BeginWait ();
	Select_Deselect();
	//SetInspectorMode(W_CONSOLE);

	QE_ConvertDOSToUnixName( temp, filename );
	Sys_Printf ("Map_LoadFile: %s\n", temp );

	Map_Free ();
	//++timo FIXME: maybe even easier to have Group_Init called from Map_Free?
	Group_Init();

	g_qeglobals.d_parsed_brushes = 0;
	strcpy (currentmap, filename);

	if (LoadFile (filename, (void **)&buf) != -1)
	{

		StartTokenParsing (buf);
		g_qeglobals.d_num_entities = 0;

		// Timo
		// will be used in Entity_Parse to detect if a conversion between brush formats is needed
		g_qeglobals.bNeedConvert = false;
		g_qeglobals.bOldBrushes = false;
		g_qeglobals.bPrimitBrushes = false;

		while (1)
		{
			ent = Entity_Parse (false, &active_brushes);
			if (!ent)
				break;
			if (!strcmp(ValueForKey (ent, "classname"), "worldspawn"))
			{
				if (world_entity)
					Sys_Printf ("WARNING: multiple worldspawn\n");
				world_entity = ent;
			}
			else if (!strcmp(ValueForKey (ent, "classname"), "group_info"))
      {
        // it's a group thing!
        Group_Add(ent);
        Entity_Free(ent);
      }
      else
			{
				// add the entity to the end of the entity list
				ent->next = &entities;
				ent->prev = entities.prev;
				entities.prev->next = ent;
				entities.prev = ent;
				g_qeglobals.d_num_entities++;
			}
		}
	}

  free (buf);

	if (!world_entity)
	{
		Sys_Printf ("No worldspawn in map.\n");
		Map_New ();
		return;
	}

    Sys_Printf ("--- LoadMapFile ---\n");
    Sys_Printf ("%s\n", temp );

    Sys_Printf ("%5i brushes\n",  g_qeglobals.d_parsed_brushes );
    Sys_Printf ("%5i entities\n", g_qeglobals.d_num_entities);

	Map_RestoreBetween ();

	Sys_Printf ("Map_BuildAllDisplayLists\n");
    Map_BuildBrushData();

	// reset the "need conversion" flag
	// conversion to the good format done in Map_BuildBrushData
	g_qeglobals.bNeedConvert=false;

	//
	// move the view to a start position
	//
  ent = AngledEntity();

  g_pParentWnd->GetCamera()->Camera().angles[PITCH] = 0;
	if (ent)
	{
		GetVectorForKey (ent, "origin", g_pParentWnd->GetCamera()->Camera().origin);
		GetVectorForKey (ent, "origin", g_pParentWnd->GetXYWnd()->GetOrigin());
		g_pParentWnd->GetCamera()->Camera().angles[YAW] = FloatForKey (ent, "angle");
	}
	else
	{
		g_pParentWnd->GetCamera()->Camera().angles[YAW] = 0;
		VectorCopy (vec3_origin, g_pParentWnd->GetCamera()->Camera().origin);
		VectorCopy (vec3_origin, g_pParentWnd->GetXYWnd()->GetOrigin());
	}

	Map_RegionOff ();


	modified = false;
	Sys_SetTitle (temp);

	Texture_ShowInuse ();

	Sys_EndWait();
	Sys_UpdateWindows (W_ALL);

}
void CPlugInManager::CommitEntityHandleToMap(LPVOID vpEntity)
{
	entity_t *pe;
	eclass_t *e;
	brush_t		*b;
	vec3_t mins,maxs;
	bool has_brushes;
	for (int i=0 ; i < m_EntityHandles.GetSize() ; i++ )
	{
		if (vpEntity == m_EntityHandles.GetAt(i))
		{
			m_EntityHandles.RemoveAt(i);
			pe = reinterpret_cast<entity_t*>(vpEntity);
			// fill additional fields
			// straight copy from Entity_Parse
			// entity_t::origin
			GetVectorForKey (pe, "origin", pe->origin);
			// entity_t::eclass
			if (pe->brushes.onext == &pe->brushes)
				has_brushes = false;
			else
				has_brushes = true;
			e = Eclass_ForName (ValueForKey (pe, "classname"), has_brushes);
			pe->eclass = e;
			// fixedsize
			if (e->fixedsize)
			{
				if (pe->brushes.onext != &pe->brushes)
				{
					Sys_Printf("Warning : Fixed size entity with brushes in CPlugInManager::CommitEntityHandleToMap\n");
				}
				// create a custom brush
				VectorAdd(e->mins, pe->origin, mins);
				VectorAdd(e->maxs, pe->origin, maxs);
				float a = 0;
				if (e->nShowFlags & ECLASS_MISCMODEL)
				{
					char* p = ValueForKey(pe, "model");
					if (p != NULL && strlen(p) > 0)
					{
						vec3_t vMin, vMax;
						a = FloatForKey (pe, "angle");
				        if (GetCachedModel(pe, p, vMin, vMax))
				        {
						      // create a custom brush
						      VectorAdd (pe->md3Class->mins, pe->origin, mins);
						      VectorAdd (pe->md3Class->maxs, pe->origin, maxs);
				        }
					}
			    }
		
			    b = Brush_Create (mins, maxs, &e->texdef);

			    if (a)
			    {
					vec3_t vAngle;
					vAngle[0] = vAngle[1] = 0;
					vAngle[2] = a;
					Brush_Rotate(b, vAngle, pe->origin, false);
				}

				b->owner = pe;

				b->onext = pe->brushes.onext;
				b->oprev = &pe->brushes;
				pe->brushes.onext->oprev = b;
				pe->brushes.onext = b;
			}
			else
			{	// brush entity
				if (pe->brushes.next == &pe->brushes)
					Sys_Printf ("Warning: Brush entity with no brushes in CPlugInManager::CommitEntityHandleToMap\n");
			}

			// add brushes to the active brushes list
			// and build them along the way
			for (b=pe->brushes.onext ; b != &pe->brushes ; b=b->onext)
			{
				// convert between old brushes and brush primitive
				if (g_qeglobals.m_bBrushPrimitMode)
				{
					// we only filled the shift scale rot fields, needs conversion
					Brush_Build( b, true, true, true );
				}
				else
				{
					// we are using old brushes
					Brush_Build( b );
				}
				b->next = active_brushes.next;
				active_brushes.next->prev = b;
				b->prev = &active_brushes;
				active_brushes.next = b;
			}

			// handle worldspawn entities
			// if worldspawn has no brushes, use the new one
			if (!strcmp(ValueForKey (pe, "classname"), "worldspawn"))
			{
				if ( world_entity && ( world_entity->brushes.onext != &world_entity->brushes ) )
				{
					// worldspawn already has brushes
					Sys_Printf ("Commiting worldspawn as func_group\n");
					SetKeyValue(pe, "classname", "func_group");
					// add the entity to the end of the entity list
					pe->next = &entities;
					pe->prev = entities.prev;
					entities.prev->next = pe;
					entities.prev = pe;
					g_qeglobals.d_num_entities++;
				}
				else
				{
					// there's a worldspawn with no brushes, we assume the map is empty
					if ( world_entity )
					{
						Entity_Free( world_entity );
						world_entity = pe;
					}
					else
						Sys_Printf("Warning : unexpected world_entity == NULL in CommitEntityHandleToMap\n");
				}
			}
			else
			{
				// add the entity to the end of the entity list
				pe->next = &entities;
				pe->prev = entities.prev;
				entities.prev->next = pe;
				entities.prev = pe;
				g_qeglobals.d_num_entities++;
			}
		}
	}
}
Exemple #11
0
 /*
 =======================================================================================================================
	Map_LoadFile
 =======================================================================================================================
 */
void Map_LoadFile(const char *filename) {
	entity_t *ent;
	CWaitDlg dlg;
	idStr fileStr, status;
	idMapFile mapfile;

	Sys_BeginWait();
	Select_Deselect();

	dlg.AllowCancel( true );
	idStr( filename ).ExtractFileName( fileStr );
	sprintf( status, "Loading %s...", fileStr.c_str() );
	dlg.SetWindowText( status );
	sprintf( status, "Reading file %s...", fileStr.c_str() );
	dlg.SetText( status );

	// SetInspectorMode(W_CONSOLE);
	fileStr = filename;
	fileStr.BackSlashesToSlashes();

	common->Printf( "Map_LoadFile: %s\n", fileStr.c_str() );

	Map_Free();

	g_qeglobals.d_parsed_brushes = 0;
	strcpy( currentmap, filename );

	if(mapfile.Parse(filename, true, true)) {
		g_qeglobals.bNeedConvert = false;
		g_qeglobals.bOldBrushes = false;
		g_qeglobals.bPrimitBrushes = false;
		g_qeglobals.mapVersion = 1.0;

		long lastUpdate = 0;
		int count = mapfile.GetNumEntities();
		for (int i = 0; i < count; i++) {
			idMapEntity *mapent = mapfile.GetEntity(i);
			if (mapent) {
				idStr classname = mapent->epairs.GetString("classname");
				// Update 20 times a second
				if ( (GetTickCount() - lastUpdate) > 50 ) {
					lastUpdate = GetTickCount();
					sprintf(status, "Loading entity %i (%s)...", i, classname.c_str());
					dlg.SetText(status);
				}
				if ( dlg.CancelPressed() ) {
					Sys_Status("Map load cancelled.\n");
					Map_New();
					return;
				}
				if (classname == "worldspawn") {
					world_entity = EntityFromMapEntity(mapent, &dlg);
					Entity_PostParse(world_entity, &active_brushes);
				} else {
					ent = EntityFromMapEntity(mapent, &dlg);
					Entity_PostParse(ent, &active_brushes);
					Entity_Name(ent, true);
					// add the entity to the end of the entity list
					ent->next = &entities;
					ent->prev = entities.prev;
					entities.prev->next = ent;
					entities.prev = ent;
					g_qeglobals.d_num_entities++;
				}
			}
		}
	}

	if (!world_entity) {
		Sys_Status("No worldspawn in map.\n");
		Map_New();
		return;
	}

	common->Printf("--- LoadMapFile ---\n");
	common->Printf("%s\n", fileStr.c_str());

	common->Printf("%5i brushes\n", g_qeglobals.d_parsed_brushes);
	common->Printf("%5i entities\n", g_qeglobals.d_num_entities);

	dlg.SetText("Restoring Between");
	Map_RestoreBetween();

	dlg.SetText("Building Brush Data");
	common->Printf("Map_BuildAllDisplayLists\n");
	Map_BuildBrushData();

	//
	// reset the "need conversion" flag conversion to the good format done in
	// Map_BuildBrushData
	//
	g_qeglobals.bNeedConvert = false;

	// move the view to a start position
	ent = AngledEntity();

	g_pParentWnd->GetCamera()->Camera().angles[PITCH] = 0;

	if (ent) {
		GetVectorForKey(ent, "origin", g_pParentWnd->GetCamera()->Camera().origin);
		GetVectorForKey(ent, "origin", g_pParentWnd->GetXYWnd()->GetOrigin());
		g_pParentWnd->GetCamera()->Camera().angles[YAW] = FloatForKey(ent, "angle");
	}
	else {
		g_pParentWnd->GetCamera()->Camera().angles[YAW] = 0;
		VectorCopy(vec3_origin, g_pParentWnd->GetCamera()->Camera().origin);
		VectorCopy(vec3_origin, g_pParentWnd->GetXYWnd()->GetOrigin());
	}

	Map_RegionOff();

	mapModified = 0;

	if (GetFileAttributes(filename) & FILE_ATTRIBUTE_READONLY) {
		fileStr += " (read only) ";
	}
	Sys_SetTitle(fileStr);

	Texture_ShowInuse();

	if (g_pParentWnd->GetCamera()->GetRenderMode()) {
		g_pParentWnd->GetCamera()->BuildRendererState();
	}

	Sys_EndWait();
	Sys_UpdateWindows(W_ALL);
}
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void AAS_PositionBrush(entity_t *mapent, mapbrush_t *brush)
{
	side_t *s;
	float newdist;
	int i, notteam;
	char *model;

	if (!strcmp(ValueForKey(mapent, "classname"), "func_door_rotating"))
	{
		AAS_PositionFuncRotatingBrush(mapent, brush);
	} //end if
	else
	{
		if (mapent->origin[0] || mapent->origin[1] || mapent->origin[2])
		{
			for (i = 0; i < brush->numsides; i++)
			{
				s = &brush->original_sides[i];
				newdist = mapplanes[s->planenum].dist +
						DotProduct(mapplanes[s->planenum].normal, mapent->origin);
				s->planenum = FindFloatPlane(mapplanes[s->planenum].normal, newdist);
			} //end for
		} //end if
		//if it's a trigger hurt
		if (!strcmp("trigger_hurt", ValueForKey(mapent, "classname")))
		{
			notteam = FloatForKey(mapent, "bot_notteam");
			if ( notteam == 1 ) {
				brush->contents |= CONTENTS_NOTTEAM1;
			}
			else if ( notteam == 2 ) {
				brush->contents |= CONTENTS_NOTTEAM2;
			}
			else {
				// always avoid so set lava contents
				brush->contents |= CONTENTS_LAVA;
			}
		} //end if
		//
		else if (!strcmp("trigger_push", ValueForKey(mapent, "classname")))
		{
			//set the jumppad contents
			brush->contents = CONTENTS_JUMPPAD;
			//Log_Print("found trigger_push brush\n");
		} //end if
		//
		else if (!strcmp("trigger_multiple", ValueForKey(mapent, "classname")))
		{
			//set teleporter contents
			brush->contents = CONTENTS_TELEPORTER;
			//Log_Print("found trigger_multiple teleporter brush\n");
		} //end if
		//
		else if (!strcmp("trigger_teleport", ValueForKey(mapent, "classname")))
		{
			//set teleporter contents
			brush->contents = CONTENTS_TELEPORTER;
			//Log_Print("found trigger_teleport teleporter brush\n");
		} //end if
		else if (!strcmp("func_door", ValueForKey(mapent, "classname")))
		{
			//set mover contents
			brush->contents = CONTENTS_MOVER;
			//get the model number
			model = ValueForKey(mapent, "model");
			brush->modelnum = atoi(model+1);
		} //end if
	} //end else
} //end of the function AAS_PositionBrush
//-----------------------------------------------------------------------------
// Places Detail Objects in the level
//-----------------------------------------------------------------------------
void EmitDetailModels()
{
	StartPacifier("Placing detail props : ");

	// Place stuff on each face
	dface_t* pFace = dfaces;
	for (int j = 0; j < numfaces; ++j)
	{
		UpdatePacifier( (float)j / (float)numfaces );

		// Get at the material associated with this face
		texinfo_t* pTexInfo = &texinfo[pFace[j].texinfo];
		dtexdata_t* pTexData = GetTexData( pTexInfo->texdata );

		// Try to get at the material
		bool found;
		MaterialSystemMaterial_t handle = 
			FindOriginalMaterial( TexDataStringTable_GetString( pTexData->nameStringTableID ), 
						  &found, false );
		if (!found)
			continue;

		// See if its got any detail objects on it
		const char* pDetailType = GetMaterialVar( handle, "%detailtype" );
		if (!pDetailType)
			continue;

		// Get the detail type...
		DetailObject_t search;
		search.m_Name = pDetailType;
		int objectType = s_DetailObjectDict.Find(search);
		if (objectType < 0)
		{
			Warning("Material %s uses unknown detail object type %s!\n",	
				TexDataStringTable_GetString( pTexData->nameStringTableID ),
				pDetailType);
			continue;
		}

		// Emit objects on a particular face
		DetailObject_t& detail = s_DetailObjectDict[objectType];

		if (pFace[j].dispinfo < 0)
		{
			EmitDetailObjectsOnFace( &pFace[j], detail );
		}
		else
		{
			// Get a CCoreDispInfo. All we need is the triangles and lightmap texture coordinates.
			mapdispinfo_t *pMapDisp = &mapdispinfo[pFace[j].dispinfo];
			CCoreDispInfo coreDispInfo;
			DispMapToCoreDispInfo( pMapDisp, &coreDispInfo, &pFace[j] );

			EmitDetailObjectsOnDisplacementFace( &pFace[j], detail, coreDispInfo );
		}
	}

	// Emit specifically specified detail props
	Vector origin;
	QAngle angles;
	Vector2D pos[2];
	Vector2D tex[2];
	for (int i = 0; i < num_entities; ++i)
	{
		char* pEntity = ValueForKey(&entities[i], "classname");
		if (!strcmp(pEntity, "detail_prop") || !strcmp(pEntity, "prop_detail"))
		{
			GetVectorForKey( &entities[i], "origin", origin );
			GetAnglesForKey( &entities[i], "angles", angles );
			char* pModelName = ValueForKey( &entities[i], "model" );
			int nOrientation = IntForKey( &entities[i], "detailOrientation" );

			AddDetailToLump( pModelName, origin, angles, nOrientation );

			// strip this ent from the .bsp file
			entities[i].epairs = 0;
			continue;
		}

		if (!strcmp(pEntity, "prop_detail_sprite"))
		{
			GetVectorForKey( &entities[i], "origin", origin );
			GetAnglesForKey( &entities[i], "angles", angles );
			int nOrientation = IntForKey( &entities[i], "detailOrientation" );
			GetVector2DForKey( &entities[i], "position_ul", pos[0] );
			GetVector2DForKey( &entities[i], "position_lr", pos[1] );
			GetVector2DForKey( &entities[i], "tex_ul", tex[0] );
			GetVector2DForKey( &entities[i], "tex_size", tex[1] );
			float flTextureSize = FloatForKey( &entities[i], "tex_total_size" );

			tex[1].x += tex[0].x - 0.5f;
			tex[1].y += tex[0].y - 0.5f;
			tex[0].x += 0.5f;
			tex[0].y += 0.5f;
			tex[0] /= flTextureSize;
			tex[1] /= flTextureSize;

			AddDetailSpriteToLump( origin, angles, nOrientation, pos, tex, 1.0f );

			// strip this ent from the .bsp file
			entities[i].epairs = 0;
			continue;
		}
	}

	EndPacifier( true );
}
Exemple #14
0
/**
 * @brief Create lights out of patches and entity lights
 * @sa LightWorld
 * @sa BuildPatch
 */
void BuildLights (void)
{
	int i;
	light_t* l;

	/* surfaces */
	for (i = 0; i < MAX_MAP_FACES; i++) {
		/* iterate subdivided patches */
		for(const patch_t* p = face_patches[i]; p; p = p->next) {
			if (VectorEmpty(p->light))
				continue;

			numlights[config.compile_for_day]++;
			l = Mem_AllocType(light_t);

			VectorCopy(p->origin, l->origin);

			l->next = lights[config.compile_for_day];
			lights[config.compile_for_day] = l;

			l->type = emit_surface;

			l->intensity = ColorNormalize(p->light, l->color);
			l->intensity *= p->area * config.surface_scale;
		}
	}

	/* entities (skip the world) */
	for (i = 1; i < num_entities; i++) {
		float intensity;
		const char* color;
		const char* target;
		const entity_t* e = &entities[i];
		const char* name = ValueForKey(e, "classname");
		if (!Q_strstart(name, "light"))
			continue;

		/* remove those lights that are only for the night version */
		if (config.compile_for_day) {
			const int spawnflags = atoi(ValueForKey(e, "spawnflags"));
			if (!(spawnflags & 1))	/* day */
				continue;
		}

		numlights[config.compile_for_day]++;
		l = Mem_AllocType(light_t);

		GetVectorForKey(e, "origin", l->origin);

		/* link in */
		l->next = lights[config.compile_for_day];
		lights[config.compile_for_day] = l;

		intensity = FloatForKey(e, "light");
		if (!intensity)
			intensity = 300.0;
		color = ValueForKey(e, "_color");
		if (color && color[0] != '\0'){
			if (sscanf(color, "%f %f %f", &l->color[0], &l->color[1], &l->color[2]) != 3)
				Sys_Error("Invalid _color entity property given: %s", color);
			ColorNormalize(l->color, l->color);
		} else
			VectorSet(l->color, 1.0, 1.0, 1.0);
		l->intensity = intensity * config.entity_scale;
		l->type = emit_point;

		target = ValueForKey(e, "target");
		if (target[0] != '\0' || Q_streq(name, "light_spot")) {
			l->type = emit_spotlight;
			l->stopdot = FloatForKey(e, "_cone");
			if (!l->stopdot)
				l->stopdot = 10;
			l->stopdot = cos(l->stopdot * torad);
			if (target[0] != '\0') {	/* point towards target */
				entity_t* e2 = FindTargetEntity(target);
				if (!e2)
					Com_Printf("WARNING: light at (%i %i %i) has missing target '%s' - e.g. create an info_null that has a 'targetname' set to '%s'\n",
						(int)l->origin[0], (int)l->origin[1], (int)l->origin[2], target, target);
				else {
					vec3_t dest;
					GetVectorForKey(e2, "origin", dest);
					VectorSubtract(dest, l->origin, l->normal);
					VectorNormalize(l->normal);
				}
			} else {	/* point down angle */
				const float angle = FloatForKey(e, "angle");
				if (angle == ANGLE_UP) {
					l->normal[0] = l->normal[1] = 0.0;
					l->normal[2] = 1.0;
				} else if (angle == ANGLE_DOWN) {
					l->normal[0] = l->normal[1] = 0.0;
					l->normal[2] = -1.0;
				} else {
					l->normal[2] = 0;
					l->normal[0] = cos(angle * torad);
					l->normal[1] = sin(angle * torad);
				}
			}
		}
	}

	/* handle worldspawn light settings */
	{
		const entity_t* e = &entities[0];
		const char* ambient, *light, *angles, *color;
		float f;
		int i;

		if (config.compile_for_day) {
			ambient = ValueForKey(e, "ambient_day");
			light = ValueForKey(e, "light_day");
			angles = ValueForKey(e, "angles_day");
			color = ValueForKey(e, "color_day");
		} else {
			ambient = ValueForKey(e, "ambient_night");
			light = ValueForKey(e, "light_night");
			angles = ValueForKey(e, "angles_night");
			color = ValueForKey(e, "color_night");
		}

		if (light[0] != '\0')
			sun_intensity = atoi(light);

		if (angles[0] != '\0') {
			VectorClear(sun_angles);
			if (sscanf(angles, "%f %f", &sun_angles[0], &sun_angles[1]) != 2)
				Sys_Error("wrong angles values given: '%s'", angles);
			AngleVectors(sun_angles, sun_normal, nullptr, nullptr);
		}

		if (color[0] != '\0') {
			GetVectorFromString(color, sun_color);
			ColorNormalize(sun_color, sun_color);
		}

		if (ambient[0] != '\0')
			GetVectorFromString(ambient, sun_ambient_color);

		/* optionally pull brightness from worldspawn */
		f = FloatForKey(e, "brightness");
		if (f > 0.0)
			config.brightness = f;

		/* saturation as well */
		f = FloatForKey(e, "saturation");
		if (f > 0.0)
			config.saturation = f;
		else
			Verb_Printf(VERB_EXTRA, "Invalid saturation setting (%f) in worldspawn found\n", f);

		f = FloatForKey(e, "contrast");
		if (f > 0.0)
			config.contrast = f;
		else
			Verb_Printf(VERB_EXTRA, "Invalid contrast setting (%f) in worldspawn found\n", f);

		/* lightmap resolution downscale (e.g. 4 = 1 << 4) */
		i = atoi(ValueForKey(e, "quant"));
		if (i >= 1 && i <= 6)
			config.lightquant = i;
		else
			Verb_Printf(VERB_EXTRA, "Invalid quant setting (%i) in worldspawn found\n", i);
	}

	Verb_Printf(VERB_EXTRA, "light settings:\n * intensity: %i\n * sun_angles: pitch %f yaw %f\n * sun_color: %f:%f:%f\n * sun_ambient_color: %f:%f:%f\n",
		sun_intensity, sun_angles[0], sun_angles[1], sun_color[0], sun_color[1], sun_color[2], sun_ambient_color[0], sun_ambient_color[1], sun_ambient_color[2]);
	Verb_Printf(VERB_NORMAL, "%i direct lights for %s lightmap\n", numlights[config.compile_for_day], (config.compile_for_day ? "day" : "night"));
}
Exemple #15
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 #16
0
void ProcessDecals( void )
{
	int					i, j, x, y, pw[ 5 ], r, iterations, smoothNormals;
	float				distance, lightmapScale, backfaceAngle;
	vec4_t				projection, plane;
	vec3_t				origin, target, delta, lightmapAxis;
	vec3_t              minlight, minvertexlight, ambient, colormod;
	entity_t			*e, *e2;
	parseMesh_t			*p;
	mesh_t				*mesh, *subdivided;
	bspDrawVert_t		*dv[ 4 ];
	const char			*value;
	
	
	/* note it */
	Sys_FPrintf( SYS_VRB, "--- ProcessDecals ---\n" );

	/* no decals */
	if (nodecals)
	{
		for( i = 0; i < numEntities; i++ )
		{	
			/* get entity */
			e = &entities[ i ];
			value = ValueForKey( e, "classname" );
			if( Q_stricmp( value, "_decal" ) && Q_stricmp( value, "misc_decal" ) )
				continue;

			/* clear entity patches */
			e->patches = NULL; // fixme: LEAK!
		}
		return;
	}
	
	/* walk entity list */
	for( i = 0; i < numEntities; i++ )
	{
		/* get entity */
		e = &entities[ i ];
		value = ValueForKey( e, "classname" );
		if( Q_stricmp( value, "_decal" ) && Q_stricmp( value, "misc_decal" ) )
			continue;
		
		/* any patches? */
		if( e->patches == NULL )
		{
			Sys_Warning( e->mapEntityNum, "Decal entity without any patch meshes, ignoring." );
			e->epairs = NULL;	/* fixme: leak! */
			continue;
		}
		
		/* find target */
		value = ValueForKey( e, "target" );
		e2 = FindTargetEntity( value );
		
		/* no target? */
		if( e2 == NULL )
		{
			Sys_Warning( e->mapEntityNum, "Decal entity without a valid target, ignoring." );
			continue;
		}

		/* vortex: get lightmap scaling value for this entity */
		GetEntityLightmapScale( e, &lightmapScale, 0);

		/* vortex: get lightmap axis for this entity */
		GetEntityLightmapAxis( e, lightmapAxis, NULL );

		/* vortex: per-entity normal smoothing */
		GetEntityNormalSmoothing( e, &smoothNormals, 0);

		/* vortex: per-entity _minlight, _ambient, _color, _colormod */
		GetEntityMinlightAmbientColor( e, NULL, minlight, minvertexlight, ambient, colormod, qtrue );
		
		/* vortex: _backfacecull */
		if ( KeyExists(e, "_backfacecull") )
			backfaceAngle = FloatForKey(e, "_backfacecull");
		else if ( KeyExists(e, "_bfc") )
			backfaceAngle = FloatForKey(e, "_bfc");
		else
			backfaceAngle = 90.0f;

		/* walk entity patches */
		for( p = e->patches; p != NULL; p = e->patches )
		{
			/* setup projector */
			if( VectorCompare( e->origin, vec3_origin ) )
			{
				VectorAdd( p->eMins, p->eMaxs, origin );
				VectorScale( origin, 0.5f, origin );
			}
			else
				VectorCopy( e->origin, origin );
			
			VectorCopy( e2->origin, target );
			VectorSubtract( target, origin, delta );
			
			/* setup projection plane */
			distance = VectorNormalize( delta, projection );
			projection[ 3 ] = DotProduct( origin, projection );
			
			/* create projectors */
			if( distance > 0.125f )
			{
				/* tesselate the patch */
				iterations = IterationsForCurve( p->longestCurve, patchSubdivisions );
				subdivided = SubdivideMesh2( p->mesh, iterations );
				
				/* fit it to the curve and remove colinear verts on rows/columns */
				PutMeshOnCurve( *subdivided );
				mesh = RemoveLinearMeshColumnsRows( subdivided );
				FreeMesh( subdivided );
				
				/* offset by projector origin */
				for( j = 0; j < (mesh->width * mesh->height); j++ )
					VectorAdd( mesh->verts[ j ].xyz, e->origin, mesh->verts[ j ].xyz );
				
				/* iterate through the mesh quads */
				for( y = 0; y < (mesh->height - 1); y++ )
				{
					for( x = 0; x < (mesh->width - 1); x++ )
					{
						/* set indexes */
						pw[ 0 ] = x + (y * mesh->width);
						pw[ 1 ] = x + ((y + 1) * mesh->width);
						pw[ 2 ] = x + 1 + ((y + 1) * mesh->width);
						pw[ 3 ] = x + 1 + (y * mesh->width);
						pw[ 4 ] = x + (y * mesh->width);	/* same as pw[ 0 ] */
						
						/* set radix */
						r = (x + y) & 1;
						
						/* get drawverts */
						dv[ 0 ] = &mesh->verts[ pw[ r + 0 ] ];
						dv[ 1 ] = &mesh->verts[ pw[ r + 1 ] ];
						dv[ 2 ] = &mesh->verts[ pw[ r + 2 ] ];
						dv[ 3 ] = &mesh->verts[ pw[ r + 3 ] ];
						
						/* planar? (nuking this optimization as it doesn't work on non-rectangular quads) */
						plane[ 0 ] = 0.0f;	/* stupid msvc */
						if( 0 && PlaneFromPoints( plane, dv[ 0 ]->xyz, dv[ 1 ]->xyz, dv[ 2 ]->xyz ) && fabs( DotProduct( dv[ 1 ]->xyz, plane ) - plane[ 3 ] ) <= PLANAR_EPSILON )
						{
							/* make a quad projector */
							MakeDecalProjector( i, p->shaderInfo, projection, distance, 4, dv, cos(backfaceAngle / 180.0f * Q_PI), lightmapScale, lightmapAxis, minlight, minvertexlight, ambient, colormod, smoothNormals);
						}
						else
						{
							/* make first triangle */
							MakeDecalProjector( i, p->shaderInfo, projection, distance, 3, dv, cos(backfaceAngle / 180.0f * Q_PI), lightmapScale, lightmapAxis, minlight, minvertexlight, ambient, colormod, smoothNormals);
							
							/* make second triangle */
							dv[ 1 ] = dv[ 2 ];
							dv[ 2 ] = dv[ 3 ];
							MakeDecalProjector( i, p->shaderInfo, projection, distance, 3, dv, cos(backfaceAngle / 180.0f * Q_PI), lightmapScale, lightmapAxis, minlight, minvertexlight, ambient, colormod, smoothNormals);
						}
					}
				}
				
				/* clean up */
				free( mesh );
			}
			
			/* remove patch from entity (fixme: leak!) */
			e->patches = p->next;
			
			/* push patch to worldspawn (enable this to debug projectors) */
			#if 0
				p->next = entities[ 0 ].patches;
				entities[ 0 ].patches = p;
			#endif
		}
	}
	
	/* emit some stats */
	Sys_FPrintf( SYS_VRB, "%9d decal projectors\n", numProjectors );
}
Exemple #17
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 #18
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 #19
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;
	}
}
Exemple #20
0
int ScaleBSPMain( int argc, char **argv ){
	int i, j;
	float f, a;
	vec3_t scale;
	vec3_t vec;
	char str[ 1024 ];
	int uniform, axis;
	qboolean texscale;
	float *old_xyzst = NULL;
	float spawn_ref = 0;


	/* arg checking */
	if ( argc < 3 ) {
		Sys_Printf( "Usage: q3map [-v] -scale [-tex] [-spawn_ref <value>] <value> <mapname>\n" );
		return 0;
	}

	texscale = qfalse;
	for ( i = 1; i < argc - 2; ++i )
	{
		if ( !strcmp( argv[i], "-tex" ) ) {
			texscale = qtrue;
		}
		else if ( !strcmp( argv[i], "-spawn_ref" ) ) {
			spawn_ref = atof( argv[i + 1] );
			++i;
		}
		else{
			break;
		}
	}

	/* get scale */
	// if(argc-2 >= i) // always true
	scale[2] = scale[1] = scale[0] = atof( argv[ argc - 2 ] );
	if ( argc - 3 >= i ) {
		scale[1] = scale[0] = atof( argv[ argc - 3 ] );
	}
	if ( argc - 4 >= i ) {
		scale[0] = atof( argv[ argc - 4 ] );
	}

	uniform = ( ( scale[0] == scale[1] ) && ( scale[1] == scale[2] ) );

	if ( scale[0] == 0.0f || scale[1] == 0.0f || scale[2] == 0.0f ) {
		Sys_Printf( "Usage: q3map [-v] -scale [-tex] [-spawn_ref <value>] <value> <mapname>\n" );
		Sys_Printf( "Non-zero scale value required.\n" );
		return 0;
	}

	/* do some path mangling */
	strcpy( source, ExpandArg( argv[ argc - 1 ] ) );
	StripExtension( source );
	DefaultExtension( source, ".bsp" );

	/* load the bsp */
	Sys_Printf( "Loading %s\n", source );
	LoadBSPFile( source );
	ParseEntities();

	/* note it */
	Sys_Printf( "--- ScaleBSP ---\n" );
	Sys_FPrintf( SYS_VRB, "%9d entities\n", numEntities );

	/* scale entity keys */
	for ( i = 0; i < numBSPEntities && i < numEntities; i++ )
	{
		/* scale origin */
		GetVectorForKey( &entities[ i ], "origin", vec );
		if ( ( vec[ 0 ] || vec[ 1 ] || vec[ 2 ] ) ) {
			if ( !strncmp( ValueForKey( &entities[i], "classname" ), "info_player_", 12 ) ) {
				vec[2] += spawn_ref;
			}
			vec[0] *= scale[0];
			vec[1] *= scale[1];
			vec[2] *= scale[2];
			if ( !strncmp( ValueForKey( &entities[i], "classname" ), "info_player_", 12 ) ) {
				vec[2] -= spawn_ref;
			}
			sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
			SetKeyValue( &entities[ i ], "origin", str );
		}

		a = FloatForKey( &entities[ i ], "angle" );
		if ( a == -1 || a == -2 ) { // z scale
			axis = 2;
		}
		else if ( fabs( sin( DEG2RAD( a ) ) ) < 0.707 ) {
			axis = 0;
		}
		else{
			axis = 1;
		}

		/* scale door lip */
		f = FloatForKey( &entities[ i ], "lip" );
		if ( f ) {
			f *= scale[axis];
			sprintf( str, "%f", f );
			SetKeyValue( &entities[ i ], "lip", str );
		}

		/* scale plat height */
		f = FloatForKey( &entities[ i ], "height" );
		if ( f ) {
			f *= scale[2];
			sprintf( str, "%f", f );
			SetKeyValue( &entities[ i ], "height", str );
		}

		// TODO maybe allow a definition file for entities to specify which values are scaled how?
	}

	/* scale models */
	for ( i = 0; i < numBSPModels; i++ )
	{
		bspModels[ i ].mins[0] *= scale[0];
		bspModels[ i ].mins[1] *= scale[1];
		bspModels[ i ].mins[2] *= scale[2];
		bspModels[ i ].maxs[0] *= scale[0];
		bspModels[ i ].maxs[1] *= scale[1];
		bspModels[ i ].maxs[2] *= scale[2];
	}

	/* scale nodes */
	for ( i = 0; i < numBSPNodes; i++ )
	{
		bspNodes[ i ].mins[0] *= scale[0];
		bspNodes[ i ].mins[1] *= scale[1];
		bspNodes[ i ].mins[2] *= scale[2];
		bspNodes[ i ].maxs[0] *= scale[0];
		bspNodes[ i ].maxs[1] *= scale[1];
		bspNodes[ i ].maxs[2] *= scale[2];
	}

	/* scale leafs */
	for ( i = 0; i < numBSPLeafs; i++ )
	{
		bspLeafs[ i ].mins[0] *= scale[0];
		bspLeafs[ i ].mins[1] *= scale[1];
		bspLeafs[ i ].mins[2] *= scale[2];
		bspLeafs[ i ].maxs[0] *= scale[0];
		bspLeafs[ i ].maxs[1] *= scale[1];
		bspLeafs[ i ].maxs[2] *= scale[2];
	}

	if ( texscale ) {
		Sys_Printf( "Using texture unlocking (and probably breaking texture alignment a lot)\n" );
		old_xyzst = safe_malloc( sizeof( *old_xyzst ) * numBSPDrawVerts * 5 );
		for ( i = 0; i < numBSPDrawVerts; i++ )
		{
			old_xyzst[5 * i + 0] = bspDrawVerts[i].xyz[0];
			old_xyzst[5 * i + 1] = bspDrawVerts[i].xyz[1];
			old_xyzst[5 * i + 2] = bspDrawVerts[i].xyz[2];
			old_xyzst[5 * i + 3] = bspDrawVerts[i].st[0];
			old_xyzst[5 * i + 4] = bspDrawVerts[i].st[1];
		}
	}

	/* scale drawverts */
	for ( i = 0; i < numBSPDrawVerts; i++ )
	{
		bspDrawVerts[i].xyz[0] *= scale[0];
		bspDrawVerts[i].xyz[1] *= scale[1];
		bspDrawVerts[i].xyz[2] *= scale[2];
		bspDrawVerts[i].normal[0] /= scale[0];
		bspDrawVerts[i].normal[1] /= scale[1];
		bspDrawVerts[i].normal[2] /= scale[2];
		VectorNormalize( bspDrawVerts[i].normal, bspDrawVerts[i].normal );
	}

	if ( texscale ) {
		for ( i = 0; i < numBSPDrawSurfaces; i++ )
		{
			switch ( bspDrawSurfaces[i].surfaceType )
			{
			case SURFACE_FACE:
			case SURFACE_META:
				if ( bspDrawSurfaces[i].numIndexes % 3 ) {
					Error( "Not a triangulation!" );
				}
				for ( j = bspDrawSurfaces[i].firstIndex; j < bspDrawSurfaces[i].firstIndex + bspDrawSurfaces[i].numIndexes; j += 3 )
				{
					int ia = bspDrawIndexes[j] + bspDrawSurfaces[i].firstVert, ib = bspDrawIndexes[j + 1] + bspDrawSurfaces[i].firstVert, ic = bspDrawIndexes[j + 2] + bspDrawSurfaces[i].firstVert;
					bspDrawVert_t *a = &bspDrawVerts[ia], *b = &bspDrawVerts[ib], *c = &bspDrawVerts[ic];
					float *oa = &old_xyzst[ia * 5], *ob = &old_xyzst[ib * 5], *oc = &old_xyzst[ic * 5];
					// extrapolate:
					//   a->xyz -> oa
					//   b->xyz -> ob
					//   c->xyz -> oc
					ExtrapolateTexcoords(
						&oa[0], &oa[3],
						&ob[0], &ob[3],
						&oc[0], &oc[3],
						a->xyz, a->st,
						b->xyz, b->st,
						c->xyz, c->st );
				}
				break;
			}
		}
	}

	/* scale planes */
	if ( uniform ) {
		for ( i = 0; i < numBSPPlanes; i++ )
		{
			bspPlanes[ i ].dist *= scale[0];
		}
	}
	else
	{
		for ( i = 0; i < numBSPPlanes; i++ )
		{
			bspPlanes[ i ].normal[0] /= scale[0];
			bspPlanes[ i ].normal[1] /= scale[1];
			bspPlanes[ i ].normal[2] /= scale[2];
			f = 1 / VectorLength( bspPlanes[i].normal );
			VectorScale( bspPlanes[i].normal, f, bspPlanes[i].normal );
			bspPlanes[ i ].dist *= f;
		}
	}

	/* scale gridsize */
	GetVectorForKey( &entities[ 0 ], "gridsize", vec );
	if ( ( vec[ 0 ] + vec[ 1 ] + vec[ 2 ] ) == 0.0f ) {
		VectorCopy( gridSize, vec );
	}
	vec[0] *= scale[0];
	vec[1] *= scale[1];
	vec[2] *= scale[2];
	sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
	SetKeyValue( &entities[ 0 ], "gridsize", str );

	/* inject command line parameters */
	InjectCommandLine( argv, 0, argc - 1 );

	/* write the bsp */
	UnparseEntities();
	StripExtension( source );
	DefaultExtension( source, "_s.bsp" );
	Sys_Printf( "Writing %s\n", source );
	WriteBSPFile( source );

	/* return to sender */
	return 0;
}
Exemple #21
0
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int Overlay_GetFromEntity( entity_t *pMapEnt )
{
	int iAccessorID = -1;

	// Allocate the new overlay.
	int iOverlay = g_aMapOverlays.AddToTail();
	mapoverlay_t *pMapOverlay = &g_aMapOverlays[iOverlay];

	// Get the overlay data.
	pMapOverlay->nId = g_aMapOverlays.Count() - 1;

	if ( ValueForKey( pMapEnt, "targetname" )[ 0 ] != '\0' )
	{
		// Overlay has a name, remember it's ID for accessing
		iAccessorID = pMapOverlay->nId;
	}

	pMapOverlay->flU[0] = FloatForKey( pMapEnt, "StartU" );
	pMapOverlay->flU[1] = FloatForKey( pMapEnt, "EndU" );
	pMapOverlay->flV[0] = FloatForKey( pMapEnt, "StartV" );
	pMapOverlay->flV[1] = FloatForKey( pMapEnt, "EndV" );

	pMapOverlay->flFadeDistMinSq = FloatForKey( pMapEnt, "fademindist" );
	if ( pMapOverlay->flFadeDistMinSq > 0 )
	{
		pMapOverlay->flFadeDistMinSq *= pMapOverlay->flFadeDistMinSq;
	}

	pMapOverlay->flFadeDistMaxSq = FloatForKey( pMapEnt, "fademaxdist" );
	if ( pMapOverlay->flFadeDistMaxSq > 0 )
	{
		pMapOverlay->flFadeDistMaxSq *= pMapOverlay->flFadeDistMaxSq;
	}

	GetVectorForKey( pMapEnt, "BasisOrigin", pMapOverlay->vecOrigin );

	pMapOverlay->m_nRenderOrder = IntForKey( pMapEnt, "RenderOrder" );
	if ( pMapOverlay->m_nRenderOrder < 0 || pMapOverlay->m_nRenderOrder >= OVERLAY_NUM_RENDER_ORDERS )
		Error( "Overlay (%s) at %f %f %f has invalid render order (%d).\n", ValueForKey( pMapEnt, "material" ), pMapOverlay->vecOrigin );

	GetVectorForKey( pMapEnt, "uv0", pMapOverlay->vecUVPoints[0] );
	GetVectorForKey( pMapEnt, "uv1", pMapOverlay->vecUVPoints[1] );
	GetVectorForKey( pMapEnt, "uv2", pMapOverlay->vecUVPoints[2] );
	GetVectorForKey( pMapEnt, "uv3", pMapOverlay->vecUVPoints[3] );

	GetVectorForKey( pMapEnt, "BasisU", pMapOverlay->vecBasis[0] );
	GetVectorForKey( pMapEnt, "BasisV", pMapOverlay->vecBasis[1] );
	GetVectorForKey( pMapEnt, "BasisNormal", pMapOverlay->vecBasis[2] );

	const char *pMaterialName = ValueForKey( pMapEnt, "material" );
	Assert( strlen( pMaterialName ) < OVERLAY_MAP_STRLEN );
	if ( strlen( pMaterialName ) >= OVERLAY_MAP_STRLEN )
	{
		Error( "Overlay Material Name (%s) too long! > OVERLAY_MAP_STRLEN (%d)", pMaterialName, OVERLAY_MAP_STRLEN );
		return -1;
	}
	strcpy( pMapOverlay->szMaterialName, pMaterialName );	

	// Convert the sidelist to side id(s).
	const char *pSideList = ValueForKey( pMapEnt, "sides" );
	char *pTmpList = ( char* )_alloca( strlen( pSideList ) + 1 );
	strcpy( pTmpList, pSideList );
	const char *pScan = strtok( pTmpList, " " );
	if ( !pScan )
		return iAccessorID;

	pMapOverlay->aSideList.Purge();
	pMapOverlay->aFaceList.Purge();

	do
	{
		int nSideId;
		if ( sscanf( pScan, "%d", &nSideId ) == 1 )
		{
			pMapOverlay->aSideList.AddToTail( nSideId );
		}
	} while ( ( pScan = strtok( NULL, " " ) ) );

	return iAccessorID;
}
Exemple #22
0
/*
=============
FinalLightFace

Add the indirect lighting on top of the direct
lighting and save into final map format
=============
*/
void FinalLightFace( int iThread, int facenum )
{
	dface_t	        *f;
	int		        i, j, k;
	facelight_t	    *fl;
	float		    minlight;
	int			    lightstyles;
	LightingValue_t lb[NUM_BUMP_VECTS + 1], v[NUM_BUMP_VECTS + 1];
	unsigned char   *pdata[NUM_BUMP_VECTS + 1];
	int				bumpSample;
	radial_t	    *rad = NULL;
	radial_t	    *prad = NULL;

   	f = &g_pFaces[facenum];

    // test for non-lit texture
    if ( texinfo[f->texinfo].flags & TEX_SPECIAL)
        return;		

	fl = &facelight[facenum];


	for (lightstyles=0; lightstyles < MAXLIGHTMAPS; lightstyles++ )
	{
		if ( f->styles[lightstyles] == 255 )
			break;
	}
	if ( !lightstyles )
		return;

	
	//
	// sample the triangulation
	//
	minlight = FloatForKey (face_entity[facenum], "_minlight") * 128;

	bool needsBumpmap = ( texinfo[f->texinfo].flags & SURF_BUMPLIGHT ) ? true : false;
	int bumpSampleCount = needsBumpmap ? NUM_BUMP_VECTS + 1 : 1;

	bool bDisp = ( f->dispinfo != -1 );

//#define RANDOM_COLOR

#ifdef RANDOM_COLOR
	unsigned char randomColor[3];
	GetRandomColor( randomColor );
#endif
	

	// NOTE: I'm using these RB trees to sort all the illumination values
	// to compute median colors. Turns out that this is a somewhat better
	// method that using the average; usually if there are surfaces
	// with a large light intensity variation, the extremely bright regions
	// have a very small area and tend to influence the average too much.
	CUtlRBTree< float, int >	m_Red( 0, 256, FloatLess );
	CUtlRBTree< float, int >	m_Green( 0, 256, FloatLess );
	CUtlRBTree< float, int >	m_Blue( 0, 256, FloatLess );

	for (k=0 ; k < lightstyles; k++ )
	{
		m_Red.RemoveAll();
		m_Green.RemoveAll();
		m_Blue.RemoveAll();

		if (!do_fast)
		{
			if( !bDisp )
			{
				rad = BuildLuxelRadial( facenum, k );
			}
			else
			{
				rad = StaticDispMgr()->BuildLuxelRadial( facenum, k, needsBumpmap );
			}
		}

		if (numbounce > 0 && k == 0)
		{
			// currently only radiosity light non-displacement surfaces!
			if( !bDisp )
			{
				prad = BuildPatchRadial( facenum );
			}
			else
			{
				prad = StaticDispMgr()->BuildPatchRadial( facenum, needsBumpmap );
			}
		}

		// pack the nonbump texture and the three bump texture for the given 
		// lightstyle right next to each other.
		// NOTE: Even though it's building positions for all bump-mapped data,
		// it isn't going to use those positions (see loop over bumpSample below)
		// The file offset is correctly computed to only store space for 1 set
		// of light data if we don't have bumped lighting.
		for( bumpSample = 0; bumpSample < bumpSampleCount; ++bumpSample )
		{
			pdata[bumpSample] = &(*pdlightdata)[f->lightofs + (k * bumpSampleCount + bumpSample) * fl->numluxels*4]; 
		}

		// Compute the average luxel color, but not for the bump samples
		Vector avg( 0.0f, 0.0f, 0.0f );
		int avgCount = 0;

		for (j=0 ; j<fl->numluxels; j++)
		{
			// garymct - direct lighting
			bool baseSampleOk = true;

			if (!do_fast)
			{
				if( !bDisp )
				{
					baseSampleOk = SampleRadial( rad, fl->luxel[j], lb, bumpSampleCount );
				}
				else
				{
					baseSampleOk = StaticDispMgr()->SampleRadial( facenum, rad, fl->luxel[j], j, lb, bumpSampleCount, false );
				}
			}
			else
			{
				for ( int iBump = 0 ; iBump < bumpSampleCount; iBump++ )
				{
					lb[iBump] = fl->light[0][iBump][j];
				}
			}

			if (prad)
			{
				// garymct - bounced light
				// v is indirect light that is received on the luxel.
				if( !bDisp )
				{
					SampleRadial( prad, fl->luxel[j], v, bumpSampleCount );
				}
				else
				{
					StaticDispMgr()->SampleRadial( facenum, prad, fl->luxel[j], j, v, bumpSampleCount, true );
				}

				for( bumpSample = 0; bumpSample < bumpSampleCount; ++bumpSample )
				{
					lb[bumpSample].AddLight( v[bumpSample] );
				}
			}

			if ( bDisp && g_bDumpPatches )
			{
				for( bumpSample = 0; bumpSample < bumpSampleCount; ++bumpSample )
				{
					DumpDispLuxels( facenum, lb[bumpSample].m_vecLighting, j, bumpSample );
				}
			}

			if (fl->numsamples == 0)
			{
				for( i = 0; i < bumpSampleCount; i++ )
				{
					lb[i].Init( 255, 0, 0 );
				}
				baseSampleOk = false;
			}

			int bumpSample;
			for( bumpSample = 0; bumpSample < bumpSampleCount; bumpSample++ )
			{
				// clip from the bottom first
				// garymct: minlight is a per entity minimum light value?
				for( i=0; i<3; i++ )
				{
					lb[bumpSample].m_vecLighting[i] = max( lb[bumpSample].m_vecLighting[i], minlight );
				}
				
				// Do the average light computation, I'm assuming (perhaps incorrectly?)
				// that all luxels in a particular lightmap have the same area here. 
				// Also, don't bother doing averages for the bump samples. Doing it here 
				// because of the minlight clamp above + the random color testy thingy. 
				// Also have to do it before Vec3toColorRGBExp32 because it 
				// destructively modifies lb[bumpSample] (Feh!)
				if ((bumpSample == 0) && baseSampleOk)
				{
					++avgCount;

					ApplyMacroTextures( facenum, fl->luxel[j], lb[0].m_vecLighting );

					// For median computation
					m_Red.Insert( lb[bumpSample].m_vecLighting[0] );
					m_Green.Insert( lb[bumpSample].m_vecLighting[1] );
					m_Blue.Insert( lb[bumpSample].m_vecLighting[2] );
				}

#ifdef RANDOM_COLOR
				pdata[bumpSample][0] = randomColor[0] / ( bumpSample + 1 );
				pdata[bumpSample][1] = randomColor[1] / ( bumpSample + 1 );
				pdata[bumpSample][2] = randomColor[2] / ( bumpSample + 1 );
				pdata[bumpSample][3] = 0;
#else
				// convert to a 4 byte r,g,b,signed exponent format
				VectorToColorRGBExp32( Vector( lb[bumpSample].m_vecLighting.x, lb[bumpSample].m_vecLighting.y,
											   lb[bumpSample].m_vecLighting.z ), *( ColorRGBExp32 *)pdata[bumpSample] );
#endif

				pdata[bumpSample] += 4;
			}
		}
		FreeRadial( rad );
		if (prad)
		{
			FreeRadial( prad );
			prad = NULL;
		}

		// Compute the median color for this lightstyle
		// Remember, the data goes *before* the specified light_ofs, in *reverse order*
		ColorRGBExp32 *pAvgColor = dface_AvgLightColor( f, k );
		if (avgCount == 0)
		{
			Vector median( 0, 0, 0 );
			VectorToColorRGBExp32( median, *pAvgColor );
		}
		else
		{
			unsigned int r, g, b;
			r = m_Red.FirstInorder();
			g = m_Green.FirstInorder();
			b = m_Blue.FirstInorder();
			avgCount >>= 1;
			while (avgCount > 0)
			{
				r = m_Red.NextInorder(r);
				g = m_Green.NextInorder(g);
				b = m_Blue.NextInorder(b);
				--avgCount;
			}

			Vector median( m_Red[r], m_Green[g], m_Blue[b] );
			VectorToColorRGBExp32( median, *pAvgColor );
		}
	}
}
Exemple #23
0
qboolean FloodEntities( tree_t *tree )
{
    int			i, s;
    vec3_t		origin, offset, scale, angles;
    qboolean	r, inside, tripped, skybox;
    node_t		*headnode;
    entity_t	*e;
    const char	*value;


    headnode = tree->headnode;
    Sys_FPrintf( SYS_VRB,"--- FloodEntities ---\n" );
    inside = qfalse;
    tree->outside_node.occupied = 0;

    tripped = qfalse;
    c_floodedleafs = 0;
    for( i = 1; i < numEntities; i++ )
    {
        /* get entity */
        e = &entities[ i ];

        /* get origin */
        GetVectorForKey( e, "origin", origin );
        if( VectorCompare( origin, vec3_origin ) )
            continue;

        /* handle skybox entities */
        value = ValueForKey( e, "classname" );
        if( !Q_stricmp( value, "_skybox" ) )
        {
            skybox = qtrue;
            skyboxPresent = qtrue;

            /* invert origin */
            VectorScale( origin, -1.0f, offset );

            /* get scale */
            VectorSet( scale, 64.0f, 64.0f, 64.0f );
            value = ValueForKey( e, "_scale" );
            if( value[ 0 ] != '\0' )
            {
                s = sscanf( value, "%f %f %f", &scale[ 0 ], &scale[ 1 ], &scale[ 2 ] );
                if( s == 1 )
                {
                    scale[ 1 ] = scale[ 0 ];
                    scale[ 2 ] = scale[ 0 ];
                }
            }

            /* get "angle" (yaw) or "angles" (pitch yaw roll) */
            VectorClear( angles );
            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( skyboxTransform );
            m4x4_pivoted_transform_by_vec3( skyboxTransform, offset, angles, eXYZ, scale, origin );
        }
        else
            skybox = qfalse;

        /* nudge off floor */
        origin[ 2 ] += 1;

        /* debugging code */
        //%	if( i == 1 )
        //%		origin[ 2 ] += 4096;

        /* find leaf */
        r = PlaceOccupant( headnode, origin, e, skybox );
        if( r )
            inside = qtrue;
        if( (!r || tree->outside_node.occupied) && !tripped )
        {
            xml_Select( "Entity leaked", e->mapEntityNum, 0, qfalse );
            tripped = qtrue;
        }
    }

    Sys_FPrintf( SYS_VRB, "%9d flooded leafs\n", c_floodedleafs );

    if( !inside )
        Sys_FPrintf( SYS_VRB, "no entities in open -- no filling\n" );
    else if( tree->outside_node.occupied )
        Sys_FPrintf( SYS_VRB, "entity reached from outside -- no filling\n" );

    return (qboolean) (inside && !tree->outside_node.occupied);
}
Exemple #24
0
/*
==================
ParseLightEntities
==================
*/
void ParseLightEntities( void )
{
	int	i, j;
	entity_t *ent;
	char *value, *targetname, *style;
	directlight_t *l;
	double vec[4], color2[3];
	qboolean isLight;

	num_directlights = 0;
	for( i = 0, ent = entities; i < num_entities; i++, ent++ ) {
		value = ValueForKey( ent, "classname" );

		if( strncmp (value, "light", 5) )
			continue;

		if( !strcmp (value, "light") )
			isLight = true;
		else
			isLight = false;

		if( num_directlights == MAP_DIRECTLIGHTS )
			Error( "numdirectlights == MAP_DIRECTLIGHTS" );

		l = &directlights[num_directlights++];
		memset( l, 0, sizeof (*l) );

		color2[0] = color2[1] = color2[2] = 1.0f;
		l->color[0] = l->color[1] = l->color[2] = 1.0f;
		GetVectorForKey( ent, "origin", l->origin );

		l->type = defaultlighttype;
		if (!overridelighttypes && (j = FloatForKey( ent, "delay" )))
		{
			if (j < 0 || j >= LIGHTTYPE_TOTAL)
				Error("error in light at %.0f %.0f %.0f:\nunknown light type \"delay\" \"%s\"\n", l->origin[0], l->origin[1], l->origin[2], ValueForKey( ent, "delay" ));
			l->type = j;
		}

		l->style = FloatForKey( ent, "style" );
		if( (unsigned)l->style > 254 )
			Error( "error in light at %.0f %.0f %.0f:\nBad light style %i (must be 0-254)", l->origin[0], l->origin[1], l->origin[2], l->style );

		l->angle = FloatForKey( ent, "angle" );

		value = ValueForKey( ent, "color" );
		if( !value[0] )
			value = ValueForKey( ent, "_color" );
		if( value[0] )
			if( sscanf (value, "%lf %lf %lf", &color2[0], &color2[1], &color2[2]) != 3 )
				Error( "error in light at %.0f %.0f %.0f:\ncolor must be given 3 values", l->origin[0], l->origin[1], l->origin[2] );

		value = ValueForKey( ent, "light" );
		if( !value[0] )
			value = ValueForKey( ent, "_light" );

		if( value[0] ) {
			j = sscanf ( value, "%lf %lf %lf %lf", &vec[0], &vec[1], &vec[2], &vec[3] );

			switch( j ) {
				case 4:// HalfLife light
					l->color[0] = vec[0];
					l->color[1] = vec[1];
					l->color[2] = vec[2];
					l->radius = vec[3];
					break;
				case 1: // quake light
					l->radius = vec[0];
					l->color[0] = vec[0];
					l->color[1] = vec[0];
					l->color[2] = vec[0];
					break;
				default:
					Error( "error in light at %.0f %.0f %.0f:\n_light (or light) key must be 1 (Quake) or 4 (HalfLife) numbers, \"%s\" is not valid\n", l->origin[0], l->origin[1], l->origin[2], value );
			}
		}

		if( !l->radius )
		{
			l->radius = DEFAULTLIGHTLEVEL;
			l->color[0] = DEFAULTLIGHTLEVEL;
			l->color[1] = DEFAULTLIGHTLEVEL;
			l->color[2] = DEFAULTLIGHTLEVEL;
		}

		// for some reason this * 0.5 is needed to match quake light
		VectorScale(l->color, 0.5, l->color);

		// fix tyrlite darklight radius value (but color remains negative)
		l->radius = fabs(l->radius);

		// apply scaling to radius
		vec[0] = FloatForKey( ent, "wait" );
		if( !vec[0] )
			vec[0] = 1;
		if (vec[0] != 1)
		{
			if (vec[0] <= 0.0001)
			{
				l->type = LIGHTTYPE_NONE;
				l->radius = BOGUS_RANGE;
				VectorScale(l->color, 0.25, l->color);
			}
			else
				l->radius /= vec[0];
		}

		l->radius *= globallightradiusscale;
		l->clampradius = l->radius;

		switch (l->type)
		{
		case LIGHTTYPE_RECIPX:
			l->clampradius = BOGUS_RANGE;
			break;
		case LIGHTTYPE_RECIPXX:
			l->clampradius = BOGUS_RANGE;
			break;
		default:
			break;
		}

		l->color[0] *= color2[0] * globallightscale;
		l->color[1] *= color2[1] * globallightscale;
		l->color[2] *= color2[2] * globallightscale;

		// this confines the light to a specified radius (typically used on RECIPX and RECIPXX)
		vec[0] = FloatForKey( ent, "_lightradius" );
		if (vec[0])
			l->clampradius = vec[0];

		if( isLight ) {
			value = ValueForKey( ent, "targetname" );

			if( value[0] && !l->style ) {
				char s[16];

				l->style = LightStyleForTargetname( value );

				memset( s, 0, sizeof(s) );
				sprintf( s, "%i", l->style );
				SetKeyValue( ent, "style", s );
			}
		}

		value = ValueForKey( ent, "target" );
		if( !value[0] )
		{
			if (l->type == LIGHTTYPE_SUN)
				Error("error in light at %.0f %.0f %.0f:\nLIGHTTYPE_SUN (delay 4) requires a target for the sun direction\n", l->origin[0], l->origin[1], l->origin[2]);
			continue;
		}

		for( j = 0; j < num_entities; j++ ) {
			if( i == j )
				continue;

			targetname = ValueForKey( &entities[j], "targetname" );
			if( !strcmp (targetname, value) ) {
				vec3_t origin;

				GetVectorForKey( &entities[j], "origin", origin );

				// set up spotlight values for lighting code to use
				VectorSubtract( origin, l->origin, l->spotdir );
				VectorNormalize( l->spotdir );

				if( !l->angle )
					l->spotcone = -cos( 20 * Q_PI / 180 );
				else
					l->spotcone = -cos( l->angle / 2 * Q_PI / 180 );
				break;
			}
		}

		if( j == num_entities )	{
			printf( "warning in light at %.0f %.0f %.0f:\nunmatched spotlight target\n", l->origin[0], l->origin[1], l->origin[2]);
			if (l->type == LIGHTTYPE_SUN)
				Error("error in light at %.0f %.0f %.0f:\nLIGHTTYPE_SUN (delay 4) requires a target for the sun direction\n", l->origin[0], l->origin[1], l->origin[2]);
			continue;
		}

		// set the style on the source ent for switchable lights
		style = ValueForKey( &entities[j], "style" );
		if( style[0] && atof (style) ) {
			char s[16];

			l->style = atof( style );
			if( (unsigned)l->style > 254 )
				Error( "error in light at %.0f %.0f %.0f:\nBad target light style %i (must be 0-254)", l->origin[0], l->origin[1], l->origin[2], l->style );

			memset( s, 0, sizeof(s) );
			sprintf( s, "%i", l->style );
			SetKeyValue( ent, "style", s );
		}
	}
}
Exemple #25
0
int ScaleBSPMain( int argc, char **argv )
{
	int			i;
	float		f, scale;
	vec3_t		vec;
	char		str[ 1024 ];
	
	
	/* arg checking */
	if( argc < 2 )
	{
		Sys_Printf( "Usage: q3map -scale <value> [-v] <mapname>\n" );
		return 0;
	}
	
	/* get scale */
	scale = atof( argv[ argc - 2 ] );
	if( scale == 0.0f )
	{
		Sys_Printf( "Usage: q3map -scale <value> [-v] <mapname>\n" );
		Sys_Printf( "Non-zero scale value required.\n" );
		return 0;
	}
	
	/* do some path mangling */
	strcpy( source, ExpandArg( argv[ argc - 1 ] ) );
	StripExtension( source );
	DefaultExtension( source, ".bsp" );
	
	/* load the bsp */
	Sys_Printf( "Loading %s\n", source );
	LoadBSPFile( source );
	ParseEntities();
	
	/* note it */
	Sys_Printf( "--- ScaleBSP ---\n" );
	Sys_FPrintf( SYS_VRB, "%9d entities\n", numEntities );
	
	/* scale entity keys */
	for( i = 0; i < numBSPEntities && i < numEntities; i++ )
	{
		/* scale origin */
		GetVectorForKey( &entities[ i ], "origin", vec );
		if( (vec[ 0 ] + vec[ 1 ] + vec[ 2 ]) )
		{
			VectorScale( vec, scale, vec );
			sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
			SetKeyValue( &entities[ i ], "origin", str );
		}
		
		/* scale door lip */
		f = FloatForKey( &entities[ i ], "lip" );
		if( f )
		{
			f *= scale;
			sprintf( str, "%f", f );
			SetKeyValue( &entities[ i ], "lip", str );
		}
	}
	
	/* scale models */
	for( i = 0; i < numBSPModels; i++ )
	{
		VectorScale( bspModels[ i ].mins, scale, bspModels[ i ].mins );
		VectorScale( bspModels[ i ].maxs, scale, bspModels[ i ].maxs );
	}
	
	/* scale nodes */
	for( i = 0; i < numBSPNodes; i++ )
	{
		VectorScale( bspNodes[ i ].mins, scale, bspNodes[ i ].mins );
		VectorScale( bspNodes[ i ].maxs, scale, bspNodes[ i ].maxs );
	}
	
	/* scale leafs */
	for( i = 0; i < numBSPLeafs; i++ )
	{
		VectorScale( bspLeafs[ i ].mins, scale, bspLeafs[ i ].mins );
		VectorScale( bspLeafs[ i ].maxs, scale, bspLeafs[ i ].maxs );
	}
	
	/* scale drawverts */
	for( i = 0; i < numBSPDrawVerts; i++ )
		VectorScale( bspDrawVerts[ i ].xyz, scale, bspDrawVerts[ i ].xyz );
	
	/* scale planes */
	for( i = 0; i < numBSPPlanes; i++ )
		bspPlanes[ i ].dist *= scale;
	
	/* scale gridsize */
	GetVectorForKey( &entities[ 0 ], "gridsize", vec );
	if( (vec[ 0 ] + vec[ 1 ] + vec[ 2 ]) == 0.0f )
		VectorCopy( gridSize, vec );
	VectorScale( vec, scale, vec );
	sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
	SetKeyValue( &entities[ 0 ], "gridsize", str );
	
	/* write the bsp */
	UnparseEntities();
	StripExtension( source );
	DefaultExtension( source, "_s.bsp" );
	Sys_Printf( "Writing %s\n", source );
	WriteBSPFile( source );
	
	/* return to sender */
	return 0;
}
/*
================
Entity_Parse

If onlypairs is set, the classname info will not
be looked up, and the entity will not be added
to the global list.  Used for parsing the project.
================
*/
entity_t	*Entity_Parse (qboolean onlypairs, brush_t* pList)
{
	entity_t	*ent;
	eclass_t	*e;
	brush_t		*b;
	vec3_t		mins, maxs;
	epair_t		*ep;
	qboolean	has_brushes;
#ifdef SOF
	float		scale;
#endif

	if (!GetToken (true))
		return NULL;

	if (strcmp (token, "{") )
		Error ("ParseEntity: { not found");
	
	ent = (entity_t*)qmalloc (sizeof(*ent));
	ent->brushes.onext = ent->brushes.oprev = &ent->brushes;

	do
	{
		if (!GetToken (true))
    {
			Warning ("ParseEntity: EOF without closing brace");
      return NULL;
    }
		if (!strcmp (token, "}") )
			break;
		if (!strcmp (token, "{") )
		{
			b = Brush_Parse ();
      if (b != NULL)
      {
			  b->owner = ent;

			  // add to the end of the entity chain
			  b->onext = &ent->brushes;
			  b->oprev = ent->brushes.oprev;
			  ent->brushes.oprev->onext = b;
			  ent->brushes.oprev = b;
      }
      else
      {
        break;
      }
    
		}
		else
		{
			ep = ParseEpair ();
			{
				// update: the original code here may have been simple, but it meant that every map load/save
				//	the key/value pair fields were reversed in the save file, which messes up SourceSafe when it
				//	tries to delta the two versions during check-in... -slc
#if 0
				ep->next = ent->epairs;
				ent->epairs = ep;
#else
				// join this onto the END of the chain instead...
				//
				if (ent->epairs == NULL)	// special case for if there isn't a chain yet... :-)
				{
					ep->next = ent->epairs;
					ent->epairs = ep;
				}
				else
				{						
					for (epair_t* ep2 = ent->epairs ; ep2 ; ep2=ep2->next)
					{
						if (ep2->next == NULL)
						{
							// found the end, so...
							//
							ep2->next = ep;							
							ep->next = NULL;
							break;
						}
					}
				}
#endif
			}
		}
	} while (1);

	if (onlypairs)
		return ent;

	if (ent->brushes.onext == &ent->brushes)
		has_brushes = false;
	else
		has_brushes = true;

	GetVectorForKey (ent, "origin", ent->origin);

	e = Eclass_ForName (ValueForKey (ent, "classname"), has_brushes);
	ent->eclass = e;
	if (e->fixedsize)
	{	// fixed size entity
		if (ent->brushes.onext != &ent->brushes)
		{
			printf ("Warning: Fixed size entity with brushes\n");
#if 0
			while (ent->brushes.onext != &ent->brushes)
			{	// FIXME: this will free the entity and crash!
				Brush_Free (b);
			}
#endif
      ent->brushes.next = ent->brushes.prev = &ent->brushes;
		}

    // create a custom brush
		VectorAdd (e->mins, ent->origin, mins);
		VectorAdd (e->maxs, ent->origin, maxs);

    float a = 0;
    if (strnicmp(e->name, "misc_model",10) == 0)
    {
      char* p = ValueForKey(ent, "model");
      if (p != NULL && strlen(p) > 0)
      {
        vec3_t vMin, vMax;
        a = FloatForKey (ent, "angle");
		gEntityToSetBoundsOf = ent;
        if (GetCachedModel(ent, p, vMin, vMax))
        {
	      // create a custom brush
	      VectorAdd (ent->md3Class->mins, ent->origin, mins);
	      VectorAdd (ent->md3Class->maxs, ent->origin, maxs);
        }
      }
    }
#ifdef SOF
	if (strnicmp(e->name, "misc_",			5) == 0 ||
		strnicmp(e->name, "light_",			6) == 0 ||
		strnicmp(e->name, "m_",				2) == 0 ||
		strnicmp(e->name, "item_weapon_",	12)== 0 ||
		strnicmp(e->name, "item_ammo_",		10)== 0
		)
		a = FloatForKey (ent, "angle");
#endif		
		b = Brush_Create (mins, maxs, &e->texdef);
///////
		b->owner = ent;

		b->onext = ent->brushes.onext;
		b->oprev = &ent->brushes;
		ent->brushes.onext->oprev = b;
		ent->brushes.onext = b;
///////
		Brush_Build(b);

#ifdef SOF
		scale = FloatForKey (ent, "scale");
		if (scale)
		{
		  Brush_Scale2(e, b, scale, ent->origin,false);
		}
#endif

//		if (a)
//		{
//			vec3_t vAngle;
//			vAngle[0] = vAngle[1] = 0;
//			vAngle[2] = a;
//			Brush_Rotate(b, vAngle, ent->origin, false);
//		}

/*
		b->owner = ent;

		b->onext = ent->brushes.onext;
		b->oprev = &ent->brushes;
		ent->brushes.onext->oprev = b;
		ent->brushes.onext = b;
*/
		// do this AFTER doing the brush stuff just above, so don't join to the other "if (a)"...
		//
		if (a)
		{
			// pick any old value to rotate away to, then back from, to avoid 0/360 weirdness on key-compares
			//
			SetKeyValue(ent, "angle", "0",			false);	// false = no tracking, ie just set the angle and nothing else			
			SetKeyValue(ent, "angle", va("%g",a),	true);	// true = do tracking, ie actually do the brush rotate
		}
	}
	else
	{	// brush entity
		if (ent->brushes.next == &ent->brushes)
			printf ("Warning: Brush entity with no brushes\n");
	}

	// add all the brushes to the main list
  if (pList)
  {
	  for (b=ent->brushes.onext ; b != &ent->brushes ; b=b->onext)
    {
		  b->next = pList->next;
		  pList->next->prev = b;
		  b->prev = pList;
		  pList->next = b;
    }
  }

	return ent;
}
Exemple #27
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 #28
0
void EmitStaticProps()
{
	CreateInterfaceFn physicsFactory = GetPhysicsFactory();
	if ( physicsFactory )
	{
		s_pPhysCollision = (IPhysicsCollision *)physicsFactory( VPHYSICS_COLLISION_INTERFACE_VERSION, NULL );
		if( !s_pPhysCollision )
			return;
	}

	// Generate a list of lighting origins, and strip them out
	int i;
	for ( i = 0; i < num_entities; ++i)
	{
		char* pEntity = ValueForKey(&entities[i], "classname");
		if (!Q_strcmp(pEntity, "info_lighting"))
		{
			s_LightingInfo.AddToTail(i);
		}
	}

	// Emit specifically specified static props
	for ( i = 0; i < num_entities; ++i)
	{
		char* pEntity = ValueForKey(&entities[i], "classname");
		if (!strcmp(pEntity, "static_prop") || !strcmp(pEntity, "prop_static"))
		{
			StaticPropBuild_t build;

			GetVectorForKey( &entities[i], "origin", build.m_Origin );
			GetAnglesForKey( &entities[i], "angles", build.m_Angles );
			build.m_pModelName = ValueForKey( &entities[i], "model" );
			build.m_Solid = IntForKey( &entities[i], "solid" );
			build.m_Skin = IntForKey( &entities[i], "skin" );
			build.m_FadeMaxDist = FloatForKey( &entities[i], "fademaxdist" );
			build.m_Flags = 0;//IntForKey( &entities[i], "spawnflags" ) & STATIC_PROP_WC_MASK;
			if (IntForKey( &entities[i], "disableshadows" ) == 1)
			{
				build.m_Flags |= STATIC_PROP_NO_SHADOW;
			}
			if (IntForKey( &entities[i], "disablevertexlighting" ) == 1)
			{
				build.m_Flags |= STATIC_PROP_NO_PER_VERTEX_LIGHTING;
			}
			if (IntForKey( &entities[i], "disableselfshadowing" ) == 1)
			{
				build.m_Flags |= STATIC_PROP_NO_SELF_SHADOWING;
			}

			if (IntForKey( &entities[i], "screenspacefade" ) == 1)
			{
				build.m_Flags |= STATIC_PROP_SCREEN_SPACE_FADE;
			}

			const char *pKey = ValueForKey( &entities[i], "fadescale" );
			if ( pKey && pKey[0] )
			{
				build.m_flForcedFadeScale = FloatForKey( &entities[i], "fadescale" );
			}
			else
			{
				build.m_flForcedFadeScale = 1;
			}
			build.m_FadesOut = (build.m_FadeMaxDist > 0);
			build.m_pLightingOrigin = ValueForKey( &entities[i], "lightingorigin" );
			if (build.m_FadesOut)
			{			  
				build.m_FadeMinDist = FloatForKey( &entities[i], "fademindist" );
				if (build.m_FadeMinDist < 0)
				{
					build.m_FadeMinDist = build.m_FadeMaxDist; 
				}
			}
			else
			{
				build.m_FadeMinDist = 0;
			}

			AddStaticPropToLump( build );

			// strip this ent from the .bsp file
			entities[i].epairs = 0;
		}
	}

	// Strip out lighting origins; has to be done here because they are used when
	// static props are made
	for ( i = s_LightingInfo.Count(); --i >= 0; )
	{
		// strip this ent from the .bsp file
		entities[s_LightingInfo[i]].epairs = 0;
	}


	SetLumpData( );
}