/// <summary> /// Sorts the provided list by camera space z distance. /// Assumes a right-handed coordinate system, so the farthest nodes have the most negative values.</summary> /// <param name="list">List of alpha TraverseNodes to sort</param> /// <param name="viewMatrix">Current view matrix to transform bounding box centroids by</param> public static void SortByCameraSpaceDepth(List <TraverseNode> list, Matrix4F viewMatrix) { KeyValuePair <float, TraverseNode>[] camSpaceDistances = new KeyValuePair <float, TraverseNode> [list.Count]; for (int i = 0; i < list.Count; ++i) { TraverseNode node = list[i]; Vec3F worldSpaceCentroid = node.WorldSpaceBoundingBox.Centroid; Vec3F centerPointInCameraSpace; viewMatrix.Transform(worldSpaceCentroid, out centerPointInCameraSpace); camSpaceDistances[i] = new KeyValuePair <float, TraverseNode>(centerPointInCameraSpace.Z, node); } Array.Sort(camSpaceDistances, new CamSpaceDistanceComparer()); list.Clear(); foreach (KeyValuePair <float, TraverseNode> entry in camSpaceDistances) { list.Add(entry.Value); } }
/// <summary> /// Traverses the control for rendering</summary> /// <param name="graphPath">The path leading to the control</param> /// <param name="action">Render action</param> /// <param name="list">Traverse list</param> public void Traverse( Stack <SceneNode> graphPath, IRenderAction action, ICollection <TraverseNode> list) { TraverseNode node = action.GetUnusedNode(); node.Init(action.RenderObject, action.TopMatrix, graphPath, s_renderState); list.Add(node); }
public bool TryAdd(TraverseNode node) { bool passedPositive = (node.RenderState.RenderMode & PassBits) == PassBits; bool passedNegative = (node.RenderState.RenderMode & NoPassBits) == 0; if (passedPositive && passedNegative) { m_nodes.Add(node); m_sorted = false; return(true); } return(false); }
/// <summary> /// Performs any traverse actions</summary> /// <param name="graphPath">The path leading to the RenderObject</param> /// <param name="renderAction">The render action used to dispatch the object</param> /// <param name="camera">The Camera used</param> /// <param name="traverseList">The traverse list used in the dispatch phase. /// RenderObjects participating in the dispatch phase need to push themselves onto the traverse list.</param> /// <returns>The TraverseState</returns> public virtual TraverseState Traverse(Stack <SceneNode> graphPath, IRenderAction renderAction, Camera camera, ICollection <TraverseNode> traverseList) { RenderState state = renderAction.RenderState; Box boundingBox = null; bool alpha = ((state.RenderMode & RenderMode.Alpha) != 0); if (alpha) { boundingBox = GetBoundingBoxObjectSpace(); boundingBox.Transform(renderAction.TopMatrix); } if ((state.RenderMode & RenderMode.Smooth) != 0) { RenderMode origRenderMode = state.RenderMode; state.RenderMode &= ~(RenderMode.Wireframe | RenderMode.WireframeColor); TraverseNode node = renderAction.GetUnusedNode(); node.Init(renderAction.RenderObject, renderAction.TopMatrix, graphPath, state); if (alpha) { node.WorldSpaceBoundingBox = boundingBox; } traverseList.Add(node); state.RenderMode = origRenderMode; } if ((state.RenderMode & RenderMode.Wireframe) != 0) { RenderMode origRenderMode = state.RenderMode; state.RenderMode &= ~(RenderMode.Smooth | RenderMode.SolidColor | RenderMode.Textured | RenderMode.Lit); TraverseNode node = renderAction.GetUnusedNode(); node.Init(renderAction.RenderObject, renderAction.TopMatrix, graphPath, state); if (alpha) { node.WorldSpaceBoundingBox = boundingBox; } traverseList.Add(node); state.RenderMode = origRenderMode; } return(renderAction.TraverseState); }
/// <summary> /// Returns either a new or previously used TraverseNode for use by IRenderObject's /// Traverse(). The caller must place this node on the traverse list and not maintain /// a permanent reference to it.</summary> /// <returns>Either a new or previously used TraverseNode</returns> public TraverseNode GetUnusedNode() { TraverseNode node; if (m_nextUnusedNode < m_nodePool.Count) { node = m_nodePool[m_nextUnusedNode]; } else { node = new TraverseNode(); m_nodePool.Add(node); } m_nextUnusedNode++; return(node); }
private HitRecord[] PopulateOpenGlSelection(ICollection<TraverseNode> traverseList) { // Ensure that OpenGL is in correct state. double[] viewMat = null; double[] projectionMat = null; int[] viewport = null; if (m_frustumPick == false) { Gl.glViewport(0, 0, m_width, m_height); Gl.glMatrixMode(Gl.GL_PROJECTION); Gl.glLoadIdentity(); Util3D.glMultMatrixf(m_projectionMatrix); Gl.glMatrixMode(Gl.GL_MODELVIEW); Gl.glLoadIdentity(); Util3D.glMultMatrixf(m_viewMatrix); viewMat = new double[16]; Gl.glGetDoublev(Gl.GL_MODELVIEW_MATRIX, viewMat); projectionMat = new double[16]; Gl.glGetDoublev(Gl.GL_PROJECTION_MATRIX, projectionMat); viewport = new int[4]; viewport[0] = viewport[1] = 0; viewport[2] = m_width; viewport[3] = m_height; } // Construct traverse array HitRecord[] selection = null; List<HitRecord> selectionList = new List<HitRecord>(); TraverseNode[] travArray = new TraverseNode[traverseList.Count]; traverseList.CopyTo(travArray, 0); uint start = 0; for (int i = 0; i < m_openGlHits; ++i) { uint nameCount = (uint)m_selectionBuffer[start]; if (nameCount > 0) { uint travNodeIndex = (uint)m_selectionBuffer[start + 3]; TraverseNode travNode = travArray[travNodeIndex]; HitRecord hitRecord; if (m_frustumPick) { hitRecord = new HitRecord( travNode.GraphPath, travNode.RenderObject, new Matrix4F(travNode.Transform), new uint[nameCount - 1]); } else { hitRecord = new HitRecord( travNode.GraphPath, travNode.RenderObject, new Matrix4F(travNode.Transform), new uint[nameCount - 1]); // Transform screen to world and record world-space intersection point. float zMin = ((float)((uint)m_selectionBuffer[start + 1])) / 0xFFFFFFFF; Vec3F intersectionPt = GetWorldIntersectionFromScreen( m_x, m_y, zMin, viewMat, projectionMat, viewport); hitRecord.WorldIntersection = intersectionPt; } // Populate object data for (uint j = 0; j < nameCount - 1; j++) { hitRecord.RenderObjectData[j] = (uint)m_selectionBuffer[start + 4 + j]; } selectionList.Add(hitRecord); start += 3 + nameCount; } } selection = new HitRecord[selectionList.Count]; selectionList.CopyTo(selection, 0); return selection; }
/// <summary> /// Returns either a new or previously used TraverseNode for use by IRenderObject's /// Traverse(). The caller must place this node on the traverse list and not maintain /// a permanent reference to it.</summary> /// <returns>Either a new or previously used TraverseNode</returns> public TraverseNode GetUnusedNode() { TraverseNode node; if (m_nextUnusedNode < m_nodePool.Count) { node = m_nodePool[m_nextUnusedNode]; } else { node = new TraverseNode(); m_nodePool.Add(node); } m_nextUnusedNode++; return node; }
private HitRecord[] PopulateOpenGlSelection(ICollection <TraverseNode> traverseList) { // Ensure that OpenGL is in correct state. double[] viewMat = null; double[] projectionMat = null; int[] viewport = null; if (m_frustumPick == false) { Gl.glViewport(0, 0, m_width, m_height); Gl.glMatrixMode(Gl.GL_PROJECTION); Gl.glLoadIdentity(); Util3D.glMultMatrixf(m_projectionMatrix); Gl.glMatrixMode(Gl.GL_MODELVIEW); Gl.glLoadIdentity(); Util3D.glMultMatrixf(m_viewMatrix); viewMat = new double[16]; Gl.glGetDoublev(Gl.GL_MODELVIEW_MATRIX, viewMat); projectionMat = new double[16]; Gl.glGetDoublev(Gl.GL_PROJECTION_MATRIX, projectionMat); viewport = new int[4]; viewport[0] = viewport[1] = 0; viewport[2] = m_width; viewport[3] = m_height; } // Construct traverse array HitRecord[] selection = null; List <HitRecord> selectionList = new List <HitRecord>(); TraverseNode[] travArray = new TraverseNode[traverseList.Count]; traverseList.CopyTo(travArray, 0); uint start = 0; for (int i = 0; i < m_openGlHits; ++i) { uint nameCount = (uint)m_selectionBuffer[start]; if (nameCount > 0) { uint travNodeIndex = (uint)m_selectionBuffer[start + 3]; TraverseNode travNode = travArray[travNodeIndex]; HitRecord hitRecord; if (m_frustumPick) { hitRecord = new HitRecord( travNode.GraphPath, travNode.RenderObject, new Matrix4F(travNode.Transform), new uint[nameCount - 1]); } else { hitRecord = new HitRecord( travNode.GraphPath, travNode.RenderObject, new Matrix4F(travNode.Transform), new uint[nameCount - 1]); // Transform screen to world and record world-space intersection point. float zMin = ((float)((uint)m_selectionBuffer[start + 1])) / 0xFFFFFFFF; Vec3F intersectionPt = GetWorldIntersectionFromScreen( m_x, m_y, zMin, viewMat, projectionMat, viewport); hitRecord.WorldIntersection = intersectionPt; } // Populate object data for (uint j = 0; j < nameCount - 1; j++) { hitRecord.RenderObjectData[j] = (uint)m_selectionBuffer[start + 4 + j]; } selectionList.Add(hitRecord); start += 3 + nameCount; } } selection = new HitRecord[selectionList.Count]; selectionList.CopyTo(selection, 0); return(selection); }