Entities that are expensive to generate, like skeletal models, can be deferred until their bounds are found to be in view, in the frustum of a shadowing light that is in view, or contacted by a trace / overlay test. This is also used to do visual cueing on items in the view The renderView may be NULL if the callback is being issued for a non-view related source. The callback function should clear renderEntity->callback if it doesn't want to be called again next time the entity is referenced (ie, if the callback has now made the entity valid until the next updateEntity)
예제 #1
0
		public override idBounds GetBounds(RenderEntityComponent renderEntity = null)
		{
			if(this.Disposed == true)
			{
				throw new ObjectDisposedException(this.GetType().Name);
			}

			return _particleSystem.Bounds;
		}
예제 #2
0
		private int	_pvsAreaCount;			// number of renderer areas the entity covers
		#endregion

		#region Constructor
		public idEntity()
		{
			_entityIndex = idR.MaxGameEntities - 1;
			_entityDefIndex = -1;

			_className = "unknown";

			_renderEntity = new RenderEntityComponent();
			_defaultPhysicsObject = new idPhysics_Static();

			idConsole.Warning("TODO: idEntity");
			/*			
			snapshotNode.SetOwner(this);
			snapshotSequence = -1;*/
	
			/*
			bindJoint = INVALID_JOINT;*/
			_bindBody = -1;

			/*memset(PVSAreas, 0, sizeof(PVSAreas));*/
			_pvsAreaCount = -1;

			_flags.NeverDormant = true; // most entities never go dormant

			/* mpGUIState = -1;*/
		}
예제 #3
0
		public virtual void Spawn()
		{
			if(this.Disposed == true)
			{
				throw new ObjectDisposedException(this.GetType().Name);
			}

			idConsole.WriteLine("TODO: idEntity.Spawn");
			/*int					i;
			const char			*temp;
			idVec3				origin;
			idMat3				axis;
			const idKeyValue	*networkSync;
			const char			*classname;
			const char			*scriptObjectName;*/

			idR.Game.RegisterEntity(this);

			_className = _spawnArgs.GetString("classname", null);

			idDeclEntity def = idR.Game.FindEntityDef(_className, false);

			if(def != null)
			{
				_entityDefIndex = def.Index;
			}

			/*
			TODO
			FixupLocalizedStrings();
			*/

			// parse static models the same way the editor display does
			_renderEntity = idR.GameEdit.ParseSpawnArgsToRenderEntity(_spawnArgs);
			_renderEntity.EntityIndex = this.Index;

			// TODO
			/*
					// go dormant within 5 frames so that when the map starts most monsters are dormant
					dormantStart = gameLocal.time - DELAY_DORMANT_TIME + gameLocal.msec * 5;*/

			/*

			// do the audio parsing the same way dmap and the editor do
			gameEdit->ParseSpawnArgsToRefSound( &spawnArgs, &refSound );

			// only play SCHANNEL_PRIVATE when sndworld->PlaceListener() is called with this listenerId
			// don't spatialize sounds from the same entity
			refSound.listenerId = entityNumber + 1;

			cameraTarget = NULL;
			temp = spawnArgs.GetString( "cameraTarget" );
			if ( temp && temp[0] ) {
				// update the camera taget
				PostEventMS( &EV_UpdateCameraTarget, 0 );
			}

			for ( i = 0; i < MAX_RENDERENTITY_GUI; i++ ) {
				UpdateGuiParms( renderEntity.gui[ i ], &spawnArgs );
			}*/

			_flags.SolidForTeam = _spawnArgs.GetBool("solidForTeam", false);
			_flags.NeverDormant = _spawnArgs.GetBool("neverDormant", false);
			_flags.Hidden = _spawnArgs.GetBool("hide", false);

			if(_flags.Hidden == true)
			{
				// make sure we're hidden, since a spawn function might not set it up right
				idConsole.Warning("TODO: PostEventMS( &EV_Hide, 0 );");
			}
			/*cinematic = spawnArgs.GetBool( "cinematic", "0" );

			networkSync = spawnArgs.FindKey( "networkSync" );
			if ( networkSync ) {
				fl.networkSync = ( atoi( networkSync->GetValue() ) != 0 );
			}
		*/

			// every object will have a unique name
			this.Name = _spawnArgs.GetString("name", string.Format("{0}_{1}_{2}", this.ClassName, _spawnArgs.GetString("classname"), this.Index));

			// if we have targets, wait until all entities are spawned to get them
			// TODO
			/*if ( spawnArgs.MatchPrefix( "target" ) || spawnArgs.MatchPrefix( "guiTarget" ) ) {
				if ( gameLocal.GameState() == GAMESTATE_STARTUP ) {
					PostEventMS( &EV_FindTargets, 0 );
				} else {
					// not during spawn, so it's ok to get the targets
					FindTargets();
				}
			}*/

			_health = _spawnArgs.GetInteger("health");

			Vector3 origin = _renderEntity.Origin;
			Matrix axis = _renderEntity.Axis;
			
			InitDefaultPhysics(origin, axis);

			this.Origin = origin;
			this.Axis = axis;

			string temp = _spawnArgs.GetString("model");

			if(temp != string.Empty)
			{
				this.SetModel(temp);
			}

			if(_spawnArgs.GetString("bind", string.Empty) == string.Empty)
			{
				idConsole.Warning("TODO: PostEventMS( &EV_SpawnBind, 0 );");
			}

			// auto-start a sound on the entity
			// TODO
			/*if ( refSound.shader && !refSound.waitfortrigger ) {
				StartSoundShader( refSound.shader, SND_CHANNEL_ANY, 0, false, NULL );
			}*/

			// setup script object
			string scriptObjectName = _spawnArgs.GetString("scriptobject", string.Empty);

			if((this.ShouldConstructScriptObjectAtSpawn == true) && (scriptObjectName != string.Empty))
			{
				idConsole.Warning("TODO: script object");
				/*if ( !scriptObject.SetType( scriptObjectName ) ) {
					gameLocal.Error( "Script object '%s' not found on entity '%s'.", scriptObjectName, name.c_str() );
				}

				ConstructScriptObject();*/
			}
		}
예제 #4
0
		public idRenderEntity()
		{
			_parameters = new RenderEntityComponent();
			_modelMatrix = Matrix.Identity;
			_referenceBounds = idBounds.Zero;
		}
예제 #5
0
		/// <summary>
		/// 
		/// </summary>
		/// <remarks>
		/// Dynamic models should return a fast, conservative approximation.
		/// Static models should usually return the exact value.
		/// </remarks>
		/// <param name="renderEntity"></param>
		/// <returns></returns>
		public abstract idBounds GetBounds(RenderEntityComponent renderEntity = null);
예제 #6
0
		private void EmitSurface(GuiModelSurface surface, Matrix modelMatrix, Matrix modelViewMatrix, bool depthHack)
		{
			if(surface.VertexCount == 0)
			{
				// nothing in the surface
				return;
			}

			// copy verts and indexes
			Surface tri = new Surface();
			tri.Indexes = new int[surface.IndexCount];
			tri.Vertices = new Vertex[surface.VertexCount];

			_indexes.CopyTo(surface.FirstIndex, tri.Indexes, 0, surface.IndexCount);

			// we might be able to avoid copying these and just let them reference the list vars
			// but some things, like deforms and recursive
			// guis, need to access the verts in cpu space, not just through the vertex range
			_vertices.CopyTo(surface.FirstVertex, tri.Vertices, 0, surface.VertexCount);

			// move the verts to the vertex cache
			tri.AmbientCache = idE.RenderSystem.AllocateVertexCacheFrameTemporary(tri.Vertices);

			// if we are out of vertex cache, don't create the surface
			if(tri.AmbientCache == null)
			{
				return;
			}

			RenderEntityComponent renderEntity = new RenderEntityComponent();
			renderEntity.MaterialParameters[0] = surface.Color.X;
			renderEntity.MaterialParameters[1] = surface.Color.Y;
			renderEntity.MaterialParameters[2] = surface.Color.Z;
			renderEntity.MaterialParameters[3] = surface.Color.W;

			ViewEntity guiSpace = new ViewEntity();
			guiSpace.ModelMatrix = modelMatrix;
			guiSpace.ModelViewMatrix = modelViewMatrix;
			guiSpace.WeaponDepthHack = depthHack;

			// add the surface, which might recursively create another gui
			idE.RenderSystem.AddDrawSurface(tri, guiSpace, renderEntity, surface.Material, idE.RenderSystem.ViewDefinition.Scissor);
		}
예제 #7
0
		/// <summary>
		/// Does not write to the demo file, which will only be updated for visible entities.
		/// </summary>
		/// <param name="index"></param>
		/// <param name="renderComponent"></param>
		public void UpdateEntityDefinition(int index, RenderEntityComponent renderComponent)
		{
			if(idE.CvarSystem.GetBool("r_skipUpdates") == true)
			{
				return;
			}

			// TODO: tr.pc.c_entityUpdates++;

			if((renderComponent.Model == null) && (renderComponent.Callback == null))
			{
				idConsole.Error("idRenderWorld::UpdateEntityDefinition: NULL model");
			}

			// create new slots if needed
			if((index < 0) || (index > idE.LudicrousEntityIndex))
			{
				idConsole.Error("idRenderWorld::UpdateEntityDefinitionL index = {0}", index);
			}

			while(index >= _entityDefinitions.Count)
			{
				_entityDefinitions.Add(null);
			}

			idRenderEntity def = _entityDefinitions[index];

			if(def != null)
			{
				if(renderComponent.ForceUpdate == false)
				{
					idConsole.Warning("TODO: force update - quite important!");

					/*// check for exact match (OPTIMIZE: check through pointers more)
					if ( !re->joints && !re->callbackData && !def->dynamicModel && !memcmp( re, &def->parms, sizeof( *re ) ) ) {
						return;
					}

					// if the only thing that changed was shaderparms, we can just leave things as they are
					// after updating parms

					// if we have a callback function and the bounds, origin, axis and model match,
					// then we can leave the references as they are
					if ( re->callback ) {

						bool axisMatch = ( re->axis == def->parms.axis );
						bool originMatch = ( re->origin == def->parms.origin );
						bool boundsMatch = ( re->bounds == def->referenceBounds );
						bool modelMatch = ( re->hModel == def->parms.hModel );

						if ( boundsMatch && originMatch && axisMatch && modelMatch ) {
							// only clear the dynamic model and interaction surfaces if they exist
							c_callbackUpdate++;
							R_ClearEntityDefDynamicModel( def );
							def->parms = *re;
							return;
						}
					}*/
				}

				// save any decals if the model is the same, allowing marks to move with entities
				if(def.Parameters.Model == renderComponent.Model)
				{
					FreeEntityDefDerivedData(def, true, true);
				}
				else
				{
					FreeEntityDefDerivedData(def, false, false);
				}
			}
			else
			{
				// creating a new one
				def = new idRenderEntity();
				_entityDefinitions[index] = def;

				def.World = this;
				def.EntityIndex = index;
			}

			def.Parameters = renderComponent;
			def.ModelMatrix = idHelper.AxisToModelMatrix(def.Parameters.Axis, def.Parameters.Origin);
			def.LastModifiedFrameNumber = idE.RenderSystem.FrameCount;

			// TODO: demo
			/*if ( session->writeDemo && def->archived ) {
				WriteFreeEntity( entityHandle );
				def->archived = false;
			}*/

			// optionally immediately issue any callbacks
			if((idE.CvarSystem.GetBool("r_useEntityCallbacks") == false) && (def.Parameters.Callback != null))
			{
				idConsole.Warning("TODO: R_IssueEntityDefCallback( def );");
			}

			// based on the model bounds, add references in each area
			// that may contain the updated surface
			CreateEntityReferences(def);
		}
예제 #8
0
		/// <summary>
		/// Calculates a rough bounds by using the joint radii without
		/// transforming all the points.
		/// </summary>
		/// <param name="renderEntity"></param>
		/// <returns></returns>
		public override idBounds GetBounds(RenderEntityComponent renderEntity = null)
		{ 
			if(this.Disposed == true)
			{
				throw new ObjectDisposedException(this.GetType().Name);
			}

			if(renderEntity == null)
			{
				// this is the bounds for the reference pose
				return _bounds;
			}

			return renderEntity.Bounds;
		}
예제 #9
0
		/// <summary>
		/// Does not write to the demo file, which will only be updated for visible entities.
		/// </summary>
		/// <param name="index"></param>
		/// <param name="renderComponent"></param>
		public void UpdateEntityDefinition(idRenderEntity renderEntity, RenderEntityComponent renderComponent)
		{
			UpdateEntityDefinition(_entityDefinitions[_entityDefinitions.IndexOf(renderEntity)], renderComponent);
		}
예제 #10
0
		public idRenderEntity AddEntityDefinition(RenderEntityComponent renderComponent)
		{
			// try and reuse a free spot
			int index = _entityDefinitions.FindIndex(x => x == null);

			if(index == -1)
			{
				index = _entityDefinitions.Count;
				_entityDefinitions.Add(null);

				idConsole.Warning("TODO: ResizeInteractionTable");
				/*if ( interactionTable && entityDefs.Num() > interactionTableWidth ) {
					ResizeInteractionTable();
				}*/
			}

			UpdateEntityDefinition(index, renderComponent);

			return _entityDefinitions[index];
		}
예제 #11
0
		private void PreRender()
		{
			if(_needsRender == true)
			{
				_world.InitFromMap(null);

				idDict spawnArgs = new idDict();
				spawnArgs.Set("classname", "light");
				spawnArgs.Set("name", "light_1");
				spawnArgs.Set("origin", _lightOrigin);
				spawnArgs.Set("_color", _lightColor);

				idConsole.Warning("TODO: lighting");
			
				/*gameEdit->ParseSpawnArgsToRenderLight(&spawnArgs, &rLight);
				lightDef = world->AddLightDef(&rLight);
				if(!modelName[0])
				{
					common->Warning("Window '%s' in gui '%s': no model set", GetName(), GetGui()->GetSourceFile());
				}*/

				spawnArgs.Clear();
				spawnArgs.Set("classname", "func_static");
				spawnArgs.Set("model", _modelName);
				spawnArgs.Set("origin", _modelOrigin);

				_worldEntity = idE.GameEdit.ParseSpawnArgsToRenderEntity(spawnArgs);

				if(_worldEntity.Model != null)
				{
					Vector3 v = _modelRotate.ToVector3();

					_worldEntity.Axis = v.ToMatrix();
					_worldEntity.MaterialParameters[0] = 1;
					_worldEntity.MaterialParameters[0] = 1;
					_worldEntity.MaterialParameters[0] = 1;
					_worldEntity.MaterialParameters[0] = 1;

					_renderEntity = _world.AddEntityDefinition(_worldEntity);
				}

				_needsRender.Set(false);
			}
		}
예제 #12
0
		public override RenderEntityComponent ParseSpawnArgsToRenderEntity(idDict args)
		{
			RenderEntityComponent renderEntity = new RenderEntityComponent();
			idDeclModel modelDef = null;
			
			string temp = args.GetString("model");

			if(temp != string.Empty)
			{
				modelDef = idE.DeclManager.FindType<idDeclModel>(DeclType.ModelDef, temp, false);

				if(modelDef != null)
				{
					renderEntity.Model = modelDef.Model;
				}

				if(renderEntity.Model == null)
				{
					renderEntity.Model = idE.RenderModelManager.FindModel(temp);
				}
			}

			if(renderEntity.Model != null)
			{
				renderEntity.Bounds = renderEntity.Model.GetBounds(renderEntity);
			}
			else
			{
				renderEntity.Bounds = new idBounds();
			}

			temp = args.GetString("skin");

			if(temp != string.Empty)
			{
				renderEntity.CustomSkin = idR.DeclManager.FindSkin(temp);
			}
			else if(modelDef != null)
			{
				renderEntity.CustomSkin = modelDef.DefaultSkin;
			}

			temp = args.GetString("shader");

			if(temp != null)
			{
				renderEntity.CustomMaterial = idR.DeclManager.FindMaterial(temp);
			}

			renderEntity.Origin = args.GetVector3("origin", Vector3.Zero);

			// get the rotation matrix in either full form, or single angle form
			renderEntity.Axis = args.GetMatrix("rotation", "1 0 0 0 1 0 0 0 1");

			if(renderEntity.Axis == Matrix.Identity)
			{
				float angle = args.GetFloat("angle");

				if(angle != 0.0f)
				{
					renderEntity.Axis = new idAngles(0.0f, angle, 0.0f).ToMatrix();
				}
				else
				{
					renderEntity.Axis = Matrix.Identity;
				}
			}

			// TODO:
			//renderEntity.ReferencedSound = null;

			// get shader parms
			Vector3 color = args.GetVector3("_color", new Vector3(1, 1, 1));

			float[] materialParms = renderEntity.MaterialParameters;

			materialParms[(int) MaterialParameter.Red] = color.X;
			materialParms[(int) MaterialParameter.Green] = color.Y;
			materialParms[(int) MaterialParameter.Blue] = color.Z;

			materialParms[3] = args.GetFloat("shaderParm3", 1);
			materialParms[4] = args.GetFloat("shaderParm4", 0);
			materialParms[5] = args.GetFloat("shaderParm5", 0);
			materialParms[6] = args.GetFloat("shaderParm6", 0);
			materialParms[7] = args.GetFloat("shaderParm7", 0);
			materialParms[8] = args.GetFloat("shaderParm8", 0);
			materialParms[9] = args.GetFloat("shaderParm9", 0);
			materialParms[10] = args.GetFloat("shaderParm10", 0);
			materialParms[11] = args.GetFloat("shaderParm11", 0);

			renderEntity.MaterialParameters = materialParms;

			// check noDynamicInteractions flag
			renderEntity.NoDynamicInteractions = args.GetBool("noDynamicInteractions");

			// check noshadows flag
			renderEntity.NoShadow = args.GetBool("noshadows");

			// check noselfshadows flag
			renderEntity.NoSelfShadow = args.GetBool("noselfshadows");

			// init any guis, including entity-specific states
			int count = renderEntity.Gui.Length;

			for(int i = 0; i < count; i++)
			{
				temp = args.GetString(i == 0 ? "gui" : string.Format("gui{0}", i + 1));

				if(temp != null)
				{
					renderEntity.Gui[i] = AddRenderGui(temp, args);
				}
			}

			return renderEntity;
		}		
예제 #13
0
		public void AddDrawSurface(Surface surface, ViewEntity space, RenderEntityComponent renderEntity, idMaterial material, idScreenRect scissor)
		{
			float[] materialParameters;
			float[] referenceRegisters = new float[idE.MaxExpressionRegisters];
			float[] generatedMaterialParameters = new float[idE.MaxEntityMaterialParameters];

			DrawSurface drawSurface = new DrawSurface();
			drawSurface.Geometry = surface;
			drawSurface.Space = space;
			drawSurface.Material = material;
			drawSurface.ScissorRectangle = scissor;
			drawSurface.Sort = (float) material.Sort + _sortOffset;

			// bumping this offset each time causes surfaces with equal sort orders to still
			// deterministically draw in the order they are added
			_sortOffset += 0.000001f;

			// process the shader expressions for conditionals / color / texcoords
			float[] constantRegisters = material.ConstantRegisters;

			if(constantRegisters != null)
			{
				// shader only uses constant values
				drawSurface.MaterialRegisters = constantRegisters;
			}
			else
			{
				drawSurface.MaterialRegisters = new float[material.RegisterCount];

				// a reference shader will take the calculated stage color value from another shader
				// and use that for the parm0-parm3 of the current shader, which allows a stage of
				// a light model and light flares to pick up different flashing tables from
				// different light shaders				
				if(renderEntity.ReferenceMaterial != null)
				{
					// evaluate the reference shader to find our shader parms
					//renderEntity.ReferenceMaterial.EvaluateRegisters(ref referenceRegisters, renderEntity.MaterialParameters, this.ViewDefinition, renderEntity.ReferenceSound);

					idConsole.Warning("TODO: ref material");
					/*MaterialStage stage = renderEntity.ReferenceMaterial.GetStage(0);

					memcpy( generatedShaderParms, renderEntity->shaderParms, sizeof( generatedShaderParms ) );
					generatedShaderParms[0] = refRegs[ pStage->color.registers[0] ];
					generatedShaderParms[1] = refRegs[ pStage->color.registers[1] ];
					generatedShaderParms[2] = refRegs[ pStage->color.registers[2] ];*/

					materialParameters = generatedMaterialParameters;
				} 
				else
				{
					// evaluate with the entityDef's shader parms
					materialParameters = renderEntity.MaterialParameters;
				}

				float oldFloatTime = 0;
				int oldTime = 0;

				if((space.EntityDef != null) && (space.EntityDef.Parameters.TimeGroup != 0))
				{
					oldFloatTime = this.ViewDefinition.FloatTime;
					oldTime = this.ViewDefinition.RenderView.Time;

					this.ViewDefinition.FloatTime = idE.Game.GetTimeGroupTime(space.EntityDef.Parameters.TimeGroup) * 0.001f;
					this.ViewDefinition.RenderView.Time = idE.Game.GetTimeGroupTime(space.EntityDef.Parameters.TimeGroup);
				}

				material.EvaluateRegisters(ref drawSurface.MaterialRegisters, materialParameters, idE.RenderSystem.ViewDefinition /* TODO: ,renderEntity->referenceSound*/);

				if((space.EntityDef != null) && (space.EntityDef.Parameters.TimeGroup != 0))
				{
					this.ViewDefinition.FloatTime = oldFloatTime;
					this.ViewDefinition.RenderView.Time = oldTime;
				}
			}

			// check for deformations
			// TODO: R_DeformDrawSurf( drawSurf );

			// skybox surfaces need a dynamic texgen
			// TODO: skybox
			/*switch( shader->Texgen() ) {
				case TG_SKYBOX_CUBE:
					R_SkyboxTexGen( drawSurf, tr.viewDef->renderView.vieworg );
					break;
				case TG_WOBBLESKY_CUBE:
					R_WobbleskyTexGen( drawSurf, tr.viewDef->renderView.vieworg );
					break;
			}*/

			// check for gui surfaces
			// TODO: gui surface
			idUserInterface	gui = null;

			if(space.EntityDef == null)
			{
				gui = material.GlobalInterface;
			}
			else
			{
				idConsole.Warning("TODO: global gui");
				/*int guiNum = shader->GetEntityGui() - 1;
				if ( guiNum >= 0 && guiNum < MAX_RENDERENTITY_GUI ) {
					gui = renderEntity->gui[ guiNum ];
				}
				if ( gui == NULL ) {
					gui = shader->GlobalGui();
				}*/
			}

			if(gui != null)
			{
				// force guis on the fast time
				float oldFloatTime = this.ViewDefinition.FloatTime;
				int oldTime = this.ViewDefinition.RenderView.Time;

				this.ViewDefinition.FloatTime = idE.Game.GetTimeGroupTime(1) * 0.001f;
				this.ViewDefinition.RenderView.Time = idE.Game.GetTimeGroupTime(1);

				idBounds ndcBounds;

				idConsole.Warning("TODO: precise cull + render gui surface");

				/*if ( !R_PreciseCullSurface( drawSurf, ndcBounds ) ) {
					// did we ever use this to forward an entity color to a gui that didn't set color?
		//			memcpy( tr.guiShaderParms, shaderParms, sizeof( tr.guiShaderParms ) );
					R_RenderGuiSurf( gui, drawSurf );
				}*/

				this.ViewDefinition.FloatTime = oldFloatTime;
				this.ViewDefinition.RenderView.Time = oldTime;
			}

			_viewDefinition.DrawSurfaces.Add(drawSurface);

			// we can't add subviews at this point, because that would
			// increment tr.viewCount, messing up the rest of the surface
			// adds for this view
		}