/// <summary> /// Recursive render function for drawing normals with a constant size. /// </summary> /// <param name="node"></param> /// <param name="visibleMeshesByNode"></param> /// <param name="flags"></param> /// <param name="invGlobalScale"></param> /// <param name="animated"></param> /// <param name="transform"></param> private void RecursiveRenderNormals(Node node, Dictionary <Node, List <Mesh> > visibleMeshesByNode, RenderFlags flags, float invGlobalScale, bool animated, Matrix4 transform, int currDispList) { // TODO unify our use of OpenTK and Assimp matrices Matrix4 mConv; if (animated) { Owner.SceneAnimator.GetLocalTransform(node, out mConv); } else { Matrix4x4 m = node.Transform; mConv = AssimpToOpenTk.FromMatrix(ref m); } mConv.Transpose(); // The normal's position and direction are transformed differently, so we manually track the transform. transform = mConv * transform; if (flags.HasFlag(RenderFlags.ShowNormals)) { List <Mesh> meshList = null; if (node.HasMeshes && (visibleMeshesByNode == null || visibleMeshesByNode.TryGetValue(node, out meshList))) { foreach (var index in node.MeshIndices) { var mesh = Owner.Raw.Meshes[index]; if (meshList != null && !meshList.Contains(mesh)) { continue; } if (currDispList == GetDispList(node.Name)) { OverlayNormals.DrawNormals(node, index, mesh, mesh.HasBones && animated ? Skinner : null, invGlobalScale, transform); } } } } for (int i = 0; i < node.ChildCount; i++) { RecursiveRenderNormals(node.Children[i], visibleMeshesByNode, flags, invGlobalScale, animated, transform, currDispList); } }
/// <summary> /// Recursive render function for drawing opaque geometry with no scaling /// in the transformation chain. This is used for overlays, such as drawing /// normal vectors or the skeleton. /// </summary> /// <param name="node"></param> /// <param name="visibleMeshesByNode"></param> /// <param name="flags"></param> /// <param name="invGlobalScale"></param> /// <param name="animated"></param> private void RecursiveRenderNoScale(Node node, Dictionary <Node, List <Mesh> > visibleMeshesByNode, RenderFlags flags, float invGlobalScale, bool animated) { // TODO unify our use of OpenTK and Assimp matrices Matrix4x4 m; Matrix4 mConv; if (animated) { Owner.SceneAnimator.GetLocalTransform(node, out mConv); OpenTkToAssimp.FromMatrix(ref mConv, out m); } else { m = node.Transform; } // get rid of the scaling part of the matrix // TODO this can be done faster and Decompose() doesn't handle // non positively semi-definite matrices correctly anyway. Vector3D scaling; Assimp.Quaternion rotation; Vector3D translation; m.Decompose(out scaling, out rotation, out translation); rotation.Normalize(); m = new Matrix4x4(rotation.GetMatrix()) * Matrix4x4.FromTranslation(translation); mConv = AssimpToOpenTk.FromMatrix(ref m); mConv.Transpose(); if (flags.HasFlag(RenderFlags.ShowSkeleton)) { var highlight = false; if (visibleMeshesByNode != null) { List <Mesh> meshList; if (visibleMeshesByNode.TryGetValue(node, out meshList) && meshList == null) { // If the user hovers over a node in the tab view, all of its descendants // are added to the visible set as well. This is not the intended // behavior for skeleton joints, though! Here we only want to show the // joint corresponding to the node being hovered over. // Therefore, only highlight nodes whose parents either don't exist // or are not in the visible set. if (node.Parent == null || !visibleMeshesByNode.TryGetValue(node.Parent, out meshList) || meshList != null) { highlight = true; } } } OverlaySkeleton.DrawSkeletonBone(node, invGlobalScale, highlight); } GL.PushMatrix(); GL.MultMatrix(ref mConv); if (flags.HasFlag(RenderFlags.ShowNormals)) { List <Mesh> meshList = null; if (node.HasMeshes && (visibleMeshesByNode == null || visibleMeshesByNode.TryGetValue(node, out meshList))) { foreach (var index in node.MeshIndices) { var mesh = Owner.Raw.Meshes[index]; if (meshList != null && !meshList.Contains(mesh)) { continue; } OverlayNormals.DrawNormals(node, index, mesh, mesh.HasBones && animated ? Skinner : null, invGlobalScale); } } } for (int i = 0; i < node.ChildCount; i++) { RecursiveRenderNoScale(node.Children[i], visibleMeshesByNode, flags, invGlobalScale, animated); } GL.PopMatrix(); }