protected override void _RenderObjects(TorqueObjectType renderMask, float aspectRatio) { // clear results from previous container query _containerQueryResults.Clear(); // find objects to render RectangleF sceneRect = new RectangleF(_t2dCamera.SceneMin.X, _t2dCamera.SceneMin.Y, _t2dCamera.SceneMax.X - _t2dCamera.SceneMin.X, _t2dCamera.SceneMax.Y - _t2dCamera.SceneMin.Y); FindObjects(sceneRect, renderMask, 0xFFFFFFFF, _containerQueryResults); // sort by layer if (_useLayerSorting && _containerQueryResults.Count > 0) { _containerQueryResults.Sort(T2DLayerSortDictionary.LayerSort); // sort contents of each layer int start = 0; int lastLayer = (_containerQueryResults[0] as ISceneObject2D).Layer; for (int end = 0; end < _containerQueryResults.Count; end++) { ISceneObject2D sceneObject = _containerQueryResults[end] as ISceneObject2D; int layer = sceneObject.Layer; // We reached the last object in a layer, or, the end of the // list. Sort this subsection. if (layer == lastLayer && end < _containerQueryResults.Count - 1) continue; IComparer<ISceneContainerObject> comparer = null; if (!_layerSortDictionary.TryGetValue(lastLayer, out comparer) || comparer == null) comparer = T2DLayerSortDictionary.DefaultSort; if (comparer != T2DLayerSortDictionary.NoSort && (end - start) > 1) _containerQueryResults.Sort(start, end - start, comparer); start = end; lastLayer = layer; } } if (!_useDepthBuffer) SceneRenderer.RenderManager.BinOverride = RenderInstance.RenderInstanceType.Mesh2D; // Number of objects we are about to render. int count = _containerQueryResults.Count; // This is the greatest depth value that will still be render as within // the camera frustum. Because the objects LayerDepth is a world // space value we must account for any camera offset in z. float maxDepth = _t2dCamera.FarDistance - _t2dCamera.Transform.Translation.Z; // If the FarDistance happens to be rediculously close, lets at // least not crash. if (maxDepth <= 0.0f) maxDepth = 1.0f; // Give each object a sliver of our available depth. // Given enough objects it is still possible to have z-fighting // but this is better than losing objects by pushing them past the FarDistance. float step = -maxDepth / (float)count; for (int i = 0; i < count; i++) { ISceneObject2D sceneObject = _containerQueryResults[i] as ISceneObject2D; sceneObject.LayerDepth = _useLayerSorting ? step * (float)i : -(float)sceneObject.Layer; _containerQueryResults[i].Render(_srs); } SceneRenderer.RenderManager.BinOverride = RenderInstance.RenderInstanceType.UndefinedType; }
/// <summary> /// Find object in scene container within the given search radius and matching the specified object type and layers. /// </summary> /// <param name="pos">Center of search radius.</param> /// <param name="radius">Radius of search.</param> /// <param name="findTypes">Object types to match.</param> /// <param name="layerMask">Layers to match.</param> /// <param name="list">List which will contain results. Note: list is not cleared.</param> public void FindObjects(Vector2 pos, float radius, TorqueObjectType findTypes, uint layerMask, List<ISceneContainerObject> list) { RectangleF searchRect = new RectangleF(pos.X - radius, pos.Y - radius, 2.0f * radius, 2.0f * radius); FindObjects(searchRect, findTypes, layerMask, list); for (int i = 0; i < list.Count; i++) { T2DSceneObject obj = list[i] as T2DSceneObject; if (obj == null) continue; RectangleF objRect = obj.WorldCollisionClipRectangle; Vector2 objRad = 0.5f * objRect.Extent; Vector2 objPos = objRect.Point + objRad; // find closest x coord of object rect to pos if (pos.X < objPos.X - objRad.X) objPos.X = objPos.X - objRad.X; else if (pos.X > objPos.X + objRad.X) objPos.X = objPos.X + objRad.X; else objPos.X = pos.X; // find closest y coord of object rect to pos if (pos.Y < objPos.Y - objRad.Y) objPos.Y = objPos.Y - objRad.Y; else if (pos.Y > objPos.Y + objRad.Y) objPos.Y = objPos.Y + objRad.Y; else objPos.Y = pos.Y; // if object further than radius away, get rid of it if ((pos - objPos).LengthSquared() > radius * radius) { list[i] = list[list.Count - 1]; list.RemoveAt(list.Count - 1); i--; } } }
/// <summary> /// Find objects in scene container within the given search rectangle and matching the specified object types and layers. /// </summary> /// <param name="searchRect">World rectangle to search.</param> /// <param name="findTypes">Object types to match.</param> /// <param name="layerMask">Layers to match.</param> /// <param name="list">List which will contain results. Note: list is not cleared.</param> public void FindObjects(RectangleF searchRect, TorqueObjectType findTypes, uint layerMask, List<ISceneContainerObject> list) { // prepare container system query _queryData.Rectangle = searchRect; _queryData.ObjectTypes = findTypes; _queryData.LayerMask = layerMask; _queryData.IgnoreObject = null; _queryData.IgnoreObjects = null; _queryData.FindInvisible = false; _queryData.IgnorePhysics = false; _queryData.ResultList = list; // do the query _container.FindObjects(_queryData); }
protected abstract void _RenderObjects(TorqueObjectType renderMask, float aspectRatio);
/// <summary> /// Render the objects which have object types compatible with the render mask but not /// the noRenderMask. /// </summary> /// <param name="gfx">Graphics device with which to render</param> /// <param name="renderMask">Render objects of these types.</param> /// <param name="noRenderMask">Do not render objects of these types.</param> public void Render(GFXDevice gfx, TorqueObjectType renderMask, TorqueObjectType noRenderMask) { #if DEBUG Profiler.Instance.StartBlock("SceneGraph.Render"); #endif SceneRenderer.RenderManager.Sort(_srs); SceneRenderer.RenderManager.PreRender(_srs); SceneRenderer.RenderManager.Render(_srs); SceneRenderer.RenderManager.Clear(); #if DEBUG Profiler.Instance.EndBlock("SceneGraph.Render"); #endif }
/// <summary> /// Prepare to render objects which have object types compatible with the render mask but /// not the noRenderMask. /// </summary> /// <param name="gfx">Graphics device with which to render</param> /// <param name="renderMask">Render objects of these types.</param> /// <param name="noRenderMask">Do not render objects of these types.</param> public void PreRender(GFXDevice gfx, TorqueObjectType renderMask, TorqueObjectType noRenderMask, float aspectRatio) { #if DEBUG Profiler.Instance.StartBlock("SceneGraph.PreRender"); #endif Assert.Fatal(gfx != null, "SceneGraph.PreRender - Must have a GFX device in order to render"); Assert.Fatal(_camera != null, "SceneGraph.PreRender - Must have a camera in order to render"); UpdateFrameTime(); // setup state _SetupSceneState(gfx); _SetupView(gfx); _SetupWorld(gfx); _SetupProjection(gfx, aspectRatio); if (_preloadMaterialsDelegate != null) _preloadMaterialsDelegate(_srs); _preloadMaterialsDelegate = null; // similar to the preload delegate, provide an event for first render // cafTODO: should preload delegate be moved into this? if (!_hasRendered) { TorqueEventManager.TriggerEvent(_firstRenderEvent, 0); _hasRendered = true; } // render _RenderObjects(renderMask - noRenderMask, aspectRatio); #if DEBUG Profiler.Instance.EndBlock("SceneGraph.PreRender"); #endif }