public void OnLoad() { var dir = Directory.GetCurrentDirectory(); ResourceGroupManager.Instance.AddResourceLocation(dir, "Folder"); //MaterialManager.Instance.Initialize(); _scene = _root.CreateSceneManager("DefaultSceneManager", "SLSharpInstance"); _scene.ClearScene(); Bindings.Axiom.SLSharp.Init(); Shader.DebugMode = true; //Shader.DebugMode = true; _clipmap = new Clipmap(_scene); RecalcHeight(); _camera = _scene.CreateCamera("MainCamera"); _camera.Position = new Vector3(0, 0, 5); _camera.LookAt(Vector3.Zero); _camera.Near = 0.001f; _camera.Far = 20.0f; _camera.AutoAspectRatio = true; var vp = _window.AddViewport(_camera); vp.BackgroundColor = ColorEx.CornflowerBlue; }
public CameraComponent() { camera = null; acceleration = Vector3.Zero; velocity = Vector3.Zero; rotation = Vector3.Zero; }
/// <summary> /// /// </summary> /// <param name="camera"></param> public override void NotifyCurrentCamera( Camera camera ) { base.NotifyCurrentCamera( camera ); ///Fake orientation toward camera Vector3 zVec = ParentNode.DerivedPosition - camera.DerivedPosition; zVec.Normalize(); Vector3 fixedAxis = camera.DerivedOrientation*Vector3.UnitY; Vector3 xVec = fixedAxis.Cross( zVec ); xVec.Normalize(); Vector3 yVec = zVec.Cross( xVec ); yVec.Normalize(); Quaternion oriQuat = Quaternion.FromAxes( xVec, yVec, zVec ); this.fakeOrientation = oriQuat.ToRotationMatrix(); Quaternion q = ParentNode.DerivedOrientation.UnitInverse*oriQuat; Matrix3 tempMat = q.ToRotationMatrix(); Matrix4 rotMat = Matrix4.Identity; rotMat = tempMat; rotMat.Translation = new Vector3( 0.5f, 0.5f, 0.5f ); this.unit.TextureMatrix = rotMat; }
protected override void CreateCamera() { base.CreateCamera(); camera2 = scene.CreateCamera("Camera2"); camera2.Far = 300; camera2.Near = 1; }
/// /// </summary> /// <param name="camera"></param> /// <returns></returns> public override float GetSquaredViewDepth(Camera camera) { // get the parent entitie's parent node Node node = this.ParentNode; Debug.Assert(node != null); return node.GetSquaredViewDepth(camera); }
public void Merge( AxisAlignedBox boxBounds, Sphere sphereBounds, Camera cam, bool receiver ) { aabb.Merge( boxBounds ); if ( receiver ) receiverAabb.Merge( boxBounds ); Real camDistToCenter = ( cam.DerivedPosition - sphereBounds.Center ).Length; minDistance = System.Math.Min( minDistance, System.Math.Max( (Real)0, camDistToCenter - sphereBounds.Radius ) ); maxDistance = System.Math.Max( maxDistance, camDistToCenter + sphereBounds.Radius ); }
/// <summary> /// /// </summary> /// <param name="cam"></param> /// <param name="section"></param> public override void NotifyCamera(Camera cam, PagedWorldSection section) { Grid2DPageStrategyData stratData = (Grid2DPageStrategyData)section.StrategyData; Vector3 pos = cam.DerivedPosition; Vector2 gridpos = Vector2.Zero; stratData.ConvetWorldToGridSpace(pos, ref gridpos); int row = 0, col = 0; stratData.DetermineGridLocation(gridpos, ref row, ref col); float loadRadius = stratData.LoadRadiusInCells; float holdRadius = stratData.HoldRadiusInCells; //scan the whole hold range float frowmin = (float)row - holdRadius; float frowmax = (float)row + holdRadius; float fcolmin = (float)col - holdRadius; float fcolmax = (float)col + holdRadius; int clampRowAt = stratData.CellCountVert - 1; int clampColAt = stratData.CellCountHorz - 1; //round UP max, round DOWN min int rowmin = frowmin < 0 ? 0 : (int)System.Math.Floor(frowmin); int rowmax = frowmax > clampRowAt ? clampRowAt : (int)System.Math.Ceiling(frowmax); int colmin = fcolmin < 0 ? 0 : (int)System.Math.Floor(fcolmin); int colmax = fcolmax > clampColAt ? clampColAt : (int)System.Math.Ceiling(fcolmax); // the inner, active load range frowmin = (float)row - loadRadius; frowmax = (float)row + loadRadius; fcolmin = (float)col - loadRadius; fcolmax = (float)col + loadRadius; //round UP max, round DOWN min int loadrowmin = frowmin < 0 ? 0 : (int)System.Math.Floor(frowmin); int loadrowmax = frowmax > clampRowAt ? clampRowAt : (int)System.Math.Ceiling(frowmax); int loadcolmin = fcolmin < 0 ? 0 : (int)System.Math.Floor(fcolmin); int loadcolmax = fcolmax > clampColAt ? clampColAt : (int)System.Math.Ceiling(fcolmax); for (int r = rowmin; r <= rowmax; ++r) { for (int c = colmin; c <= colmax; ++c) { PageID pageID = stratData.CalculatePageID(r, c); if (r >= loadrowmin && r <= loadrowmax && c >= loadcolmin && c <= loadcolmax) { // int the 'load' range, request it section.LoadPage(pageID); } else { // int the outer 'hold' range, keep it but don't actively load. section.HoldPage(pageID); } // other paged will by inference be marked for unloading } } }
/// <summary> /// Returns the camera-relative squared depth of this renderable. /// </summary> /// <param name="camera"></param> /// <returns></returns> public override Real GetSquaredViewDepth( Camera camera ) { Vector3 min, max, mid, dist; min = box.Minimum; max = box.Maximum; mid = ( ( min - max )*0.5 ) + min; dist = camera.DerivedPosition - mid; return dist.LengthSquared; }
public virtual void CreateCamera() { // create a camera and initialize its position camera = scene.CreateCamera("MainCamera"); camera.Position = new Vector3(0, 0, 500); camera.LookAt(new Vector3(0, 0, -300)); // set the near clipping plane to be very close camera.Near = 5; camera.AutoAspectRatio = true; }
public override void NotifyCurrentCamera(Axiom.Core.Camera cam) { if (((Camera)(cam)).IsObjectVisible(this.worldAABB)) { isVisible = true; } else { isVisible = false; return; } }
/// <summary> /// Internal method for updating the scene graph ie the tree of SceneNode instances managed by this class. /// </summary> /// <param name="cam"></param> /// <remarks> /// This must be done before issuing objects to the rendering pipeline, since derived transformations from /// parent nodes are not updated until required. This SceneManager is a basic implementation which simply /// updates all nodes from the root. This ensures the scene is up to date but requires all the nodes /// to be updated even if they are not visible. Subclasses could trim this such that only potentially visible /// nodes are updated. /// </remarks> protected override void UpdateSceneGraph(Axiom.Core.Camera cam) { // entry into here could come before SetWorldGeometry // got called which could be disasterous // so check for init if (worldGeomIsSetup) { pageManager.Update((Camera)cam); renderableManager.ResetVisibles(); } // Call the default base.UpdateSceneGraph(cam); }
public void OnLoad() { //ResourceGroupManager.Instance.AddResourceLocation("media", "Folder", true); _root.SceneManager = _sceneManager = _root.CreateSceneManager(SceneType.ExteriorClose); _sceneManager.ClearScene(); _camera = _sceneManager.CreateCamera("MainCamera"); _camera.Position = new Vector3(0, 0, 500); _camera.LookAt(new Vector3(0, 0, -300)); _camera.Near = 5; _camera.AutoAspectRatio = true; _camera.FieldOfView = 0.70f; _viewport = _renderWindow.AddViewport(_camera, 0, 0, 1.0f, 1.0f, 100); _viewport.BackgroundColor = ColorEx.Black; ; _light = _sceneManager.CreateLight("light1"); _light.Type = LightType.Directional; _light.Position = new Vector3(0, 150, 300); _light.Diffuse = ColorEx.Blue; _light.Specular = ColorEx.Blue; //_light.Direction = new Vector3(0, 0, -300); _sceneManager.AmbientLight = ColorEx.White;// new ColorEx(0.2f, 0.2f, 0.2f); ResourceGroupManager.Instance.InitializeAllResourceGroups(); _inputReader = PlatformManager.Instance.CreateInputReader(); _inputReader.Initialize(_renderWindow, true, true, false, false); _inputReader.UseKeyboardEvents = true; _inputReader.UseMouseEvents = false; //_renderItems.Add(new BasicCube()); _renderItems.Add(new CubeBrowser()); foreach (var i in _renderItems) { i.Initialise(_root); } }
/// <summary> /// Internal method for updating the scene graph ie the tree of SceneNode instances managed by this class. /// </summary> /// <param name="cam"></param> /// <remarks> /// This must be done before issuing objects to the rendering pipeline, since derived transformations from /// parent nodes are not updated until required. This SceneManager is a basic implementation which simply /// updates all nodes from the root. This ensures the scene is up to date but requires all the nodes /// to be updated even if they are not visible. Subclasses could trim this such that only potentially visible /// nodes are updated. /// </remarks> protected override void UpdateSceneGraph(Axiom.Core.Camera cam) { if (illuminationStage == IlluminationRenderStage.None) { // Notify the TerrainManager of the camera location. If a page or tile boundary is crossed // this will result in a bunch of shuffling of heightMap data. // After the object bounding boxes have been update below, we need to call // the TerrainManager again to perform LOD adjustments on all visible tiles, // and queue the non-visible ones. TerrainManager.Instance.UpdateCamera(cam); } // call the base SceneManager to update the transforms and world bounds of all the // objects in the scene graph. base.UpdateSceneGraph(cam); if (illuminationStage == IlluminationRenderStage.None) { TerrainManager.Instance.LatePerFrameProcessing(cam); } }
/// <summary> /// Internal method for locating a list of shadow casters which /// could be affecting the frustum for a given light. /// </summary> /// <remarks> /// Custom scene managers are encouraged to override this method to add optimizations, /// and to add their own custom shadow casters (perhaps for world geometry) /// </remarks> /// <param name="light"></param> /// <param name="camera"></param> protected virtual IList FindShadowCastersForLight( Light light, Camera camera ) { this.shadowCasterList.Clear(); if ( light.Type == LightType.Directional ) { // Basic AABB query encompassing the frustum and the extrusion of it AxisAlignedBox aabb = new AxisAlignedBox(); Vector3[] corners = camera.WorldSpaceCorners; Vector3 min, max; Vector3 extrude = light.DerivedDirection * -this.shadowDirLightExtrudeDist; // do first corner min = max = corners[ 0 ]; min.Floor( corners[ 0 ] + extrude ); max.Ceil( corners[ 0 ] + extrude ); for ( int c = 1; c < 8; ++c ) { min.Floor( corners[ c ] ); max.Ceil( corners[ c ] ); min.Floor( corners[ c ] + extrude ); max.Ceil( corners[ c ] + extrude ); } aabb.SetExtents( min, max ); if ( this.shadowCasterAABBQuery == null ) { this.shadowCasterAABBQuery = this.CreateAABBRegionQuery( aabb ); } else { this.shadowCasterAABBQuery.Box = aabb; } // Execute, use callback this.shadowCasterQueryListener.Prepare( false, light.GetFrustumClipVolumes( camera ), light, camera, this.shadowCasterList, light.ShadowFarDistanceSquared ); this.shadowCasterAABBQuery.Execute( this.shadowCasterQueryListener ); } else { Sphere s = new Sphere( light.DerivedPosition, light.AttenuationRange ); // eliminate early if camera cannot see light sphere if ( camera.IsObjectVisible( s ) ) { // create or init a sphere region query if ( this.shadowCasterSphereQuery == null ) { this.shadowCasterSphereQuery = this.CreateSphereRegionQuery( s ); } else { this.shadowCasterSphereQuery.Sphere = s; } // check if the light is within view of the camera bool lightInFrustum = camera.IsObjectVisible( light.DerivedPosition ); PlaneBoundedVolumeList volumeList = null; // Only worth building an external volume list if // light is outside the frustum if ( !lightInFrustum ) { volumeList = light.GetFrustumClipVolumes( camera ); } // prepare the query and execute using the callback this.shadowCasterQueryListener.Prepare( lightInFrustum, volumeList, light, camera, this.shadowCasterList, light.ShadowFarDistanceSquared ); this.shadowCasterSphereQuery.Execute( this.shadowCasterQueryListener ); } } return this.shadowCasterList; }
/// <summary> /// Internal method for locating a list of lights which could be affecting the frustum. /// </summary> /// <remarks> /// Custom scene managers are encouraged to override this method to make use of their /// scene partitioning scheme to more efficiently locate lights, and to eliminate lights /// which may be occluded by word geometry. /// </remarks> /// <param name="camera">Camera to find lights within it's view.</param> protected virtual void FindLightsAffectingFrustum( Camera camera ) { // Basic iteration for this scene manager this.lightsAffectingFrustum.Clear(); MovableObjectCollection lightList = this.GetMovableObjectCollection( LightFactory.TypeName ); // sphere to use for testing Sphere sphere = new Sphere(); foreach ( Light light in lightList.Values ) { if ( light.IsVisible ) { if ( light.Type == LightType.Directional ) { // Always visible this.lightsAffectingFrustum.Add( light ); } else { // treating spotlight as point for simplicity // Just see if the lights attenuation range is within the frustum sphere.Center = light.DerivedPosition; sphere.Radius = light.AttenuationRange; if ( camera.IsObjectVisible( sphere ) ) { this.lightsAffectingFrustum.Add( light ); } } } } // notify light dirty, so all movable objects will re-populate // their light list next time NotifyLightsDirty(); }
/** called when the scene manager creates a camera because some zone managers (like TerrainZone) need the camera info. */ public override void NotifyCameraCreated( Camera c ) { }
public void DestroyCamera( Camera camera ) { cameraList.Remove( camera.Name ); this.targetRenderSystem.NotifyCameraRemoved( camera ); if ( !camera.IsDisposed ) camera.Dispose(); }
/// <summary> /// Internal method for updating the scene graph ie the tree of SceneNode instances managed by this class. /// </summary> /// <remarks> /// This must be done before issuing objects to the rendering pipeline, since derived transformations from /// parent nodes are not updated until required. This SceneManager is a basic implementation which simply /// updates all nodes from the root. This ensures the scene is up to date but requires all the nodes /// to be updated even if they are not visible. Subclasses could trim this such that only potentially visible /// nodes are updated. /// </remarks> /// <param name="camera"></param> protected internal virtual void UpdateSceneGraph( Camera camera ) { // Process queued needUpdate calls Node.ProcessQueuedUpdates(); // Cascade down the graph updating transforms & world bounds // In this implementation, just update from the root // Smarter SceneManager subclasses may choose to update only // certain scene graph branches based on space partioning info. this.rootSceneNode.Update( true, false ); }
/// <summary> /// Removes the specified camera from the scene. /// </summary> /// <remarks> /// This method removes a previously added camera from the scene. /// </remarks> /// <param name="camera">Reference to the camera to remove.</param> public virtual void RemoveCamera( Camera camera ) { cameraList.Remove( camera.Name ); // notify all render targets this.targetRenderSystem.NotifyCameraRemoved( camera ); }
public override void NotifyCurrentCamera(Axiom.Core.Camera cam) { if (inUse == false || isLoaded == false) { return; } if (((Camera)(cam)).IsObjectVisible(this.worldAABB)) { inFrustum = true; isVisible = true; } else { inFrustum = false; isVisible = false; return; } /* set*/ #if _VisibilityCheck //Check if the renderable need to be rendered based on the Cone normal approach //TODO: use the cone aperture not a fixed value if (Options.Instance.Lit == true) { mustRender = (bool)(cam.Direction.Dot(coneNormal) < Options.Instance.VisibilityAngle); } #endif float d = (parentNode.DerivedPosition - cam.DerivedPosition).LengthSquared; // Now adjust it by the camera bias d = d * cam.LodBias; // Material LOD //TODO:: Axiom Doesn't Support Material LOD yet. //if ( this.material.getNumLodLevels() > 1 ) // materialLODIndex = m_pMaterial->getLodIndexSquaredDepth(d); // Check if we need to decrease the LOD float factor = Options.Instance.LOD_Factor; float curr_lod = factor * (1 + RenderLevel); bool changeLOD = false; if (d < curr_lod) { if (RenderLevel != 0) { RenderLevel--; curr_lod -= factor; changeLOD = true; } } else if (RenderLevel < Options.Instance.MaxRenderLevel && d >= (curr_lod * 2)) { curr_lod += factor; RenderLevel++; changeLOD = true; } //************** //RenderLevel = Options.Instance.MaxRenderLevel; //changeLOD = true; //************** if (changeLOD || this.renderOp.indexData == null) { Update(); for (long i = 0; i < 4; i++) { if (neighbors[i] != null && neighbors[i].IsLoaded) { neighbors[i].Update(); } } } if (this.needReload) { Load(); } }
/** Updates the level of detail to be used for rendering this PagingLandScapeRenderable based on the passed in Camera */ public override void NotifyCurrentCamera(Axiom.Core.Camera cam) { PagingLandscape.Camera plsmcam = (PagingLandscape.Camera)(cam); this.isVisible = (init && loaded && plsmcam.GetVisibility(tileSceneNode.WorldAABB)); // this.isVisible = (init && loaded ); }
/// <summary> /// Internal method for rendering all the objects for a given light into the stencil buffer. /// </summary> /// <param name="light">The light source.</param> /// <param name="camera">The camera being viewed from.</param> protected virtual void RenderShadowVolumesToStencil( Light light, Camera camera ) { // get the shadow caster list IList casters = this.FindShadowCastersForLight( light, camera ); if ( casters.Count == 0 ) { // No casters, just do nothing return; } // Set up scissor test (point & spot lights only) bool scissored = false; if ( light.Type != LightType.Directional && this.targetRenderSystem.Capabilities.HasCapability( Capabilities.ScissorTest ) ) { // Project the sphere onto the camera float left, right, top, bottom; Sphere sphere = new Sphere( light.DerivedPosition, light.AttenuationRange ); if ( camera.ProjectSphere( sphere, out left, out top, out right, out bottom ) ) { scissored = true; // Turn normalised device coordinates into pixels int iLeft, iTop, iWidth, iHeight; this.currentViewport.GetActualDimensions( out iLeft, out iTop, out iWidth, out iHeight ); int szLeft, szRight, szTop, szBottom; szLeft = (int)( iLeft + ( ( left + 1 ) * 0.5f * iWidth ) ); szRight = (int)( iLeft + ( ( right + 1 ) * 0.5f * iWidth ) ); szTop = (int)( iTop + ( ( -top + 1 ) * 0.5f * iHeight ) ); szBottom = (int)( iTop + ( ( -bottom + 1 ) * 0.5f * iHeight ) ); this.targetRenderSystem.SetScissorTest( true, szLeft, szTop, szRight, szBottom ); } } this.targetRenderSystem.UnbindGpuProgram( GpuProgramType.Fragment ); // Can we do a 2-sided stencil? bool stencil2sided = false; if ( this.targetRenderSystem.Capabilities.HasCapability( Capabilities.TwoSidedStencil ) && this.targetRenderSystem.Capabilities.HasCapability( Capabilities.StencilWrap ) ) { // enable stencil2sided = true; } // Do we have access to vertex programs? bool extrudeInSoftware = true; bool finiteExtrude = !this.shadowUseInfiniteFarPlane || !this.targetRenderSystem.Capabilities.HasCapability( Capabilities.InfiniteFarPlane ); if ( this.targetRenderSystem.Capabilities.HasCapability( Capabilities.VertexPrograms ) ) { extrudeInSoftware = false; this.EnableHardwareShadowExtrusion( light, finiteExtrude ); } else { this.targetRenderSystem.UnbindGpuProgram( GpuProgramType.Vertex ); } // Add light to internal list for use in render call tmpLightList.Clear(); tmpLightList.Add( light ); // Turn off color writing and depth writing this.targetRenderSystem.SetColorBufferWriteEnabled( false, false, false, false ); this.targetRenderSystem.DepthBufferWriteEnabled = false; this.targetRenderSystem.StencilCheckEnabled = true; this.targetRenderSystem.DepthBufferFunction = CompareFunction.Less; // Calculate extrusion distance float extrudeDistance = 0; if ( light.Type == LightType.Directional ) { extrudeDistance = this.shadowDirLightExtrudeDist; } // get the near clip volume PlaneBoundedVolume nearClipVol = light.GetNearClipVolume( camera ); // Determine whether zfail is required // We need to use zfail for ALL objects if we find a single object which // requires it bool zfailAlgo = false; this.CheckShadowCasters( casters, nearClipVol, light, extrudeInSoftware, finiteExtrude, zfailAlgo, camera, extrudeDistance, stencil2sided, tmpLightList ); // revert colour write state this.targetRenderSystem.SetColorBufferWriteEnabled( true, true, true, true ); // revert depth state this.targetRenderSystem.SetDepthBufferParams(); this.targetRenderSystem.StencilCheckEnabled = false; this.targetRenderSystem.UnbindGpuProgram( GpuProgramType.Vertex ); if ( scissored ) { // disable scissor test this.targetRenderSystem.SetScissorTest( false ); } }
private void CheckShadowCasters( IList casters, PlaneBoundedVolume nearClipVol, Light light, bool extrudeInSoftware, bool finiteExtrude, bool zfailAlgo, Camera camera, float extrudeDistance, bool stencil2sided, LightList tmpLightList ) { int flags; for ( int i = 0; i < casters.Count; i++ ) { ShadowCaster caster = (ShadowCaster)casters[ i ]; if ( nearClipVol.Intersects( caster.GetWorldBoundingBox() ) ) { // We have a zfail case, we must use zfail for all objects zfailAlgo = true; break; } } for ( int ci = 0; ci < casters.Count; ci++ ) { ShadowCaster caster = (ShadowCaster)casters[ ci ]; flags = 0; if ( light.Type != LightType.Directional ) { extrudeDistance = caster.GetPointExtrusionDistance( light ); } if ( !extrudeInSoftware && !finiteExtrude ) { // hardware extrusion, to infinity (and beyond!) flags |= (int)ShadowRenderableFlags.ExtrudeToInfinity; } if ( zfailAlgo ) { // We need to include the light and / or dark cap // But only if they will be visible if ( camera.IsObjectVisible( caster.GetLightCapBounds() ) ) { flags |= (int)ShadowRenderableFlags.IncludeLightCap; } } // Dark cap (no dark cap for directional lights using // hardware extrusion to infinity) if ( !( ( flags & (int)ShadowRenderableFlags.ExtrudeToInfinity ) != 0 && light.Type == LightType.Directional ) && camera.IsObjectVisible( caster.GetDarkCapBounds( light, extrudeDistance ) ) ) { flags |= (int)ShadowRenderableFlags.IncludeDarkCap; } // get shadow renderables IEnumerator renderables = caster.GetShadowVolumeRenderableEnumerator( this.shadowTechnique, light, this.shadowIndexBuffer, extrudeInSoftware, extrudeDistance, flags ); // If using one-sided stencil, render the first pass of all shadow // renderables before all the second passes for ( int i = 0; i < ( stencil2sided ? 1 : 2 ); i++ ) { if ( i == 1 ) { renderables = caster.GetLastShadowVolumeRenderableEnumerator(); } while ( renderables.MoveNext() ) { ShadowRenderable sr = (ShadowRenderable)renderables.Current; // omit hidden renderables if ( sr.IsVisible ) { // render volume, including dark and (maybe) light caps this.RenderSingleShadowVolumeToStencil( sr, zfailAlgo, stencil2sided, tmpLightList, ( i > 0 ) ); // optionally render separate light cap if ( sr.IsLightCapSeperate && ( ( flags & (int)ShadowRenderableFlags.IncludeLightCap ) ) > 0 ) { // must always fail depth check this.targetRenderSystem.DepthBufferFunction = CompareFunction.AlwaysFail; Debug.Assert( sr.LightCapRenderable != null, "Shadow renderable is missing a separate light cap renderable!" ); this.RenderSingleShadowVolumeToStencil( sr.LightCapRenderable, zfailAlgo, stencil2sided, tmpLightList, ( i > 0 ) ); // reset depth function this.targetRenderSystem.DepthBufferFunction = CompareFunction.Less; } } } } } }
/// <summary> /// Internal method for queueing the sky objects with the params as /// previously set through SetSkyBox, SetSkyPlane and SetSkyDome. /// </summary> /// <param name="camera"></param> internal virtual void QueueSkiesForRendering( Camera camera ) { // translate the skybox by cam position if ( this.skyPlaneNode != null ) { this.skyPlaneNode.Position = camera.DerivedPosition; } if ( this.skyBoxNode != null ) { this.skyBoxNode.Position = camera.DerivedPosition; } if ( this.skyDomeNode != null ) { this.skyDomeNode.Position = camera.DerivedPosition; } RenderQueueGroupID qid; // if the skyplane is enabled, queue up the single plane if ( this.isSkyPlaneEnabled ) { qid = this.isSkyPlaneDrawnFirst ? RenderQueueGroupID.SkiesEarly : RenderQueueGroupID.SkiesLate; this.GetRenderQueue().AddRenderable( this.skyPlaneEntity.GetSubEntity( 0 ), 1, qid ); } // if the skybox is enabled, queue up all the planes if ( this.isSkyBoxEnabled ) { qid = this.isSkyBoxDrawnFirst ? RenderQueueGroupID.SkiesEarly : RenderQueueGroupID.SkiesLate; for ( int plane = 0; plane < 6; plane++ ) { this.GetRenderQueue().AddRenderable( this.skyBoxEntities[ plane ].GetSubEntity( 0 ), 1, qid ); } } // if the skydome is enabled, queue up all the planes if ( this.isSkyDomeEnabled ) { qid = this.isSkyDomeDrawnFirst ? RenderQueueGroupID.SkiesEarly : RenderQueueGroupID.SkiesLate; for ( int plane = 0; plane < 5; ++plane ) { this.GetRenderQueue().AddRenderable( this.skyDomeEntities[ plane ].GetSubEntity( 0 ), 1, qid ); } } }
/// <summary> /// Prompts the class to send its contents to the renderer. /// </summary> /// <remarks> /// This method prompts the scene manager to send the /// contents of the scene it manages to the rendering /// pipeline, possibly preceded by some sorting, culling /// or other scene management tasks. Note that this method is not normally called /// directly by the user application; it is called automatically /// by the engine's rendering loop. /// </remarks> /// <param name="camera">Pointer to a camera from whose viewpoint the scene is to be rendered.</param> /// <param name="viewport">The target viewport</param> /// <param name="showOverlays">Whether or not any overlay objects should be rendered</param> protected internal void RenderScene( Camera camera, Viewport viewport, bool showOverlays ) { // let the engine know this is the current scene manager Root.Instance.SceneManager = this; if ( this.IsShadowTechniqueInUse ) { // initialize shadow volume materials this.InitShadowVolumeMaterials(); } // Perform a quick pre-check to see whether we should override far distance // When using stencil volumes we have to use infinite far distance // to prevent dark caps getting clipped if ( this.IsShadowTechniqueStencilBased && camera.Far != 0 && this.targetRenderSystem.Capabilities.HasCapability( Capabilities.InfiniteFarPlane ) && this.shadowUseInfiniteFarPlane ) { // infinite far distance camera.Far = 0.0f; } this.cameraInProgress = camera; this.hasCameraChanged = true; // Update the scene, only do this once per frame ulong thisFrameNumber = Root.Instance.CurrentFrameCount; if ( thisFrameNumber != this.lastFrameNumber ) { // Update animations this.ApplySceneAnimations(); // Update controllers ControllerManager.Instance.UpdateAll(); this.lastFrameNumber = thisFrameNumber; } // Update scene graph for this camera (can happen multiple times per frame) this.UpdateSceneGraph( camera ); // Auto-track nodes foreach ( SceneNode sn in autoTrackingSceneNodes.Values ) { sn.AutoTrack(); } // ask the camera to auto track if it has a target camera.AutoTrack(); // Are we using any shadows at all? if ( this.IsShadowTechniqueInUse && this.illuminationStage != IlluminationRenderStage.RenderToTexture && viewport.ShowShadows && this.findVisibleObjects ) { // Locate any lights which could be affecting the frustum this.FindLightsAffectingFrustum( camera ); if ( this.IsShadowTechniqueTextureBased ) { // ******* // WARNING // ******* // This call will result in re-entrant calls to this method // therefore anything which comes before this is NOT // guaranteed persistent. Make sure that anything which // MUST be specific to this camera / target is done // AFTER THIS POINT this.PrepareShadowTextures( camera, viewport ); // reset the cameras because of the re-entrant call this.cameraInProgress = camera; this.hasCameraChanged = true; } } // Invert vertex winding? this.targetRenderSystem.InvertVertexWinding = camera.IsReflected; // Tell params about viewport this.autoParamDataSource.Viewport = viewport; // Set the viewport this.SetViewport( viewport ); // set the current camera for use in the auto GPU program params this.autoParamDataSource.Camera = camera; // Set autoparams for finite dir light extrusion this.autoParamDataSource.SetShadowDirLightExtrusionDistance( this.shadowDirLightExtrudeDist ); // sets the current ambient light color for use in auto GPU program params this.autoParamDataSource.AmbientLight = this.ambientColor; // Tell rendersystem this.targetRenderSystem.AmbientLight = this.ambientColor; // Tell params about render target this.autoParamDataSource.RenderTarget = viewport.Target; // set fog params float fogScale = 1f; if ( this.fogMode == FogMode.None ) { fogScale = 0f; } this.autoParamDataSource.FogParams = new Vector4( this.fogStart, this.fogEnd, fogScale, 0 ); // set the time in the auto param data source //autoParamDataSource.Time = ((float)Root.Instance.Timer.Milliseconds) / 1000f; // Set camera window clipping planes (if any) if ( this.targetRenderSystem.Capabilities.HasCapability( Capabilities.UserClipPlanes ) ) { // TODO: Add ClipPlanes to RenderSystem.cs if ( camera.IsWindowSet ) { targetRenderSystem.ResetClipPlanes(); IList<Plane> planeList = camera.WindowPlanes; for ( ushort i = 0; i < 4; ++i ) { targetRenderSystem.AddClipPlane( planeList[ i ] ); //this.targetRenderSystem.EnableClipPlane( i, true ); //this.targetRenderSystem.SetClipPlane( i, planeList[ i ] ); } } // this disables any user-set clipplanes... this should be done manually //else //{ // for (ushort i = 0; i < 4; ++i) // { // targetRenderSystem.EnableClipPlane(i, false); // } //} } // Prepare render queue for receiving new objects this.PrepareRenderQueue(); // Parse the scene and tag visibles if ( this.findVisibleObjects ) { if ( this.PreFindVisibleObjects != null ) PreFindVisibleObjects( this, this.illuminationStage, viewport ); this.FindVisibleObjects( camera, this.illuminationStage == IlluminationRenderStage.RenderToTexture ); if ( this.PostFindVisibleObjects != null ) PostFindVisibleObjects( this, this.illuminationStage, viewport ); } // Add overlays, if viewport deems it if ( viewport.ShowOverlays && this.illuminationStage != IlluminationRenderStage.RenderToTexture ) { // Queue overlays for rendering OverlayManager.Instance.QueueOverlaysForRendering( camera, this.GetRenderQueue(), viewport ); } // queue overlays and skyboxes for rendering if ( viewport.ShowSkies && this.findVisibleObjects && this.illuminationStage != IlluminationRenderStage.RenderToTexture ) { this.QueueSkiesForRendering( camera ); } // begin frame geometry count this.targetRenderSystem.BeginGeometryCount(); // clear the device if need be if ( viewport.ClearEveryFrame ) { this.targetRenderSystem.ClearFrameBuffer( viewport.ClearBuffers, viewport.BackgroundColor ); } // being a frame of animation this.targetRenderSystem.BeginFrame(); // use the camera's current scene detail level this.targetRenderSystem.PolygonMode = camera.PolygonMode; // Set initial camera state this.targetRenderSystem.ProjectionMatrix = camera.ProjectionMatrixRS; this.targetRenderSystem.ViewMatrix = camera.ViewMatrix; // render all visible objects this.RenderVisibleObjects(); // end the current frame this.targetRenderSystem.EndFrame(); // Notify camera of the number of rendered faces camera.NotifyRenderedFaces( this.targetRenderSystem.FaceCount ); // Notify camera of the number of rendered batches camera.NotifyRenderedBatches( this.targetRenderSystem.BatchCount ); }
/// <summary> /// Creates a camera to be managed by this scene manager. /// </summary> /// <remarks> /// This camera can be added to the scene at a later time using /// the AttachObject method of the SceneNode class. /// </remarks> /// <param name="name"></param> /// <returns></returns> public virtual Camera CreateCamera( string name ) { if ( this.cameraList.ContainsKey( name ) ) { throw new AxiomException( string.Format( "A camera with the name '{0}' already exists in the scene.", name ) ); } // create the camera and add it to our local list Camera camera = new Camera( name, this ); this.cameraList.Add( camera ); return camera; }
/// <summary> /// Internal method which parses the scene to find visible objects to render. /// </summary> /// <remarks> /// If you're implementing a custom scene manager, this is the most important method to /// override since it's here you can apply your custom world partitioning scheme. Once you /// have added the appropriate objects to the render queue, you can let the default /// SceneManager objects RenderVisibleObjects handle the actual rendering of the objects /// you pick. /// <p/> /// Any visible objects will be added to a rendering queue, which is indexed by material in order /// to ensure objects with the same material are rendered together to minimise render state changes. /// </remarks> public virtual void FindVisibleObjects( Camera camera, bool onlyShadowCasters ) { // ask the root node to iterate through and find visible objects in the scene this.rootSceneNode.FindVisibleObjects( camera, this.GetRenderQueue(), true, this.displayNodes, onlyShadowCasters ); }
public override void NotifyCurrentCamera( Camera camera ) { if ( parentNode != null ) { // Get mesh lod strategy var meshStrategy = this.mesh.LodStrategy; // Get the appropriate lod value Real lodValue = meshStrategy.GetValue( this, camera ); // Bias the lod value var biasedMeshLodValue = lodValue*this.meshLodFactorTransformed; // Get the index at this biased depth var newMeshLodIndex = this.mesh.GetLodIndex( biasedMeshLodValue ); // Apply maximum detail restriction (remember lower = higher detail) this.meshLodIndex = (int)Utility.Max( this.maxMeshLodIndex, this.meshLodIndex ); // Apply minimum detail restriction (remember higher = lower detail) this.meshLodIndex = (int)Utility.Min( this.minMeshLodIndex, this.meshLodIndex ); // Construct event object EntityMeshLodChangedEvent evt; evt.Entity = this; evt.Camera = camera; evt.LodValue = biasedMeshLodValue; evt.PreviousLodIndex = this.meshLodIndex; evt.NewLodIndex = newMeshLodIndex; // Notify lod event listeners //camera.SceneManager.NotifyEntityMeshLodChanged( evt ); // Change lod index this.meshLodIndex = evt.NewLodIndex; // Now do material LOD lodValue *= this.materialLodFactorTransformed; // apply the material LOD to all sub entities foreach ( var subEntity in this.subEntityList ) { // Get sub-entity material var material = subEntity.Material; // Get material lod strategy var materialStrategy = material.LodStrategy; // Recalculate lod value if strategies do not match Real biasedMaterialLodValue; if ( meshStrategy == materialStrategy ) { biasedMaterialLodValue = lodValue; } else { biasedMaterialLodValue = materialStrategy.GetValue( this, camera )* materialStrategy.TransformBias( this.materialLodFactor ); } // Get the index at this biased depth var idx = material.GetLodIndex( biasedMaterialLodValue ); // Apply maximum detail restriction (remember lower = higher detail) idx = (int)Utility.Max( this.maxMaterialLodIndex, idx ); // Apply minimum detail restriction (remember higher = lower detail) idx = (int)Utility.Min( this.minMaterialLodIndex, idx ); // Construct event object EntityMaterialLodChangedEvent materialLodEvent; materialLodEvent.SubEntity = subEntity; materialLodEvent.Camera = camera; materialLodEvent.LodValue = biasedMaterialLodValue; materialLodEvent.PreviousLodIndex = subEntity.MaterialLodIndex; materialLodEvent.NewLodIndex = idx; // Notify lod event listeners //camera.SceneManager.NotifyEntityMaterialLodChanged( materialLodEvent ); // Change lod index subEntity.MaterialLodIndex = materialLodEvent.NewLodIndex; // Also invalidate any camera distance cache //subEntity.InvalidateCameraCache(); } } // Notify child objects (tag points) foreach ( var child in this.childObjectList.Values ) { child.NotifyCurrentCamera( camera ); } }
/// <summary> /// Internal method for preparing shadow textures ready for use in a regular render /// </summary> /// <param name="camera"></param> /// <param name="viewPort"></param> protected internal virtual void PrepareShadowTextures( Camera camera, Viewport viewPort ) { // Set the illumination stage, prevents recursive calls IlluminationRenderStage savedStage = this.illuminationStage; this.illuminationStage = IlluminationRenderStage.RenderToTexture; // Determine far shadow distance float shadowDist = this.shadowFarDistance; if ( shadowDist == 0.0f ) { // need a shadow distance, make one up shadowDist = camera.Near * 300; } // set fogging to hide the shadow edge float shadowOffset = shadowDist * this.shadowTextureOffset; // Precalculate fading info float shadowEnd = shadowDist + shadowOffset; float fadeStart = shadowEnd * this.shadowTextureFadeStart; float fadeEnd = shadowEnd * this.shadowTextureFadeEnd; // Additive lighting should not use fogging, since it will overbrighten; use border clamp if ( !this.IsShadowTechniqueAdditive ) { this.shadowReceiverPass.SetFog( true, FogMode.Linear, ColorEx.White, 0, fadeStart, fadeEnd ); // if we have a custom receiver material, then give it the fog params too if ( this.shadowTextureCustomReceiverPass != null ) { this.shadowTextureCustomReceiverPass.SetFog( true, FogMode.Linear, ColorEx.White, 0, fadeStart, fadeEnd ); } } else { // disable fogging explicitly this.shadowReceiverPass.SetFog( true, FogMode.None ); // if we have a custom receiver material, then give it the fog params too if ( this.shadowTextureCustomReceiverPass != null ) { this.shadowTextureCustomReceiverPass.SetFog( true, FogMode.None ); } } // Iterate over the lights we've found, max out at the limit of light textures int sti = 0; foreach ( Light light in this.lightsAffectingFrustum ) { // Check limit reached if ( sti == this.shadowTextures.Count ) break; // Skip non-shadowing lights if ( !light.CastShadows ) { continue; } Texture shadowTex = this.shadowTextures[ sti ]; RenderTarget shadowRTT = shadowTex.GetBuffer().GetRenderTarget(); Viewport shadowView = shadowRTT.GetViewport( 0 ); Camera texCam = this.shadowTextureCameras[ sti ]; // rebind camera, incase another SM in use which has switched to its cam shadowView.Camera = texCam; // Associate main view camera as LOD camera texCam.LodCamera = camera; //Vector3 dir; // set base if ( light.Type == LightType.Point ) texCam.Direction = light.DerivedDirection; if ( light.Type == LightType.Directional ) texCam.Position = light.DerivedPosition; // Use the material scheme of the main viewport // This is required to pick up the correct shadow_caster_material and similar properties. shadowView.MaterialScheme = viewPort.MaterialScheme; if ( light.CustomShadowCameraSetup == null ) { _defaultShadowCameraSetup.GetShadowCamera( this, camera, viewPort, light, texCam, sti ); } else { light.CustomShadowCameraSetup.GetShadowCamera( this, camera, viewPort, light, texCam, sti ); } shadowView.BackgroundColor = ColorEx.White; // Fire shadow caster update, callee can alter camera settings // fireShadowTexturesPreCaster(light, texCam); // Update target shadowRTT.Update(); ++sti; } // Set the illumination stage, prevents recursive calls this.illuminationStage = savedStage; //fireShadowTexturesUpdated( std::min(mLightsAffectingFrustum.size(), mShadowTextures.size())); }
public override float GetSquaredViewDepth(Axiom.Core.Camera camera) { // Use squared length to avoid square root return((this.ParentNode.DerivedPosition - camera.DerivedPosition).LengthSquared); }
/// <summary> /// Prepare the listener for use with a set of parameters. /// </summary> /// <param name="lightInFrustum"></param> /// <param name="lightClipVolumes"></param> /// <param name="light"></param> /// <param name="camera"></param> /// <param name="shadowCasterList"></param> /// <param name="farDistSquared"></param> public void Prepare( bool lightInFrustum, PlaneBoundedVolumeList lightClipVolumes, Light light, Camera camera, List<ShadowCaster> shadowCasterList, float farDistSquared ) { this.casterList = shadowCasterList; this.isLightInFrustum = lightInFrustum; this.lightClipVolumeList = lightClipVolumes; this.camera = camera; this.light = light; this.farDistSquared = farDistSquared; }
/// <summary> /// Walks the BSP tree looking for the node which the camera is in, and tags any geometry /// which is in a visible leaf for later processing. /// </summary> protected BspNode WalkTree( Camera camera, bool onlyShadowCasters ) { if ( this.level == null ) { return null; } // Locate the leaf node where the camera is located BspNode cameraNode = this.level.FindLeaf( camera.DerivedPosition ); this.matFaceGroupMap.Clear(); this.faceGroupChecked.Clear(); // Scan through all the other leaf nodes looking for visibles int i = this.level.NumNodes - this.level.LeafStart; int p = this.level.LeafStart; BspNode node; while ( i-- > 0 ) { node = this.level.Nodes[ p ]; if ( this.level.IsLeafVisible( cameraNode, node ) ) { // Visible according to PVS, check bounding box against frustum //if ( camera.IsObjectVisible( node.BoundingBox ) ) { ProcessVisibleLeaf( node, camera, onlyShadowCasters ); if ( this.showNodeAABs ) { AddBoundingBox( node.BoundingBox, true ); } } } p++; } return cameraNode; }
public override Real GetSquaredViewDepth( Camera camera ) { return 0; }
/// <summary> /// Tags geometry in the leaf specified for later rendering. /// </summary> protected void ProcessVisibleLeaf( BspNode leaf, Camera camera, bool onlyShadowCasters ) { // Skip world geometry if we're only supposed to process shadow casters // World is pre-lit if ( !onlyShadowCasters ) { // Parse the leaf node's faces, add face groups to material map int numGroups = leaf.NumFaceGroups; int idx = leaf.FaceGroupStart; while ( numGroups-- > 0 ) { int realIndex = this.level.LeafFaceGroups[ idx++ ]; // Is it already checked ? if ( this.faceGroupChecked.ContainsKey( realIndex ) && this.faceGroupChecked[ realIndex ] == true ) { continue; } this.faceGroupChecked[ realIndex ] = true; BspStaticFaceGroup faceGroup = this.level.FaceGroups[ realIndex ]; // Get Material reference by handle Material mat = GetMaterial( faceGroup.materialHandle ); // Check normal (manual culling) ManualCullingMode cullMode = mat.GetTechnique( 0 ).GetPass( 0 ).ManualCullingMode; if ( cullMode != ManualCullingMode.None ) { float dist = faceGroup.plane.GetDistance( camera.DerivedPosition ); if ( ( ( dist < 0 ) && ( cullMode == ManualCullingMode.Back ) ) || ( ( dist > 0 ) && ( cullMode == ManualCullingMode.Front ) ) ) { continue; } } // Try to insert, will find existing if already there this.matFaceGroupMap.Add( mat, faceGroup ); } } // Add movables to render queue, provided it hasn't been seen already. foreach ( MovableObject obj in leaf.Objects.Values ) { if ( !this.objectsForRendering.ContainsKey( obj.Name ) ) { if ( obj.IsVisible && ( !onlyShadowCasters || obj.CastShadows ) && camera.IsObjectVisible( obj.GetWorldBoundingBox() ) ) { obj.NotifyCurrentCamera( camera ); obj.UpdateRenderQueue( renderQueue ); // Check if the bounding box should be shown. var node = (SceneNode)obj.ParentNode; if ( node.ShowBoundingBox || showBoundingBoxes ) { node.AddBoundingBoxToQueue( renderQueue ); } this.objectsForRendering.Add( obj ); } } } }
protected void CreateCamera() { camera = scene.CreateCamera("PlayerCam"); ResetCameraPosition(); camera.Near = 1 * oneMeter; camera.Far = 10000 * oneMeter; camera.AspectRatio = (float)window.Width / window.Height; }
/** called when the scene manager creates a camera in order to store the first camera created as the primary one, for determining error metrics and the 'home' terrain page. */ public abstract void NotifyCameraCreated( Camera c );