public AStarNode(double latestCosts, double costsToEnd, MeshNode node, AStarNode precedent) { mLatestCosts = latestCosts; mCostsToEnd = costsToEnd; mNode = node; mPrecedent = precedent; }
int GetBox ( MeshNode node ) { if ( count >= arr.Length ) EnsureCapacity ( count+1 ); arr[count] = new BBTreeBox ( node ); count++; return count-1; }
static void exportBone(BinaryWriter dest, MeshNode target, Assimp.Scene scene, int boneID) { Assimp.Node node = target.node; exportString(dest, node.Name); if (node.Parent!=null) exportString(dest, node.Parent.Name); else exportString(dest, ""); Matrix4x4 mat = new Matrix4x4(node.Transform.A1, node.Transform.A2, node.Transform.A3, node.Transform.A4, node.Transform.B1, node.Transform.B2, node.Transform.B3, node.Transform.B4, node.Transform.C1, node.Transform.C2, node.Transform.C3, node.Transform.C4, node.Transform.D1, node.Transform.D2, node.Transform.D3, node.Transform.D4); mat.Transpose(); exportMatrix(dest, mat); Bone bone = target.bone; if (bone != null) { mat = new Matrix4x4(bone.OffsetMatrix.A1, bone.OffsetMatrix.A2, bone.OffsetMatrix.A3, bone.OffsetMatrix.A4, bone.OffsetMatrix.B1, bone.OffsetMatrix.B2, bone.OffsetMatrix.B3, bone.OffsetMatrix.B4, bone.OffsetMatrix.C1, bone.OffsetMatrix.C2, bone.OffsetMatrix.C3, bone.OffsetMatrix.C4, bone.OffsetMatrix.D1, bone.OffsetMatrix.D2, bone.OffsetMatrix.D3, bone.OffsetMatrix.D4); mat.Transpose(); } else mat = Matrix4x4.Identity; exportMatrix(dest, mat); }
/** Rebuilds the tree using the specified nodes. * This is faster and gives better quality results compared to calling Insert with all nodes */ public void RebuildFrom (MeshNode[] nodes) { Clear(); if (nodes.Length == 0) { return; } if (nodes.Length == 1) { GetBox(nodes[0]); return; } // We will use approximately 2N tree nodes EnsureCapacity(Mathf.CeilToInt (nodes.Length * 2.1f)); // Make a copy of the nodes array since we will be modifying it var nodeCopies = new MeshNode[nodes.Length]; for (int i = 0; i < nodes.Length; i++) nodeCopies[i] = nodes[i]; RebuildFromInternal(nodeCopies, 0, nodes.Length, false); }
public BBTreeBox (MeshNode node) { this.node = node; var first = node.GetVertex(0); var min = new Int2(first.x,first.z); Int2 max = min; for (int i=1;i<node.GetVertexCount();i++) { var p = node.GetVertex(i); min.x = Math.Min (min.x,p.x); min.y = Math.Min (min.y,p.z); max.x = Math.Max (max.x,p.x); max.y = Math.Max (max.y,p.z); } rect = new IntRect (min.x,min.y,max.x,max.y); left = right = -1; }
static bool NodeIntersectsCircle (MeshNode node, Vector3 p, float radius) { if (float.IsPositiveInfinity(radius)) return true; /** \bug Is not correct on the Y axis */ return (p - node.ClosestPointOnNode (p)).sqrMagnitude < radius*radius; }
/** Calculates the bounding box in XZ space of all nodes between \a from (inclusive) and \a to (exclusive) */ static IntRect NodeBounds (MeshNode[] nodes, int from, int to) { if (to - from <= 0) throw new ArgumentException(); var first = nodes[from].GetVertex(0); var min = new Int2(first.x,first.z); Int2 max = min; for (int j = from; j < to; j++) { var node = nodes[j]; var nverts = node.GetVertexCount(); for (int i = 0; i < nverts; i++) { var p = node.GetVertex(i); min.x = Math.Min (min.x, p.x); min.y = Math.Min (min.y, p.z); max.x = Math.Max (max.x, p.x); max.y = Math.Max (max.y, p.z); } } return new IntRect (min.x, min.y, max.x, max.y); }
public void InternalOnPostScan () { #if !ASTAR_NO_POINT_GRAPH if ( AstarPath.active.astarData.pointGraph == null ) { AstarPath.active.astarData.AddGraph ( new PointGraph () ); } //Get nearest nodes from the first point graph, assuming both start and end transforms are nodes startNode = AstarPath.active.astarData.pointGraph.AddNode ( new NodeLink3Node(AstarPath.active), (Int3)StartTransform.position );//AstarPath.active.astarData.pointGraph.GetNearest(StartTransform.position).node as PointNode; startNode.link = this; endNode = AstarPath.active.astarData.pointGraph.AddNode ( new NodeLink3Node(AstarPath.active), (Int3)EndTransform.position ); //AstarPath.active.astarData.pointGraph.GetNearest(EndTransform.position).node as PointNode; endNode.link = this; #else throw new System.Exception ("Point graphs are not included. Check your A* Optimization settings."); #endif connectedNode1 = null; connectedNode2 = null; if (startNode == null || endNode == null) { startNode = null; endNode = null; return; } postScanCalled = true; reference[startNode] = this; reference[endNode] = this; Apply( true ); }
private Ragdoll CreateRagdoll(MeshNode meshNode) { var mesh = meshNode.Mesh; var skeleton = mesh.Skeleton; // Extract the vertices from the mesh sorted per bone. var verticesPerBone = new List <Vector3> [skeleton.NumberOfBones]; // Also get the AABB of the model. Aabb?aabb = null; foreach (var submesh in mesh.Submeshes) { // Get vertex element info. var vertexDeclaration = submesh.VertexBuffer.VertexDeclaration; var vertexElements = vertexDeclaration.GetVertexElements(); // Get the vertex positions. var positionElement = vertexElements.First(e => e.VertexElementUsage == VertexElementUsage.Position); if (positionElement.VertexElementFormat != VertexElementFormat.Vector3) { throw new NotSupportedException("For vertex positions only VertexElementFormat.Vector3 is supported."); } var positions = new Vector3[submesh.VertexCount]; submesh.VertexBuffer.GetData( submesh.StartVertex * vertexDeclaration.VertexStride + positionElement.Offset, positions, 0, submesh.VertexCount, vertexDeclaration.VertexStride); // Get the bone indices. var boneIndexElement = vertexElements.First(e => e.VertexElementUsage == VertexElementUsage.BlendIndices); if (boneIndexElement.VertexElementFormat != VertexElementFormat.Byte4) { throw new NotSupportedException(); } var boneIndicesArray = new Byte4[submesh.VertexCount]; submesh.VertexBuffer.GetData( submesh.StartVertex * vertexDeclaration.VertexStride + boneIndexElement.Offset, boneIndicesArray, 0, submesh.VertexCount, vertexDeclaration.VertexStride); // Get the bone weights. var boneWeightElement = vertexElements.First(e => e.VertexElementUsage == VertexElementUsage.BlendWeight); if (boneWeightElement.VertexElementFormat != VertexElementFormat.Vector4) { throw new NotSupportedException(); } var boneWeightsArray = new Vector4[submesh.VertexCount]; submesh.VertexBuffer.GetData( submesh.StartVertex * vertexDeclaration.VertexStride + boneWeightElement.Offset, boneWeightsArray, 0, submesh.VertexCount, vertexDeclaration.VertexStride); // Sort the vertices per bone. for (int i = 0; i < submesh.VertexCount; i++) { var vertex = (Vector3)positions[i]; // Here, we only check the first bone index. We could also check the // bone weights to add the vertex to all bone vertex lists where the // weight is high... Vector4 boneIndices = boneIndicesArray[i].ToVector4(); //Vector4 boneWeights = boneWeightsArray[i]; int boneIndex = (int)boneIndices.X; if (verticesPerBone[boneIndex] == null) { verticesPerBone[boneIndex] = new List <Vector3>(); } verticesPerBone[boneIndex].Add(vertex); // Add vertex to AABB. if (aabb == null) { aabb = new Aabb(vertex, vertex); } else { aabb.Value.Grow(vertex); } } } // We create a body for each bone with vertices. int numberOfBodies = verticesPerBone.Count(vertices => vertices != null); // We use the same mass properties for all bodies. This is not realistic but more stable // because large mass differences or thin bodies (arms!) are less stable. // We use the mass properties of sphere proportional to the size of the model. const float totalMass = 80; // The total mass of the ragdoll. var massFrame = MassFrame.FromShapeAndMass(new SphereShape(aabb.Value.Extent.Y / 8), Vector3.One, totalMass / numberOfBodies, 0.1f, 1); var material = new UniformMaterial(); Ragdoll ragdoll = new Ragdoll(); for (int boneIndex = 0; boneIndex < skeleton.NumberOfBones; boneIndex++) { var boneVertices = verticesPerBone[boneIndex]; if (boneVertices != null) { var bindPoseInverse = (Pose)skeleton.GetBindPoseAbsoluteInverse(boneIndex); // Compute bounding capsule. //float radius; //float height; //Pose pose; //GeometryHelper.ComputeBoundingCapsule(boneVertices, out radius, out height, out pose); //Shape shape = new TransformedShape(new GeometricObject(new CapsuleShape(radius, height), pose)); // Compute convex hull. var points = GeometryHelper.CreateConvexHull(boneVertices, 32, 0).ToTriangleMesh().Vertices; Shape shape = new ConvexHullOfPoints(points.Count > 0 ? points : boneVertices); ragdoll.Bodies.Add(new RigidBody(shape, massFrame, material)); ragdoll.BodyOffsets.Add(bindPoseInverse); } else { ragdoll.Bodies.Add(null); ragdoll.BodyOffsets.Add(Pose.Identity); } } return(ragdoll); }
public void Apply ( bool forceNewCheck ) { //TODO //This function assumes that connections from the n1,n2 nodes never need to be removed in the future (e.g because the nodes move or something) NNConstraint nn = NNConstraint.None; nn.distanceXZ = true; int graph = (int)startNode.GraphIndex; //Search all graphs but the one which start and end nodes are on nn.graphMask = ~(1 << graph); bool same = true; if (true) { NNInfo n1 = AstarPath.active.GetNearest(StartTransform.position, nn); same &= n1.node == connectedNode1 && n1.node != null; connectedNode1 = n1.node as MeshNode; clamped1 = n1.clampedPosition; if ( connectedNode1 != null ) Debug.DrawRay ( (Vector3)connectedNode1.position, Vector3.up*5,Color.red); } if (true) { NNInfo n2 = AstarPath.active.GetNearest(EndTransform.position, nn); same &= n2.node == connectedNode2 && n2.node != null; connectedNode2 = n2.node as MeshNode; clamped2 = n2.clampedPosition; if ( connectedNode2 != null ) Debug.DrawRay ( (Vector3)connectedNode2.position, Vector3.up*5,Color.cyan); } if (connectedNode2 == null || connectedNode1 == null) return; startNode.SetPosition ( (Int3)StartTransform.position ); endNode.SetPosition ( (Int3)EndTransform.position ); if ( same && !forceNewCheck ) return; RemoveConnections(startNode); RemoveConnections(endNode); uint cost = (uint)Mathf.RoundToInt(((Int3)(StartTransform.position-EndTransform.position)).costMagnitude*costFactor); startNode.AddConnection (endNode, cost); endNode.AddConnection(startNode, cost); Int3 dir = connectedNode2.position - connectedNode1.position; for ( int a=0;a<connectedNode1.GetVertexCount();a++) { Int3 va1 = connectedNode1.GetVertex ( a ); Int3 va2 = connectedNode1.GetVertex ( (a+1) % connectedNode1.GetVertexCount() ); if ( Int3.DotLong ( (va2-va1).Normal2D (), dir ) > 0 ) continue; for ( int b=0;b<connectedNode2.GetVertexCount();b++) { Int3 vb1 = connectedNode2.GetVertex ( b ); Int3 vb2 = connectedNode2.GetVertex ( (b+1) % connectedNode2.GetVertexCount() ); if ( Int3.DotLong ( (vb2-vb1).Normal2D (), dir ) < 0 ) continue; //Debug.DrawLine ((Vector3)va1, (Vector3)va2, Color.magenta); //Debug.DrawLine ((Vector3)vb1, (Vector3)vb2, Color.cyan); //Debug.Break (); if ( Int3.Angle ( (vb2-vb1), (va2-va1) ) > (170.0/360.0f)*Mathf.PI*2 ) { float t1 = 0; float t2 = 1; t2 = System.Math.Min ( t2, AstarMath.NearestPointFactor ( va1, va2, vb1 ) ); t1 = System.Math.Max ( t1, AstarMath.NearestPointFactor ( va1, va2, vb2 ) ); if ( t2 < t1 ) { Debug.LogError ("Wait wut!? " + t1 + " " + t2 + " " + va1 + " " + va2 + " " + vb1 + " " + vb2+"\nTODO, fix this error" ); } else { Vector3 pa = (Vector3)(va2-va1)*t1 + (Vector3)va1; Vector3 pb = (Vector3)(va2-va1)*t2 + (Vector3)va1; startNode.portalA = pa; startNode.portalB = pb; endNode.portalA = pb; endNode.portalB = pa; //Enqueue connections between nodes, or replace old connections if existing connectedNode1.AddConnection(startNode, (uint)Mathf.RoundToInt (((Int3)(clamped1 - StartTransform.position)).costMagnitude*costFactor)); connectedNode2.AddConnection(endNode, (uint)Mathf.RoundToInt (((Int3)(clamped2 - EndTransform.position)).costMagnitude*costFactor)); startNode.AddConnection(connectedNode1, (uint)Mathf.RoundToInt (((Int3)(clamped1 - StartTransform.position)).costMagnitude*costFactor)); endNode.AddConnection(connectedNode2, (uint)Mathf.RoundToInt (((Int3)(clamped2 - EndTransform.position)).costMagnitude*costFactor)); return; } } } } }
public void Apply ( bool forceNewCheck ) { //TODO //This function assumes that connections from the n1,n2 nodes never need to be removed in the future (e.g because the nodes move or something) NNConstraint nn = NNConstraint.None; int graph = (int)startNode.GraphIndex; //Search all graphs but the one which start and end nodes are on nn.graphMask = ~(1 << graph); startNode.SetPosition ( (Int3)StartTransform.position ); endNode.SetPosition ( (Int3)EndTransform.position ); RemoveConnections(startNode); RemoveConnections(endNode); uint cost = (uint)Mathf.RoundToInt(((Int3)(StartTransform.position-EndTransform.position)).costMagnitude*costFactor); startNode.AddConnection (endNode, cost); endNode.AddConnection(startNode, cost); if (connectedNode1 == null || forceNewCheck) { NNInfo n1 = AstarPath.active.GetNearest(StartTransform.position, nn); connectedNode1 = n1.node as MeshNode; clamped1 = n1.clampedPosition; } if (connectedNode2 == null || forceNewCheck) { NNInfo n2 = AstarPath.active.GetNearest(EndTransform.position, nn); connectedNode2 = n2.node as MeshNode; clamped2 = n2.clampedPosition; } if (connectedNode2 == null || connectedNode1 == null) return; //Enqueue connections between nodes, or replace old connections if existing connectedNode1.AddConnection(startNode, (uint)Mathf.RoundToInt (((Int3)(clamped1 - StartTransform.position)).costMagnitude*costFactor)); if ( !oneWay ) connectedNode2.AddConnection(endNode, (uint)Mathf.RoundToInt (((Int3)(clamped2 - EndTransform.position)).costMagnitude*costFactor)); if ( !oneWay ) startNode.AddConnection(connectedNode1, (uint)Mathf.RoundToInt (((Int3)(clamped1 - StartTransform.position)).costMagnitude*costFactor)); endNode.AddConnection(connectedNode2, (uint)Mathf.RoundToInt (((Int3)(clamped2 - EndTransform.position)).costMagnitude*costFactor)); }
// Interpolate between to skeleton animation poses and apply the result to // the specified MeshNode. private static void InterpolatePose(MeshNode meshNode, SkeletonPose pose0, SkeletonPose pose1, float w) { var skeletonPose = meshNode.SkeletonPose; SkeletonPoseTraits.Instance.Interpolate(ref pose0, ref pose1, w, ref skeletonPose); }
public LookAtIKSample(Microsoft.Xna.Framework.Game game) : base(game) { var modelNode = ContentManager.Load <ModelNode>("Dude/Dude"); _meshNode = modelNode.GetSubtree().OfType <MeshNode>().First().Clone(); _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi)); SampleHelper.EnablePerPixelLighting(_meshNode); GraphicsScreen.Scene.Children.Add(_meshNode); var animations = _meshNode.Mesh.Animations; var loopingAnimation = new AnimationClip <SkeletonPose>(animations.Values.First()) { LoopBehavior = LoopBehavior.Cycle, Duration = TimeSpan.MaxValue, }; AnimationService.StartAnimation(loopingAnimation, (IAnimatableProperty)_meshNode.SkeletonPose); // Create LookAtIKSolvers for some spine bones, the neck and the head. _spine1IK = new LookAtIKSolver { SkeletonPose = _meshNode.SkeletonPose, BoneIndex = 3, // The bone space axis that points in look direction. Forward = Vector3F.UnitY, // The bone space axis that points in up direction Up = Vector3F.UnitX, // An arbitrary rotation limit. Limit = ConstantsF.PiOver4, // We use a weight of 1 for the head, and lower weights for all other bones. Thus, most // of the looking will be done by the head bone, and the influence on the other bones is // smaller. Weight = 0.2f, // It is important to set the EyeOffsets. If we do not set EyeOffsets, the IK solver // assumes that the eyes are positioned in the origin of the bone. // Approximate EyeOffsets are sufficient. EyeOffset = new Vector3F(0.8f, 0, 0), }; _spine2IK = new LookAtIKSolver { SkeletonPose = _meshNode.SkeletonPose, BoneIndex = 4, Forward = Vector3F.UnitY, Up = Vector3F.UnitX, Limit = ConstantsF.PiOver4, Weight = 0.2f, EyeOffset = new Vector3F(0.64f, 0, 0), }; _spine3IK = new LookAtIKSolver { SkeletonPose = _meshNode.SkeletonPose, BoneIndex = 5, Forward = Vector3F.UnitY, Up = Vector3F.UnitX, Limit = ConstantsF.PiOver4, Weight = 0.3f, EyeOffset = new Vector3F(0.48f, 0, 0), }; _neckIK = new LookAtIKSolver { SkeletonPose = _meshNode.SkeletonPose, BoneIndex = 6, Forward = Vector3F.UnitY, Up = Vector3F.UnitX, Limit = ConstantsF.PiOver4, Weight = 0.4f, EyeOffset = new Vector3F(0.32f, 0, 0), }; _headIK = new LookAtIKSolver { SkeletonPose = _meshNode.SkeletonPose, BoneIndex = 7, Forward = Vector3F.UnitY, Up = Vector3F.UnitX, EyeOffset = new Vector3F(0.16f, 0.16f, 0), Weight = 1.0f, Limit = ConstantsF.PiOver4, }; }
public override void OnGraphsPostUpdate () { //if (connectedNode1 != null && connectedNode2 != null) { if (!AstarPath.active.isScanning) { if (connectedNode1 != null && connectedNode1.Destroyed) { connectedNode1 = null; } if (connectedNode2 != null && connectedNode2.Destroyed) { connectedNode2 = null; } if (!postScanCalled) { OnPostScan(); } else { //OnPostScan will also call this method /** \todo Can mess up pathfinding, wrap in delegate */ Apply( false ); } } }
protected override void OnLoad() { var contentManager = _services.GetInstance <ContentManager>(); var scene = _services.GetInstance <IScene>(); _debugRenderer = _services.GetInstance <DebugRenderer>(); // Load materials (*.drmat files) which define the used shaders and material // properties (e.g. textures, colors, etc.). var bloodMaterial = contentManager.Load <Material>("Decals/Blood"); var crackMaterial = contentManager.Load <Material>("Decals/Crack"); var bulletHoleMaterial = contentManager.Load <Material>("Decals/BulletHole"); // Decal materials (like materials of meshes) usually have several render passes // (such as "GBuffer", "Material"). Decal materials without a "Material" pass can // be used to render only normal maps without color changes: //crackMaterial.Remove("Material"); // Add some DecalNodes, which define where a material is projected onto the scene. var bloodDecal0 = new DecalNode(bloodMaterial); bloodDecal0.NormalThreshold = MathHelper.ToRadians(75); bloodDecal0.LookAt(new Vector3F(0.7f, 0.6f, 0.7f), new Vector3F(0.7f, 0.6f, 0), new Vector3F(0.1f, 1, 0)); bloodDecal0.Width = 1.1f; bloodDecal0.Height = 1.1f; bloodDecal0.Depth = 1; bloodDecal0.Options = DecalOptions.ProjectOnStatic; scene.Children.Add(bloodDecal0); _decals.Add(bloodDecal0); var bloodDecal1 = new DecalNode(bloodMaterial); bloodDecal1.LookAt(new Vector3F(0.0f, 0.2f, 1.9f), new Vector3F(0.0f, 0, 1.9f), new Vector3F(1.0f, 0, -0.5f)); bloodDecal1.Width = 1.6f; bloodDecal1.Height = 1.6f; bloodDecal1.Depth = 0.5f; scene.Children.Add(bloodDecal1); _decals.Add(bloodDecal1); var crackDecal0 = new DecalNode(crackMaterial); crackDecal0.NormalThreshold = MathHelper.ToRadians(75); crackDecal0.LookAt(new Vector3F(-0.7f, 0.7f, 0.7f), new Vector3F(-0.7f, 0.7f, 0), new Vector3F(0.1f, 1, 0)); crackDecal0.Width = 1.75f; crackDecal0.Height = 1.75f; crackDecal0.Depth = 0.6f; crackDecal0.Options = DecalOptions.ProjectOnStatic; scene.Children.Add(crackDecal0); _decals.Add(crackDecal0); var crackDecal1 = crackDecal0.Clone(); var position = new Vector3F(2.0f, 0.2f, 2.0f); crackDecal1.LookAt(position, position + new Vector3F(0, -1, 0), new Vector3F(-0.8f, 0, 1.0f)); crackDecal1.Width = 2.5f; crackDecal1.Height = 2.5f; crackDecal1.Depth = 0.5f; scene.Children.Add(crackDecal1); _decals.Add(crackDecal1); var bulletHole0 = new DecalNode(bulletHoleMaterial); bulletHole0.NormalThreshold = MathHelper.ToRadians(90); bulletHole0.LookAt(new Vector3F(0.0f, 0.8f, 0.7f), new Vector3F(0.0f, 0.7f, 0), new Vector3F(0.1f, -1, 0)); bulletHole0.Width = 0.20f; bulletHole0.Height = 0.20f; bulletHole0.Depth = 1f; bulletHole0.DrawOrder = 10; // Draw over other decals. scene.Children.Add(bulletHole0); _decals.Add(bulletHole0); var bulletHole1 = bulletHole0.Clone(); bulletHole1.LookAt(new Vector3F(-0.4f, 0.9f, 0.7f), new Vector3F(-0.4f, 0.9f, 0), new Vector3F(0.1f, 1, 0)); scene.Children.Add(bulletHole1); _decals.Add(bulletHole1); var bulletHole2 = bulletHole0.Clone(); bulletHole2.LookAt(new Vector3F(-0.2f, 0.8f, 0.7f), new Vector3F(-0.2f, 0.0f, 0), new Vector3F(0.1f, -1, 0)); scene.Children.Add(bulletHole2); _decals.Add(bulletHole2); var bulletHole3 = bulletHole0.Clone(); bulletHole3.LookAt(new Vector3F(3.0f, 1.0f, 2.0f), new Vector3F(3.0f, 1.0f, 1), new Vector3F(0.3f, 1, 0)); scene.Children.Add(bulletHole3); _decals.Add(bulletHole3); var bulletHole4 = bulletHole0.Clone(); bulletHole4.LookAt(new Vector3F(2.5f, 0.7f, 2.0f), new Vector3F(3.0f, 0.7f, 1.0f), new Vector3F(-0.1f, -1, 0)); scene.Children.Add(bulletHole4); _decals.Add(bulletHole4); var bulletHole5 = bulletHole0.Clone(); bulletHole5.LookAt(new Vector3F(2.7f, 1.2f, 2.0f), new Vector3F(3.0f, 1.2f, 1.0f), new Vector3F(-0.5f, -1, 0)); scene.Children.Add(bulletHole5); _decals.Add(bulletHole5); var bulletHole6 = bulletHole0.Clone(); bulletHole6.LookAt(new Vector3F(3.2f, 0.4f, 2.0f), new Vector3F(3.0f, 0.4f, 1), new Vector3F(-0.3f, -0.5f, 0)); scene.Children.Add(bulletHole6); _decals.Add(bulletHole6); // Get the first dynamic mesh (the rusty cube) and add a decal as a child. MeshNode meshNode = ((Scene)scene).GetSubtree().OfType <MeshNode>().First(n => !n.IsStatic); var bulletHole7 = bulletHole0.Clone(); bulletHole7.LookAt(new Vector3F(0, 0, -0.6f), new Vector3F(0, 0, 0), new Vector3F(0, 1, 0)); bulletHole7.Depth = 0.2f; meshNode.Children = new SceneNodeCollection { bulletHole7 }; _decals.Add(bulletHole7); }
public MeshTri(MeshNode a, MeshNode b, MeshNode c) { this.a = a; this.b = b; this.c = c; }
/// <summary> /// Computes the intersection of <see cref="MeshNode"/>s. /// </summary> /// <param name="meshNodePairs"> /// A collection of <see cref="MeshNode"/> pairs.The renderer computes the intersection volume /// of each pair. /// </param> /// <param name="color">The diffuse color used for the intersection.</param> /// <param name="alpha">The opacity of the intersection.</param> /// <param name="maxConvexity"> /// The maximum convexity of the submeshes. A convex mesh has a convexity of 1. A concave mesh /// has a convexity greater than 1. Convexity is the number of layers required for depth peeling /// (= the number of front face layers when looking at the object). /// </param> /// <param name="context">The render context.</param> /// <remarks> /// <para> /// This method renders an off-screen image (color and depth) of the intersection volume. This /// operation destroys the currently set render target and depth/stencil buffer. /// </para> /// </remarks> /// <exception cref="ObjectDisposedException"> /// The <see cref="IntersectionRenderer"/> has already been disposed. /// </exception> /// <exception cref="ArgumentNullException"> /// <paramref name="meshNodePairs"/> or <see cref="context"/> is /// <see langword="null"/>. /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// The convexity must be greater than 0. /// </exception> /// <exception cref="GraphicsException"> /// Invalid render context: Graphics service is not set. /// </exception> /// <exception cref="GraphicsException"> /// Invalid render context: Wrong graphics device. /// </exception> /// <exception cref="GraphicsException"> /// Invalid render context: Scene is not set. /// </exception> /// <exception cref="GraphicsException"> /// Invalid render context: Camera node needs to be set in render context. /// </exception> public void ComputeIntersection(IEnumerable <Pair <MeshNode> > meshNodePairs, Vector3 color, float alpha, float maxConvexity, RenderContext context) { if (_isDisposed) { throw new ObjectDisposedException("IntersectionRenderer has already been disposed."); } if (meshNodePairs == null) { throw new ArgumentNullException("meshNodePairs"); } if (maxConvexity < 1) { throw new ArgumentOutOfRangeException("maxConvexity", "The max convexity must be greater than 0."); } if (context == null) { throw new ArgumentNullException("context"); } if (context.GraphicsService == null) { throw new GraphicsException("Invalid render context: Graphics service is not set."); } if (_graphicsService != context.GraphicsService) { throw new GraphicsException("Invalid render context: Wrong graphics service."); } if (context.CameraNode == null) { throw new GraphicsException("Camera node needs to be set in render context."); } if (context.Scene == null) { throw new GraphicsException("A scene needs to be set in the render context."); } // Create 2 ordered pairs for each unordered pair. _pairs.Clear(); foreach (var pair in meshNodePairs) { if (pair.First == null || pair.Second == null) { continue; } // Frustum culling. if (!context.Scene.HaveContact(pair.First, context.CameraNode)) { continue; } if (!context.Scene.HaveContact(pair.Second, context.CameraNode)) { continue; } _pairs.Add(new Pair <MeshNode, MeshNode>(pair.First, pair.Second)); _pairs.Add(new Pair <MeshNode, MeshNode>(pair.Second, pair.First)); } var renderTargetPool = _graphicsService.RenderTargetPool; if (_pairs.Count == 0) { renderTargetPool.Recycle(_intersectionImage); _intersectionImage = null; return; } // Color and alpha are applied in RenderIntersection(). _color = color; _alpha = alpha; var graphicsDevice = _graphicsService.GraphicsDevice; // Save original render states. var originalBlendState = graphicsDevice.BlendState; var originalDepthStencilState = graphicsDevice.DepthStencilState; var originalRasterizerState = graphicsDevice.RasterizerState; var originalScissorRectangle = graphicsDevice.ScissorRectangle; // Get offscreen render targets. var viewport = context.Viewport; viewport.X = 0; viewport.Y = 0; viewport.Width = (int)(viewport.Width / DownsampleFactor); viewport.Height = (int)(viewport.Height / DownsampleFactor); var renderTargetFormat = new RenderTargetFormat(viewport.Width, viewport.Height, false, SurfaceFormat.Color, DepthFormat.Depth24Stencil8); // Try to reuse any existing render targets. // (Usually they are recycled in RenderIntersection()). var currentScene = _intersectionImage; if (currentScene == null || !renderTargetFormat.IsCompatibleWith(currentScene)) { currentScene.SafeDispose(); currentScene = renderTargetPool.Obtain2D(renderTargetFormat); } var lastScene = renderTargetPool.Obtain2D(renderTargetFormat); // Set shared effect parameters. var cameraNode = context.CameraNode; var view = (Matrix)cameraNode.View; var projection = cameraNode.Camera.Projection; var near = projection.Near; var far = projection.Far; _parameterViewportSize.SetValue(new Vector2(viewport.Width, viewport.Height)); // The DepthEpsilon has to be tuned if depth peeling does not work because // of numerical problems equality z comparisons. _parameterCameraParameters.SetValue(new Vector3(near, far - near, 0.0000001f)); _parameterView.SetValue(view); _parameterProjection.SetValue((Matrix)projection); var defaultTexture = _graphicsService.GetDefaultTexture2DBlack(); // Handle all pairs. bool isFirstPass = true; while (true) { // Find a mesh node A and all mesh nodes to which it needs to be clipped. MeshNode meshNodeA = null; _partners.Clear(); for (int i = 0; i < _pairs.Count; i++) { var pair = _pairs[i]; if (pair.First == null) { continue; } if (meshNodeA == null) { meshNodeA = pair.First; } if (pair.First == meshNodeA) { _partners.Add(pair.Second); // Remove this pair. _pairs[i] = new Pair <MeshNode, MeshNode>(); } } // Abort if we have handled all pairs. if (meshNodeA == null) { break; } var worldTransformA = (Matrix)(meshNodeA.PoseWorld * Matrix.CreateScale(meshNodeA.ScaleWorld)); if (EnableScissorTest) { // Scissor rectangle of A. var scissorA = GraphicsHelper.GetScissorRectangle(context.CameraNode, viewport, meshNodeA); // Union of scissor rectangles of partners. Rectangle partnerRectangle = GraphicsHelper.GetScissorRectangle(context.CameraNode, viewport, _partners[0]); for (int i = 1; i < _partners.Count; i++) { var a = GraphicsHelper.GetScissorRectangle(context.CameraNode, viewport, _partners[i]); partnerRectangle = Rectangle.Union(partnerRectangle, a); } // Use intersection of A and partners. graphicsDevice.ScissorRectangle = Rectangle.Intersect(scissorA, partnerRectangle); // We store the union of all scissor rectangles for use in RenderIntersection(). if (isFirstPass) { _totalScissorRectangle = graphicsDevice.ScissorRectangle; } else { _totalScissorRectangle = Rectangle.Union(_totalScissorRectangle, graphicsDevice.ScissorRectangle); } } // Depth peeling of A. for (int layer = 0; layer < maxConvexity; layer++) { // Set and clear render target. graphicsDevice.SetRenderTarget(currentScene); graphicsDevice.Clear(new Color(1, 1, 1, 0)); // RGB = "a large depth", A = "empty area" // Render a depth layer of A. graphicsDevice.DepthStencilState = DepthStencilStateWriteLess; graphicsDevice.BlendState = BlendState.Opaque; graphicsDevice.RasterizerState = EnableScissorTest ? CullCounterClockwiseScissor : RasterizerState.CullCounterClockwise; _parameterWorld.SetValue(worldTransformA); _parameterTexture.SetValue((layer == 0) ? defaultTexture : lastScene); _passPeel.Apply(); foreach (var submesh in meshNodeA.Mesh.Submeshes) { submesh.Draw(); } // Render partners to set stencil. graphicsDevice.DepthStencilState = DepthStencilStateOnePassStencilFail; graphicsDevice.BlendState = BlendStateNoWrite; graphicsDevice.RasterizerState = EnableScissorTest ? CullNoneScissor : RasterizerState.CullNone; foreach (var partner in _partners) { _parameterWorld.SetValue((Matrix)(partner.PoseWorld * Matrix.CreateScale(partner.ScaleWorld))); _passMark.Apply(); foreach (var submesh in partner.Mesh.Submeshes) { submesh.Draw(); } } // Clear depth buffer. Leave stencil buffer unchanged. graphicsDevice.Clear(ClearOptions.DepthBuffer, new Color(0, 1, 0), 1, 0); // Render A to compute lighting. graphicsDevice.DepthStencilState = DepthStencilStateStencilNotEqual0; graphicsDevice.BlendState = BlendState.Opaque; graphicsDevice.RasterizerState = EnableScissorTest ? CullCounterClockwiseScissor : RasterizerState.CullCounterClockwise; _parameterWorld.SetValue(worldTransformA); _passDraw.Apply(); foreach (var submesh in meshNodeA.Mesh.Submeshes) { submesh.Draw(); } // Combine last intersection image with current. if (!isFirstPass) { graphicsDevice.DepthStencilState = DepthStencilState.DepthRead; graphicsDevice.BlendState = BlendState.Opaque; graphicsDevice.RasterizerState = EnableScissorTest ? CullNoneScissor : RasterizerState.CullNone; _parameterTexture.SetValue(lastScene); _passCombine.Apply(); graphicsDevice.DrawFullScreenQuad(); } isFirstPass = false; // ----- Swap render targets. MathHelper.Swap(ref lastScene, ref currentScene); } } // Store final images for RenderIntersection. _intersectionImage = lastScene; // Scale scissor rectangle back to full-screen resolution. if (DownsampleFactor > 1) { _totalScissorRectangle.X = (int)(_totalScissorRectangle.X * DownsampleFactor); _totalScissorRectangle.Y = (int)(_totalScissorRectangle.Y * DownsampleFactor); _totalScissorRectangle.Width = (int)(_totalScissorRectangle.Width * DownsampleFactor); _totalScissorRectangle.Height = (int)(_totalScissorRectangle.Height * DownsampleFactor); } // Restore original render state. graphicsDevice.BlendState = originalBlendState ?? BlendState.Opaque; graphicsDevice.DepthStencilState = originalDepthStencilState ?? DepthStencilState.Default; graphicsDevice.RasterizerState = originalRasterizerState ?? RasterizerState.CullCounterClockwise; graphicsDevice.ScissorRectangle = originalScissorRectangle; renderTargetPool.Recycle(currentScene); _partners.Clear(); _pairs.Clear(); }
public ActiveRagdollSample(Microsoft.Xna.Framework.Game game) : base(game) { GraphicsScreen.DrawReticle = true; // Add game objects which allow to shoot balls and grab rigid bodies. _ballShooterObject = new BallShooterObject(Services) { Speed = 10 }; GameObjectService.Objects.Add(_ballShooterObject); _grabObject = new GrabObject(Services); GameObjectService.Objects.Add(_grabObject); var modelNode = ContentManager.Load <ModelNode>("Dude/Dude"); _meshNode = modelNode.GetSubtree().OfType <MeshNode>().First().Clone(); _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0)); SampleHelper.EnablePerPixelLighting(_meshNode); GraphicsScreen.Scene.Children.Add(_meshNode); // Create a copy of the dude's skeleton. _targetSkeletonPose = SkeletonPose.Create(_meshNode.Mesh.Skeleton); // Animate the _targetSkeletonPose. var animations = _meshNode.Mesh.Animations; var loopingAnimation = new AnimationClip <SkeletonPose>(animations.Values.First()) { LoopBehavior = LoopBehavior.Cycle, Duration = TimeSpan.MaxValue, }; AnimationService.StartAnimation(loopingAnimation, (IAnimatableProperty)_targetSkeletonPose); // Create a ragdoll for the Dude model. _ragdoll = new Ragdoll(); DudeRagdollCreator.Create(_targetSkeletonPose, _ragdoll, Simulation, 0.571f); // Set the world space pose of the whole ragdoll. And copy the bone poses of the // current skeleton pose. _ragdoll.Pose = _meshNode.PoseWorld; _ragdoll.UpdateBodiesFromSkeleton(_targetSkeletonPose); // In this sample we use an active ragdoll. We need joints because constraint ragdoll // motors only affect the body rotations. _ragdoll.EnableJoints(); // We disable limits. If limits are enabled, the ragdoll could get unstable if // the animation tries to move a limb beyond an allowed limit. (This happens if // a pose in the animation violates one of our limits.) _ragdoll.DisableLimits(); // Set all motors to constraint motors. Constraint motors are like springs that // rotate the limbs to a target position. foreach (RagdollMotor motor in _ragdoll.Motors) { if (motor != null) { motor.Mode = RagdollMotorMode.Constraint; motor.ConstraintDamping = 10000; motor.ConstraintSpring = 100000; } } _ragdoll.EnableMotors(); // Add rigid bodies and the constraints of the ragdoll to the simulation. _ragdoll.AddToSimulation(Simulation); // Add a rigid body. var box = new RigidBody(new BoxShape(0.4f, 0.4f, 0.4f)) { Name = "Box", Pose = new Pose(new Vector3F(0, 3, 0)), }; Simulation.RigidBodies.Add(box); }
public PassiveRagdollSample(Microsoft.Xna.Framework.Game game) : base(game) { GraphicsScreen.DrawReticle = true; // Add game objects which allow to shoot balls and grab rigid bodies. _ballShooterObject = new BallShooterObject(Services) { Speed = 10 }; GameObjectService.Objects.Add(_ballShooterObject); _grabObject = new GrabObject(Services); GameObjectService.Objects.Add(_grabObject); var modelNode = ContentManager.Load <ModelNode>("Dude/Dude"); _meshNode = modelNode.GetSubtree().OfType <MeshNode>().First().Clone(); _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0)); SampleHelper.EnablePerPixelLighting(_meshNode); GraphicsScreen.Scene.Children.Add(_meshNode); // Create a ragdoll for the Dude model. _ragdoll = new Ragdoll(); DudeRagdollCreator.Create(_meshNode.SkeletonPose, _ragdoll, Simulation, 0.571f); // Set the world space pose of the whole ragdoll. And copy the bone poses of the // current skeleton pose. _ragdoll.Pose = _meshNode.PoseWorld; _ragdoll.UpdateBodiesFromSkeleton(_meshNode.SkeletonPose); // Uncomment to disable dynamic movement (for debugging during ragdoll creation): //foreach (var body in _ragdoll.Bodies) // if (body != null) // body.MotionType = MotionType.Kinematic; // In this sample we use a passive ragdoll where we need joints to hold the // limbs together and limits to restrict angular movement. _ragdoll.EnableJoints(); _ragdoll.EnableLimits(); // Set all motors to constraint motors that only use damping. This adds a damping // effect to all ragdoll limbs. foreach (RagdollMotor motor in _ragdoll.Motors) { if (motor != null) { motor.Mode = RagdollMotorMode.Constraint; motor.ConstraintDamping = 5; motor.ConstraintSpring = 0; } } _ragdoll.EnableMotors(); // Add rigid bodies and the constraints of the ragdoll to the simulation. _ragdoll.AddToSimulation(Simulation); // Add a rigid body. var box = new RigidBody(new BoxShape(0.4f, 0.4f, 0.4f)) { Name = "Box", Pose = new Pose(new Vector3F(0, 3, 0)), }; Simulation.RigidBodies.Add(box); }
public MeshNode ConstructMeshTree() { // Create the grid CreateGrid(); // Do the hierarchical clustering on the grid Dictionary <Vector3, MeshNode> slotClusterAssign = new Dictionary <Vector3, MeshNode>(); int maxClusterSize = 1; // Assign the slotClusterAssign foreach (Vector3 key in slots.Keys) { slotClusterAssign.Add(key, new MeshNode(slots[key].GetMesh(), key, slots[key].GetOffset())); } // Processing queue Queue <List <Vector3> > clusters = new Queue <List <Vector3> >(); // Add initial clusters to the queue System.Random rand = new System.Random(); List <Vector3> randomOrder = new List <Vector3>(slotClusterAssign.Keys); randomOrder.Sort((x, y) => rand.Next(100000)); foreach (Vector3 key in randomOrder) { List <Vector3> cluster = new List <Vector3>(); cluster.Add(key); clusters.Enqueue(cluster); } while (maxClusterSize != slots.Count && clusters.Count != 0) { // Get the processing position foreach (Vector3 procPos in clusters.Dequeue()) { // Get the node behind the key MeshNode procNode = slotClusterAssign[procPos]; // Get all the positions inside the cluster (this nodes cluster) HashSet <Vector3> selfClusterPositions = new HashSet <Vector3>(procNode.GetPositions()); // Find the neighboring cluster with the lowest size int minClusterSize = 1000; Vector3 minClusterKey = new Vector3(10000f, 10000f, 10000f); foreach (Vector3 n in basisvectors) { // Get a neighbor key Vector3 candidate = procPos + n;; // Check if the candidate exists if (!slots.ContainsKey(candidate)) { continue; } // Check if the candidate is in the same cluster as current node if (selfClusterPositions.Contains(candidate)) { continue; } // Check the size of the cluster MeshNode neigh = slotClusterAssign[candidate]; if (neigh.GetSize() < minClusterSize) { minClusterSize = neigh.GetSize(); minClusterKey = candidate; } } // No eligable neighbours if (minClusterSize == 1000) { continue; } // Now we know the cluster we want to pair with // Get the node of the cluster MeshNode clusterNode = slotClusterAssign[minClusterKey]; // Create a new cluster where the children are the current cluster and the neighbor cluster MeshNode newNode = new MeshNode(clusterNode.GetMesh(), procNode.GetMesh()); newNode.AddChild(clusterNode); newNode.AddChild(procNode); // Get all the positions in the new cluster List <Vector3> clusterPositions = newNode.GetPositions(); // Update the cluster assignment foreach (Vector3 position in clusterPositions) { slotClusterAssign[position] = newNode; } // Add the cluster positions to the processing queue clusters.Enqueue(clusterPositions); // Get the cluster size if (newNode.GetSize() > maxClusterSize) { maxClusterSize = newNode.GetSize(); // Early exit if task is already finished if (maxClusterSize == slots.Count) { break; } } } } // Return the topmost cluster return(slotClusterAssign[new Vector3(0f, 0f, 0f)]); }
public frmNetworkInfo(MeshNode node) { InitializeComponent(); _node = node; }
public FacialAnimationSample(Microsoft.Xna.Framework.Game game) : base(game) { _graphicsScreen = new DeferredGraphicsScreen(Services) { DrawReticle = false }; GraphicsService.Screens.Insert(0, _graphicsScreen); Services.Register(typeof(DebugRenderer), null, _graphicsScreen.DebugRenderer); Services.Register(typeof(IScene), null, _graphicsScreen.Scene); // Add a game object which adds some GUI controls for the deferred graphics // screen to the Options window. GameObjectService.Objects.Add(new DeferredGraphicsOptionsObject(Services)); // Use a fixed camera. var projection = new PerspectiveProjection(); projection.SetFieldOfView( ConstantsF.PiOver4, GraphicsService.GraphicsDevice.Viewport.AspectRatio, 0.1f, 10); var cameraNode = new CameraNode(new Camera(projection)); cameraNode.LookAt(new Vector3(0.15f, 0.15f, 0.5f), new Vector3(0.1f, 0.15f, 0), Vector3.Up); _graphicsScreen.Scene.Children.Add(cameraNode); _graphicsScreen.ActiveCameraNode = cameraNode; // Lighting setup: var keyLight = new LightNode(new Spotlight { DiffuseIntensity = 0.6f, SpecularIntensity = 0.4f }); keyLight.LookAt(new Vector3(-2, 2, 2), new Vector3(), Vector3.Up); _graphicsScreen.Scene.Children.Add(keyLight); var backLight = new LightNode(new Spotlight { DiffuseIntensity = 0.3f, SpecularIntensity = 0.3f }); backLight.LookAt(new Vector3(1, 0.5f, -2), new Vector3(), Vector3.Up); _graphicsScreen.Scene.Children.Add(backLight); var fillLight = new LightNode(new AmbientLight { HemisphericAttenuation = 1, Intensity = 0.1f }); _graphicsScreen.Scene.Children.Add(fillLight); // The scene does not have a proper background. That's why the exposure is a // bit off. --> Reduce the max exposure. var hdrFilter = _graphicsScreen.PostProcessors.OfType <HdrFilter>().First(); hdrFilter.MaxExposure = 6; // Load the customized "Sintel" model (original: Durian Open Movie Project - http://www.sintel.org/). var model = ContentManager.Load <ModelNode>("Sintel/Sintel-Head").Clone(); model.PoseWorld = new Pose(new Vector3(0, 0, 0), Matrix.CreateRotationY(MathHelper.ToRadians(10)) * Matrix.CreateRotationX(-MathHelper.ToRadians(90))); _graphicsScreen.Scene.Children.Add(model); // The model consists of a root node and a mesh node. // ModelNode "Sintel-Head" // MeshNode "Sintel" _sintel = (MeshNode)model.Children[0]; // The model contains two skeletal animations: // - "MOUTH-open" is just a single frame. // - "Test" is a short animation (250 frames). // In the Options window, we will add a slider to move the jaw. // Slider.Value = 0 ... mouth closed (default) _mouthClosedPose = SkeletonPose.Create(_sintel.Mesh.Skeleton); // Slider.Value = 1 ... mouth open (copied from the "MOUTH-open" animation) SkeletonKeyFrameAnimation mouthOpen = _sintel.Mesh.Animations["MOUTH-open"]; _mouthOpenPose = SkeletonPose.Create(_sintel.Mesh.Skeleton); mouthOpen.GetValue(TimeSpan.Zero, ref _mouthOpenPose, ref _mouthOpenPose, ref _mouthOpenPose); // Turn the "Test" animation into an endless loop. _skeletalAnimation = new AnimationClip <SkeletonPose>(_sintel.Mesh.Animations["Test"]) { Duration = TimeSpan.MaxValue, LoopBehavior = LoopBehavior.Cycle }; // Mesh has several morph targets for facial animation, which are imported // automatically via the content pipeline. Unfortunately, the XNA content // pipeline cannot import morph target animations automatically. // In this demo, we will create a morph target animation in code. _morphingAnimation = CreateMorphingAnimation(); CreateGuiControls(); }
/** Exports the INavmesh graph to a file */ public void ExportToFile(NavGraph target) { INavmesh graph = (INavmesh)target; if (graph == null) { return; } Int3[] vertices = graph.vertices; if (vertices == null || target.nodes == null) { if (EditorUtility.DisplayDialog("Scan graph before exporting?", "The graph does not contain any mesh data. Do you want to scan it?", "Ok", "Cancel")) { AstarPath.MenuScan(); } else { return; } } vertices = graph.vertices; if (vertices == null || target.nodes == null) { Debug.LogError("Graph still does not contain any nodes or vertices. Canceling"); return; } string path = EditorUtility.SaveFilePanel("Export .obj", "", "navmesh.obj", "obj"); if (path == "") { return; } //Generate .obj System.Text.StringBuilder sb = new System.Text.StringBuilder(); string name = System.IO.Path.GetFileNameWithoutExtension(path); sb.Append("g ").Append(name).AppendLine(); //Write vertices for (int i = 0; i < vertices.Length; i++) { Vector3 v = (Vector3)vertices[i]; sb.Append(string.Format("v {0} {1} {2}\n", -v.x, v.y, v.z)); } //Define single texture coordinate to zero sb.Append("vt 0\n"); //Write triangles for (int i = 0; i < target.nodes.Length; i++) { MeshNode node = target.nodes[i] as MeshNode; if (node == null) { Debug.LogError("Node could not be casted to MeshNode. Node was null or no MeshNode"); return; } sb.Append(string.Format("f {0}/0 {1}/0 {2}/0\n", node.v1 + 1, node.v2 + 1, node.v3 + 1)); } string obj = sb.ToString(); using (System.IO.StreamWriter sw = new System.IO.StreamWriter(path)) { sw.Write(obj); } }
public void InternalOnPostScan () { if ( EndTransform == null || StartTransform == null ) return; #if !ASTAR_NO_POINT_GRAPH if ( AstarPath.active.astarData.pointGraph == null ) { AstarPath.active.astarData.AddGraph ( new PointGraph () ); } #endif if ( startNode != null) { NodeLink2 tmp; if (reference.TryGetValue (startNode, out tmp) && tmp == this) reference.Remove (startNode); } if ( endNode != null) { NodeLink2 tmp; if (reference.TryGetValue (endNode, out tmp) && tmp == this) reference.Remove (endNode); } #if !ASTAR_NO_POINT_GRAPH //Get nearest nodes from the first point graph, assuming both start and end transforms are nodes startNode = AstarPath.active.astarData.pointGraph.AddNode ( (Int3)StartTransform.position );//AstarPath.active.astarData.pointGraph.GetNearest(StartTransform.position).node as PointNode; endNode = AstarPath.active.astarData.pointGraph.AddNode ( (Int3)EndTransform.position ); //AstarPath.active.astarData.pointGraph.GetNearest(EndTransform.position).node as PointNode; #else throw new System.Exception ("Point graph is not included. Check your A* optimization settings."); #endif connectedNode1 = null; connectedNode2 = null; if (startNode == null || endNode == null) { startNode = null; endNode = null; return; } postScanCalled = true; reference[startNode] = this; reference[endNode] = this; Apply( true ); }
public ParallaxMappingSample(Microsoft.Xna.Framework.Game game) : base(game) { SampleFramework.IsMouseVisible = false; _graphicsScreen = new DeferredGraphicsScreen(Services); _graphicsScreen.DrawReticle = true; GraphicsService.Screens.Insert(0, _graphicsScreen); GameObjectService.Objects.Add(new DeferredGraphicsOptionsObject(Services)); Services.Register(typeof(DebugRenderer), null, _graphicsScreen.DebugRenderer); Services.Register(typeof(IScene), null, _graphicsScreen.Scene); // Add gravity and damping to the physics Simulation. Simulation.ForceEffects.Add(new Gravity()); Simulation.ForceEffects.Add(new Damping()); // Add a custom game object which controls the camera. var cameraGameObject = new CameraObject(Services); GameObjectService.Objects.Add(cameraGameObject); _graphicsScreen.ActiveCameraNode = cameraGameObject.CameraNode; GameObjectService.Objects.Add(new GrabObject(Services)); GameObjectService.Objects.Add(new ObjectCreatorObject(Services)); GameObjectService.Objects.Add(new DynamicSkyObject(Services, false, false, true)); GameObjectService.Objects.Add(new DynamicObject(Services, 1)); GameObjectService.Objects.Add(new DynamicObject(Services, 1)); GameObjectService.Objects.Add(new DynamicObject(Services, 1)); GameObjectService.Objects.Add(new DynamicObject(Services, 2)); GameObjectService.Objects.Add(new DynamicObject(Services, 2)); GameObjectService.Objects.Add(new DynamicObject(Services, 2)); // Add a few palm trees. Random random = new Random(12345); for (int i = 0; i < 10; i++) { Vector3F position = new Vector3F(random.NextFloat(-3, -8), 0, random.NextFloat(0, -5)); Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi)); float scale = random.NextFloat(0.5f, 1.2f); GameObjectService.Objects.Add(new StaticObject(Services, "PalmTree/palm_tree", scale, new Pose(position, orientation))); } // Load ground model which uses normal mapping. var modelNode = ContentManager.Load <ModelNode>("Parallax/Ground"); _meshNode = modelNode.Children.OfType <MeshNode>().First().Clone(); _meshNode.ScaleLocal = new Vector3F(0.1f); _meshNode.IsStatic = true; Debug.Assert(_meshNode.Mesh.Materials.Count == 1, "Mesh should have only one material."); // Load materials with normal mapping, parallax mapping and parallax occlusion mapping. _normalMaterial = ContentManager.Load <Material>("Parallax/Normal").Clone(); _parallaxMappingMaterial = ContentManager.Load <Material>("Parallax/PM").Clone(); _parallaxOcclusionMappingMaterial = ContentManager.Load <Material>("Parallax/POM").Clone(); // Get default values from materials. var parameterBindings = _parallaxOcclusionMappingMaterial["Material"].ParameterBindings; _heightScale = ((ConstParameterBinding <float>)parameterBindings["HeightScale"]).Value; _heightBias = ((ConstParameterBinding <float>)parameterBindings["HeightBias"]).Value; _lodThreshold = ((ConstParameterBinding <int>)parameterBindings["LodThreshold"]).Value; _maxSamples = ((ConstParameterBinding <int>)parameterBindings["MaxSamples"]).Value; _shadowStrength = ((ConstParameterBinding <float>)parameterBindings["ShadowStrength"]).Value; // Start test with POM material. _currentMaterialIndex = 2; UpdateMesh(); // Add nodes to scene graph. _graphicsScreen.Scene.Children.Add(_meshNode); // Create rigid body for ground plane. Simulation.RigidBodies.Add(new RigidBody(new PlaneShape(Vector3F.UnitY, 0)) { MotionType = MotionType.Static, }); }
public static Vector3 GetNextTarget(Path path, Vector3 currPosition, float offset, float pickNextWaypointMargin) { if (path.error) { return currPosition; } Int3 currentPosition = (Int3)currPosition; int startIndex = 0; int endIndex = path.path.Length; //Int3 pos = (Int3)currentPosition; //int minDist = -1; //int minNode = -1; INavmesh navmeshGraph = AstarData.GetGraph(path.path[0]) as INavmesh; if (navmeshGraph == null) { Debug.LogError("Couldn't cast graph to the appropriate type (graph isn't a Navmesh type graph, it doesn't implement the INavmesh interface)"); return currPosition;///Apply (path,start,end, startIndex, endIndex, graph); } Int3[] vertices = navmeshGraph.vertices; //float minDist2 = -1; //int minNode2 = -1; //Debug.Log (meshPath.Length + " "+path.Length +" "+startIndex+" "+endIndex); /*for (int i=startIndex;i< endIndex;i++) { MeshNode node = path.path[i] as MeshNode; if (node == null) { Debug.LogWarning ("Path could not be casted to Mesh Nodes"); return currentPosition;//return base.Apply (path,start,end, startIndex, endIndex, graph); } //if (Polygon.TriangleArea2 (vertices[node.v1],vertices[node.v2],currentPosition) >= 0 || Polygon.TriangleArea2 (vertices[node.v2],vertices[node.v3],currentPosition) >= 0 || Polygon.TriangleArea2 (vertices[node.v3],vertices[node.v1],currentPosition) >= 0) { if (!Polygon.IsClockwise (vertices[node.v1],vertices[node.v2],pos) || !Polygon.IsClockwise (vertices[node.v2],vertices[node.v3],pos) || !Polygon.IsClockwise (vertices[node.v3],vertices[node.v1],pos)) { if (minDist == -1) { float dist2 = (node.position-pos).sqrMagnitude; if (minDist2 == -1 || dist2 < minDist2) { minDist2 = dist2; minNode2 = i; } } continue; } Debug.DrawLine (vertices[node.v1],vertices[node.v2],Color.blue); Debug.DrawLine (vertices[node.v2],vertices[node.v3],Color.blue); Debug.DrawLine (vertices[node.v3],vertices[node.v1],Color.blue); int dist = node.position.y-pos.y; if (minDist == -1 || dist < minDist) { minDist = dist; minNode = i; } }*/ MeshNode lastNode = path.path[endIndex - 1] as MeshNode; if (lastNode == null) { Debug.LogWarning("Path could not be casted to Mesh Nodes"); return currentPosition;//return base.Apply (path,start,end, startIndex, endIndex, graph); } PathNNConstraint constraint = PathNNConstraint.Default; constraint.SetStart(lastNode); NNInfo nninfo = NavMeshGraph.GetNearestForce(path.path, vertices, currPosition, constraint); currentPosition = nninfo.clampedPosition; /*for (int i=startIndex;i< endIndex;i++) { if (nninfo.node == path.path[i]) { minNode = i; } }*/ //Node minNode = nninfo.node; /*startIndex = minNode; if (startIndex == -1) { startIndex = minNode2; currentPosition = path.path[minNode2].position; } if (startIndex == -1) { Debug.Log ("Couldn't find current node"); return currentPosition; }*/ MeshNode[] meshPath = new MeshNode[endIndex - startIndex]; for (int i = startIndex; i < endIndex; i++) { meshPath[i - startIndex] = path.path[i] as MeshNode; } //return Vector3.zero; //Vector3[] vertices = null; if (leftFunnel == null || leftFunnel.Length < meshPath.Length + 1) { leftFunnel = new Int3[meshPath.Length + 1]; } if (rightFunnel == null || rightFunnel.Length < meshPath.Length + 1) { rightFunnel = new Int3[meshPath.Length + 1]; } int leftFunnelLength = meshPath.Length + 1; //int rightFunnelLength = meshPath.Length+1; leftFunnel[0] = currentPosition; rightFunnel[0] = currentPosition; leftFunnel[meshPath.Length] = path.endPoint; rightFunnel[meshPath.Length] = path.endPoint; int lastLeftIndex = -1; int lastRightIndex = -1; for (int i = 0; i < meshPath.Length - 1; i++) { //Find the connection between the nodes MeshNode n1 = meshPath[i]; MeshNode n2 = meshPath[i + 1]; bool foundFirst = false; int first = -1; int second = -1; for (int x = 0; x < 3; x++) { //Vector3 vertice1 = vertices[n1.vertices[x]]; //n1[x] gets the vertice index for vertex number 'x' in the node. Equal to n1.GetVertexIndex (x) int vertice1 = n1[x]; for (int y = 0; y < 3; y++) { //Vector3 vertice2 = vertices[n2.vertices[y]]; int vertice2 = n2[y]; if (vertice1 == vertice2) { if (foundFirst) { second = vertice2; break; } else { first = vertice2; foundFirst = true; } } } } //Debug.DrawLine ((Vector3)vertices[first]+Vector3.up*0.1F,(Vector3)vertices[second]+Vector3.up*0.1F,Color.cyan); //Debug.Log (first+" "+second); if (first == lastLeftIndex) { leftFunnel[i + 1] = vertices[first]; rightFunnel[i + 1] = vertices[second]; lastLeftIndex = first; lastRightIndex = second; } else if (first == lastRightIndex) { leftFunnel[i + 1] = vertices[second]; rightFunnel[i + 1] = vertices[first]; lastLeftIndex = second; lastRightIndex = first; } else if (second == lastLeftIndex) { leftFunnel[i + 1] = vertices[second]; rightFunnel[i + 1] = vertices[first]; lastLeftIndex = second; lastRightIndex = first; } else { leftFunnel[i + 1] = vertices[first]; rightFunnel[i + 1] = vertices[second]; lastLeftIndex = first; lastRightIndex = second; } } //Switch the arrays so the right funnel really is on the right side (and vice versa) if (!Polygon.IsClockwise(currentPosition, leftFunnel[1], rightFunnel[1])) { Int3[] tmp = leftFunnel; leftFunnel = rightFunnel; rightFunnel = tmp; } for (int i = 1; i < leftFunnelLength - 1; i++) { //float unitWidth = 2; Int3 normal = (rightFunnel[i] - leftFunnel[i]); float magn = normal.worldMagnitude; normal /= magn; normal *= Mathf.Clamp(offset, 0, (magn / 2F)); leftFunnel[i] += normal; rightFunnel[i] -= normal; //Debug.DrawLine (rightFunnel[i],leftFunnel[i],Color.blue); } /*for (int i=0;i<path.Length-1;i++) { Debug.DrawLine (path[i].position,path[i+1].position,Color.blue); }*/ /*for (int i=0;i<leftFunnel.Length-1;i++) { Debug.DrawLine (leftFunnel[i],leftFunnel[i+1],Color.red); Debug.DrawLine (rightFunnel[i],rightFunnel[i+1],Color.magenta); }*/ if (tmpList == null) { tmpList = new List<Vector3>(3); } List<Vector3> funnelPath = tmpList; funnelPath.Clear(); funnelPath.Add(currentPosition); Int3 portalApex = currentPosition; Int3 portalLeft = leftFunnel[0]; Int3 portalRight = rightFunnel[0]; int apexIndex = 0; int rightIndex = 0; int leftIndex = 0; //yield return 0; for (int i = 1; i < leftFunnelLength; i++) { Int3 left = leftFunnel[i]; Int3 right = rightFunnel[i]; /*Debug.DrawLine (portalApex,portalLeft,Color.red); Debug.DrawLine (portalApex,portalRight,Color.yellow); Debug.DrawLine (portalApex,left,Color.cyan); Debug.DrawLine (portalApex,right,Color.cyan);*/ if (Polygon.TriangleArea2(portalApex, portalRight, right) >= 0) { if (portalApex == portalRight || Polygon.TriangleArea2(portalApex, portalLeft, right) <= 0) { portalRight = right; rightIndex = i; } else { funnelPath.Add((Vector3)portalLeft); //if (funnelPath.Count > 3) //break; portalApex = portalLeft; apexIndex = leftIndex; portalLeft = portalApex; portalRight = portalApex; leftIndex = apexIndex; rightIndex = apexIndex; i = apexIndex; //yield return 0; continue; } } if (Polygon.TriangleArea2(portalApex, portalLeft, left) <= 0) { if (portalApex == portalLeft || Polygon.TriangleArea2(portalApex, portalRight, left) >= 0) { portalLeft = left; leftIndex = i; } else { funnelPath.Add((Vector3)portalRight); //if (funnelPath.Count > 3) //break; portalApex = portalRight; apexIndex = rightIndex; portalLeft = portalApex; portalRight = portalApex; leftIndex = apexIndex; rightIndex = apexIndex; i = apexIndex; //yield return 0; continue; } } //yield return 0; } //yield return 0; funnelPath.Add(path.endPoint); Vector3[] p = funnelPath.ToArray(); if (p.Length <= 1) { return currentPosition; } for (int i = 1; i < p.Length - 1; i++) { Vector3 closest = Mathfx.NearestPointStrict(p[i], p[i + 1], currentPosition); if ((closest - (Vector3)currentPosition).sqrMagnitude < pickNextWaypointMargin * pickNextWaypointMargin) { continue; } else { return p[i]; } } return p[p.Length - 1]; }
public FurSample(Microsoft.Xna.Framework.Game game) : base(game) { SampleFramework.IsMouseVisible = false; _graphicsScreen = new DeferredGraphicsScreen(Services); _graphicsScreen.DrawReticle = true; GraphicsService.Screens.Insert(0, _graphicsScreen); Services.Register(typeof(DebugRenderer), null, _graphicsScreen.DebugRenderer); Services.Register(typeof(IScene), null, _graphicsScreen.Scene); // Add gravity and damping to the physics Simulation. Simulation.ForceEffects.Add(new Gravity()); Simulation.ForceEffects.Add(new Damping()); // Add a custom game object which controls the camera. var cameraGameObject = new CameraObject(Services); GameObjectService.Objects.Add(cameraGameObject); _graphicsScreen.ActiveCameraNode = cameraGameObject.CameraNode; // More standard objects. GameObjectService.Objects.Add(new GrabObject(Services)); GameObjectService.Objects.Add(new ObjectCreatorObject(Services)); GameObjectService.Objects.Add(new StaticSkyObject(Services)); GameObjectService.Objects.Add(new GroundObject(Services)); // Tell the engine how to interpret effect parameters with the name or semantic "FurDisplacement". // We could add our own effect interpreter instance, as it is done in the CloudQuadSample. // Or, we add the parameter description to the standard DefaultEffectInterpreter instance: var defaultEffectInterpreter = GraphicsService.EffectInterpreters.OfType <DefaultEffectInterpreter>().First(); // If the effect parameter name or semantic in the .fx file is called "FurDisplacement", then // return an EffectParameterDescription. The hint "PerInstance" tells the engine that this // parameter needs to be updated for each scene node. defaultEffectInterpreter.ParameterDescriptions.Add( "FurDisplacement", (parameter, i) => new EffectParameterDescription(parameter, "FurDisplacement", i, EffectParameterHint.PerInstance)); // Tell the engine how to create an effect parameter binding for "FurDisplacement". // We could add our own effect binder instance, as it is done in the CloudQuadSample. // Or, we add the parameter description to the standard DefaultEffectBinder instance: var defaultEffectBinder = GraphicsService.EffectBinders.OfType <DefaultEffectBinder>().First(); // If the effect parameter represents "FurDisplacement", then create a DelegateParameterBinding // for the parameter. When an object is rendered using this effect the method ComputeFurDisplacement // is called to update the value of the effect parameter. defaultEffectBinder.Vector3Bindings.Add( "FurDisplacement", (effect, parameter, data) => new DelegateParameterBinding <Vector3>(effect, parameter, ComputeFurDisplacement)); // Load model. (When the model and its effects are loaded, the engine will // check for the FurDisplacement parameter and create the appropriate parameter binding.) _meshNode = (MeshNode)ContentManager.Load <ModelNode>("Fur/FurBall").Children[0].Clone(); _rigidBody = new RigidBody(new SphereShape(0.5f)); // Store a reference to the rigid body in SceneNode.UserData. _meshNode.UserData = _rigidBody; // Set a random pose. _rigidBody.Pose = new Pose(new Vector3(0, 1, 0), RandomHelper.Random.NextQuaternion()); _meshNode.PoseWorld = _rigidBody.Pose; // Add rigid body to physics simulation and model to scene. Simulation.RigidBodies.Add(_rigidBody); _graphicsScreen.Scene.Children.Add(_meshNode); }
/// <summary> /// Exports the model. /// </summary> /// <param name="model"> /// The model. /// </param> /// <param name="transform"> /// The transform. /// </param> protected virtual void ExportModel(MeshNode model, Transform3D transform) { }
public void RemoveEdgesWithSibling(MeshNode sibling) { int index = TargetNodes.IndexOf(sibling); if (index > -1) { if (index < TargetEdges.Count) RemoveEdge(TargetEdges[index]); TargetNodes.Remove(sibling); } }
int RebuildFromInternal (MeshNode[] nodes, int from, int to, bool odd) { if (to - from <= 0) throw new ArgumentException(); if (to - from == 1) { return GetBox(nodes[from]); } var rect = NodeBounds(nodes, from, to); int box = GetBox(rect); // Performance optimization for a common case if (to - from == 2) { arr[box].left = GetBox(nodes[from]); arr[box].right = GetBox(nodes[from+1]); return box; } int mx; if (odd) { // X int divider = (rect.xmin + rect.xmax)/2; mx = SplitByX (nodes, from, to, divider); } else { // Y/Z int divider = (rect.ymin + rect.ymax)/2; mx = SplitByZ (nodes, from, to, divider); } if (mx == from || mx == to) { // All nodes were on one side of the divider // Try to split along the other axis if (!odd) { // X int divider = (rect.xmin + rect.xmax)/2; mx = SplitByX (nodes, from, to, divider); } else { // Y/Z int divider = (rect.ymin + rect.ymax)/2; mx = SplitByZ (nodes, from, to, divider); } if (mx == from || mx == to) { // All nodes were on one side of the divider // Just pick one half mx = (from+to)/2; } } arr[box].left = RebuildFromInternal(nodes, from, mx, !odd); arr[box].right = RebuildFromInternal(nodes, mx, to, !odd); return box; }
// OnLoad() is called when the GameObject is added to the IGameObjectService. protected override void OnLoad() { var graphicsService = _services.GetInstance <IGraphicsService>(); var gameObjectService = _services.GetInstance <IGameObjectService>(); // Check if the game object manager has another ProceduralObject instance. var otherProceduralObject = gameObjectService.Objects .OfType <ProceduralObject>() .FirstOrDefault(o => o != this); Mesh mesh; if (otherProceduralObject != null) { // This ProceduralObject is not the first. We re-use rigid body data and // the mesh from the existing instance. var otherBody = otherProceduralObject._rigidBody; _rigidBody = new RigidBody(otherBody.Shape, otherBody.MassFrame, otherBody.Material); mesh = otherProceduralObject._meshNode.Mesh; } else { // This is the first ProceduralObject instance. We create a new rigid body // and a new mesh. var shape = new MinkowskiSumShape(new GeometricObject(new SphereShape(0.05f)), new GeometricObject(new BoxShape(0.5f, 0.5f, 0.5f))); _rigidBody = new RigidBody(shape); // Create a DigitalRune.Geometry.Meshes.TriangleMesh from the RigidBody's // shape and convert this to a DigitalRune.Graphics.Mesh. var triangleMesh = _rigidBody.Shape.GetMesh(0.01f, 4); mesh = new Mesh { Name = "ProceduralObject" }; var submesh = CreateSubmeshWithTexCoords(graphicsService.GraphicsDevice, triangleMesh, MathHelper.ToRadians(70)); mesh.Submeshes.Add(submesh); // Next, we need a material. We can load a predefined material (*.drmat file) // with the content manager. //var material = content.Load<Material>("Default"); // Alternatively, we can load some effects and build the material here: Material material = new Material(); // We need an EffectBinding for each render pass. // The "Default" pass uses a BasicEffectBinding (which is an EffectBinding // for the XNA BasicEffect). // Note: The "Default" pass is not used by the DeferredLightingScreen, so // we could ignore this pass in this sample project. BasicEffectBinding defaultEffectBinding = new BasicEffectBinding(graphicsService, null) { LightingEnabled = true, TextureEnabled = true, VertexColorEnabled = false }; defaultEffectBinding.Set("Texture", graphicsService.GetDefaultTexture2DWhite()); defaultEffectBinding.Set("DiffuseColor", new Vector3(1, 1, 1)); defaultEffectBinding.Set("SpecularColor", new Vector3(1, 1, 1)); defaultEffectBinding.Set("SpecularPower", 100f); material.Add("Default", defaultEffectBinding); // EffectBinding for the "ShadowMap" pass. // Note: EffectBindings which are used in a Material must be marked with // the EffectParameterHint Material. var content = _services.GetInstance <ContentManager>(); EffectBinding shadowMapEffectBinding = new EffectBinding( graphicsService, content.Load <Effect>("DigitalRune\\Materials\\ShadowMap"), null, EffectParameterHint.Material); material.Add("ShadowMap", shadowMapEffectBinding); // EffectBinding for the "GBuffer" pass. EffectBinding gBufferEffectBinding = new EffectBinding( graphicsService, content.Load <Effect>("DigitalRune\\Materials\\GBuffer"), null, EffectParameterHint.Material); gBufferEffectBinding.Set("SpecularPower", 100f); material.Add("GBuffer", gBufferEffectBinding); // EffectBinding for the "Material" pass. EffectBinding materialEffectBinding = new EffectBinding( graphicsService, content.Load <Effect>("DigitalRune\\Materials\\Material"), null, EffectParameterHint.Material); materialEffectBinding.Set("DiffuseTexture", graphicsService.GetDefaultTexture2DWhite()); materialEffectBinding.Set("DiffuseColor", new Vector3(1, 1, 1)); materialEffectBinding.Set("SpecularColor", new Vector3(1, 1, 1)); material.Add("Material", materialEffectBinding); // Assign this material to the submesh. submesh.SetMaterial(material); } // Create a scene graph node for the mesh. _meshNode = new MeshNode(mesh); // Set a random pose. var randomPosition = new Vector3F( RandomHelper.Random.NextFloat(-10, 10), RandomHelper.Random.NextFloat(2, 5), RandomHelper.Random.NextFloat(-20, 0)); _rigidBody.Pose = new Pose(randomPosition, RandomHelper.Random.NextQuaternionF()); _meshNode.PoseWorld = _rigidBody.Pose; // Add mesh node to scene graph. var scene = _services.GetInstance <IScene>(); scene.Children.Add(_meshNode); // Add rigid body to the physics simulation. var simulation = _services.GetInstance <Simulation>(); simulation.RigidBodies.Add(_rigidBody); }
/** Inserts a mesh node in the tree */ public void Insert (MeshNode node) { int boxi = GetBox (node); // Was set to root if (boxi == 0) { return; } BBTreeBox box = arr[boxi]; //int depth = 0; int c = 0; while (true) { BBTreeBox cb = arr[c]; cb.rect = ExpandToContain (cb.rect,box.rect); if (cb.node != null) { //Is Leaf cb.left = boxi; int box2 = GetBox (cb.node); //BBTreeBox box2 = new BBTreeBox (this,c.node); //Console.WriteLine ("Inserted "+box.node+", rect "+box.rect.ToString ()); cb.right = box2; cb.node = null; //cb.depth++; //c.rect = c.rect. arr[c] = cb; //Debug.Log (depth); return; } else { //depth++; //cb.depth++; arr[c] = cb; int e1 = ExpansionRequired (arr[cb.left].rect,box.rect);// * arr[cb.left].depth; int e2 = ExpansionRequired (arr[cb.right].rect,box.rect);// * arr[cb.left].depth; //Choose the rect requiring the least expansion to contain box.rect if (e1 < e2) { c = cb.left; } else if (e2 < e1) { c = cb.right; } else { //Equal, Choose the one with the smallest area c = RectArea (arr[cb.left].rect) < RectArea (arr[cb.right].rect) ? cb.left : cb.right; } } } }
public IKPhysicsSample(Microsoft.Xna.Framework.Game game) : base(game) { GraphicsScreen.DrawReticle = true; // Add game objects which allows to grab rigid bodies. _grabObject = new GrabObject(Services); GameObjectService.Objects.Add(_grabObject); // Add Dude model. var modelNode = ContentManager.Load <ModelNode>("Dude/Dude"); _meshNode = modelNode.GetSubtree().OfType <MeshNode>().First().Clone(); _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0)); SampleHelper.EnablePerPixelLighting(_meshNode); GraphicsScreen.Scene.Children.Add(_meshNode); // Create a ragdoll for the Dude model. _ragdoll = new Ragdoll(); DudeRagdollCreator.Create(_meshNode.SkeletonPose, _ragdoll, Simulation, 0.571f); // Set the initial world space pose of the whole ragdoll. And copy the bone poses of the // current skeleton pose. _ragdoll.Pose = _meshNode.PoseWorld; _ragdoll.UpdateBodiesFromSkeleton(_meshNode.SkeletonPose); // Enable constraints (joints and limits, no motors) _ragdoll.EnableJoints(); _ragdoll.EnableLimits(); _ragdoll.DisableMotors(); foreach (var body in _ragdoll.Bodies) { if (body != null) { // Disable rigid body sleeping. (If we leave it enabled, the simulation might // disable slow bodies before they reach their IK goal.) body.CanSleep = false; // Disable collisions response. body.CollisionResponseEnabled = false; } } // Add rigid bodies and the constraints of the ragdoll to the simulation. _ragdoll.AddToSimulation(Simulation); // Disable all force effects (default gravity and damping). Simulation.ForceEffects.Clear(); // Create constraints which hold selected bodies at their current position // relative to the world. // To constrain the position + orientation, we use a FixedJoint. foreach (var boneName in new[] { "Pelvis" }) { var ragdollBody = _ragdoll.Bodies[_meshNode.SkeletonPose.Skeleton.GetIndex(boneName)]; var ikJoint = new FixedJoint { AnchorPoseALocal = ragdollBody.Pose, BodyA = Simulation.World, AnchorPoseBLocal = Pose.Identity, BodyB = ragdollBody, CollisionEnabled = false, MaxForce = 1000, }; _ikJoints.Add(ikJoint); Simulation.Constraints.Add(ikJoint); } // To constrain only the position, we use a BallJoint. foreach (var boneName in new[] { "L_Hand", "R_Hand", "L_Ankle1", "R_Ankle" }) { var ragdollBody = _ragdoll.Bodies[_meshNode.SkeletonPose.Skeleton.GetIndex(boneName)]; var ikJoint = new BallJoint { AnchorPositionALocal = ragdollBody.Pose.Position, BodyA = Simulation.World, AnchorPositionBLocal = Vector3F.Zero, BodyB = ragdollBody, CollisionEnabled = false, MaxForce = 1000, }; _ikJoints.Add(ikJoint); Simulation.Constraints.Add(ikJoint); } }
public BBTreeBox (IntRect rect) { node = null; this.rect = rect; left = right = -1; }
/** Applies constrained movement from \a startPos to \a endPos. * The result is stored in \a clampedPos. * Returns the new current node */ public Node ClampAlongNavmesh(Vector3 startPos, Node startNode, Vector3 endPos, out Vector3 clampedPos) { clampedPos = endPos; Stack <Node> stack = tmpStack; // Tiny stack List <Node> closed = tmpClosed; // Tiny closed list stack.Clear(); closed.Clear(); Vector3 bestPos, p; float bestDist = float.PositiveInfinity; float d; Node bestRef = null; // Search constraint Vector3 searchPos = (startPos + endPos) / 2; float searchRadius = Mathfx.MagnitudeXZ(startPos, endPos) / 2; // Init bestPos = startPos; stack.Push(startNode); closed.Add(startNode); // Self ref, start maker. INavmesh graph = AstarData.GetGraph(startNode) as INavmesh; if (graph == null) { //Debug.LogError ("Null graph, or the graph was no NavMeshGraph"); return(startNode); } while (stack.Count > 0) { // Pop front. Node cur = stack.Pop(); MeshNode poly = cur as MeshNode; // If target is inside the poly, stop search. if (NavMeshGraph.ContainsPoint(poly, endPos, graph.vertices)) { bestRef = cur; bestPos = endPos; break; } // Follow edges or keep track of nearest point on blocking edge. for (int i = 0, j = 2; i < 3; j = i++) { int sp = poly.GetVertexIndex(j); int sq = poly.GetVertexIndex(i); bool blocking = true; MeshNode conn = null; for (int q = 0; q < cur.connections.Length; q++) { conn = cur.connections[q] as MeshNode; if (conn == null) { continue; } for (int i2 = 0, j2 = 2; i2 < 3; j2 = i2++) { int sp2 = conn.GetVertexIndex(j2); int sq2 = conn.GetVertexIndex(i2); if ((sp2 == sp && sq2 == sq) || (sp2 == sq && sq2 == sp)) { blocking = false; break; } } if (!blocking) { break; } } //Node neiRef = poly->nei[j]; if (blocking) { // Blocked edge, calc distance. p = Mathfx.NearestPointStrictXZ((Vector3)graph.vertices[sp], (Vector3)graph.vertices[sq], endPos); d = Mathfx.MagnitudeXZ(p, endPos); if (d < bestDist) { // Update nearest distance. bestPos = p; bestDist = d; bestRef = cur; } } else { // Skip already visited. if (closed.Contains(conn)) { continue; } // Store to closed with parent for trace back. closed.Add(conn); // Non-blocked edge, follow if within search radius. p = Mathfx.NearestPointStrictXZ((Vector3)graph.vertices[sp], (Vector3)graph.vertices[sq], searchPos); d = Mathfx.MagnitudeXZ(p, searchPos); if (d <= searchRadius) { stack.Push(conn); } } } } // Trace back and store visited polygons. /* followVisited(bestRef,visited,closed); * // Store best movement position.*/ clampedPos = bestPos; // Return number of visited polys. return(bestRef); //visited.size(); }
public KinematicRagdollSample(Microsoft.Xna.Framework.Game game) : base(game) { GraphicsScreen.DrawReticle = true; // Add game objects which allow to shoot balls and grab rigid bodies. _ballShooterObject = new BallShooterObject(Services) { Speed = 10 }; GameObjectService.Objects.Add(_ballShooterObject); _grabObject = new GrabObject(Services); GameObjectService.Objects.Add(_grabObject); var modelNode = ContentManager.Load <ModelNode>("Dude/Dude"); _meshNode = modelNode.GetSubtree().OfType <MeshNode>().First().Clone(); _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi)); SampleHelper.EnablePerPixelLighting(_meshNode); GraphicsScreen.Scene.Children.Add(_meshNode); var animations = _meshNode.Mesh.Animations; var loopingAnimation = new AnimationClip <SkeletonPose>(animations.Values.First()) { LoopBehavior = LoopBehavior.Cycle, Duration = TimeSpan.MaxValue, }; var animationController = AnimationService.StartAnimation(loopingAnimation, (IAnimatableProperty)_meshNode.SkeletonPose); animationController.UpdateAndApply(); // Create a ragdoll for the Dude model. _ragdoll = new Ragdoll(); DudeRagdollCreator.Create(_meshNode.SkeletonPose, _ragdoll, Simulation, 0.571f); // Set the world space pose of the whole ragdoll. And copy the bone poses of the // current skeleton pose. _ragdoll.Pose = _meshNode.PoseWorld; _ragdoll.UpdateBodiesFromSkeleton(_meshNode.SkeletonPose); // Set all bodies to kinematic - they should not be affected by forces. foreach (var body in _ragdoll.Bodies) { if (body != null) { body.MotionType = MotionType.Kinematic; } } // Set all motors to velocity motors. Velocity motors change RigidBody.LinearVelocity // RigidBody.AngularVelocity to move the rigid bodies. foreach (RagdollMotor motor in _ragdoll.Motors) { if (motor != null) { motor.Mode = RagdollMotorMode.Velocity; } } _ragdoll.EnableMotors(); // In this sample, we do not need joints or limits. _ragdoll.DisableJoints(); _ragdoll.DisableLimits(); // Add ragdoll rigid bodies to the simulation. _ragdoll.AddToSimulation(Simulation); // Add a rigid body. var box = new RigidBody(new BoxShape(0.4f, 0.4f, 0.4f)) { Name = "Box", Pose = new Pose(new Vector3F(0, 3, 0)), }; Simulation.RigidBodies.Add(box); }
// Creates a test scene with a lot of randomly placed objects. internal static void CreateScene(ServiceContainer services, ContentManager content, DeferredGraphicsScreen graphicsScreen) { var gameObjectService = services.GetInstance <IGameObjectService>(); var graphicsService = services.GetInstance <IGraphicsService>(); gameObjectService.Objects.Add(new DynamicSkyObject(services, true, false, true) { EnableAmbientLight = false, // Disable ambient light of sky to make shadows more visible. EnableCloudShadows = false }); gameObjectService.Objects.Add(new GroundObject(services)); gameObjectService.Objects.Add(new DynamicObject(services, 1)); gameObjectService.Objects.Add(new DynamicObject(services, 2)); gameObjectService.Objects.Add(new DynamicObject(services, 3)); gameObjectService.Objects.Add(new DynamicObject(services, 5)); gameObjectService.Objects.Add(new DynamicObject(services, 6)); gameObjectService.Objects.Add(new DynamicObject(services, 7)); gameObjectService.Objects.Add(new ObjectCreatorObject(services)); gameObjectService.Objects.Add(new LavaBallsObject(services)); var random = new Random(); // Spheres var sphereMesh = SampleHelper.CreateMesh(content, graphicsService, new SphereShape(1)); for (int i = 0; i < 100; i++) { Vector3F position = new Vector3F(random.NextFloat(-100, 100), random.NextFloat(0, 3), random.NextFloat(-100, 100)); float scale = random.NextFloat(0.5f, 3f); var meshNode = new MeshNode(sphereMesh) { PoseLocal = new Pose(position), ScaleLocal = new Vector3F(scale), IsStatic = true, }; graphicsScreen.Scene.Children.Add(meshNode); } // Boxes var boxMesh = SampleHelper.CreateMesh(content, graphicsService, new BoxShape(1, 1, 1)); for (int i = 0; i < 100; i++) { Vector3F position = new Vector3F(random.NextFloat(-100, 100), random.NextFloat(0, 3), random.NextFloat(-100, 100)); QuaternionF orientation = random.NextQuaternionF(); Vector3F scale = random.NextVector3F(0.1f, 4f); var meshNode = new MeshNode(boxMesh) { PoseLocal = new Pose(position, orientation), ScaleLocal = scale, IsStatic = true, }; graphicsScreen.Scene.Children.Add(meshNode); } // Height field with smooth hills. var numberOfSamplesX = 20; var numberOfSamplesZ = 20; var samples = new float[numberOfSamplesX * numberOfSamplesZ]; for (int z = 0; z < numberOfSamplesZ; z++) { for (int x = 0; x < numberOfSamplesX; x++) { if (x == 0 || z == 0 || x == 19 || z == 19) { // Set this boundary elements to a low height, so that the height field is connected // to the ground. samples[z * numberOfSamplesX + x] = -1; } else { // A sine/cosine function that creates some interesting waves. samples[z * numberOfSamplesX + x] = 1 + (float)(Math.Cos(z / 2f) * Math.Sin(x / 2f) * 1); } } } var heightField = new HeightField(0, 0, 20, 20, samples, numberOfSamplesX, numberOfSamplesZ); var heightFieldMesh = SampleHelper.CreateMesh(content, graphicsService, heightField); var heightFieldMeshNode = new MeshNode(heightFieldMesh) { PoseLocal = new Pose(new Vector3F(20, 0, -20)), ScaleLocal = new Vector3F(1, 2, 1), IsStatic = true, }; graphicsScreen.Scene.Children.Add(heightFieldMeshNode); // Dudes. for (int i = 0; i < 10; i++) { Vector3F position = new Vector3F(random.NextFloat(-20, 20), 0, random.NextFloat(-20, 20)); Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi)); gameObjectService.Objects.Add(new DudeObject(services) { Pose = new Pose(position, orientation) }); } // Palm trees. for (int i = 0; i < 100; i++) { Vector3F position = new Vector3F(random.NextFloat(-80, 80), 0, random.NextFloat(-100, 100)); Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi)); float scale = random.NextFloat(0.5f, 1.2f); gameObjectService.Objects.Add(new StaticObject(services, "PalmTree/palm_tree", scale, new Pose(position, orientation))); } // Rocks for (int i = 0; i < 100; i++) { Vector3F position = new Vector3F(random.NextFloat(-80, 80), 1, random.NextFloat(-100, 100)); QuaternionF orientation = RandomHelper.Random.NextQuaternionF(); float scale = random.NextFloat(0.5f, 1.2f); gameObjectService.Objects.Add(new StaticObject(services, "Rock/rock_05", scale, new Pose(position, orientation))); } // Grass for (int i = 0; i < 100; i++) { Vector3F position = new Vector3F(random.NextFloat(-20, 20), 0, random.NextFloat(-20, 20)); Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi)); float scale = random.NextFloat(0.5f, 1.2f); gameObjectService.Objects.Add(new StaticObject(services, "Grass/Grass", scale, new Pose(position, orientation))); } // More plants for (int i = 0; i < 100; i++) { Vector3F position = new Vector3F(random.NextFloat(-20, 20), 0, random.NextFloat(-20, 20)); Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi)); float scale = random.NextFloat(0.5f, 1.2f); gameObjectService.Objects.Add(new StaticObject(services, "Parviflora/Parviflora", scale, new Pose(position, orientation))); } // "Skyscrapers" for (int i = 0; i < 20; i++) { Vector3F position = new Vector3F(random.NextFloat(90, 100), 0, random.NextFloat(-100, 100)); Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi)); Vector3F scale = new Vector3F(random.NextFloat(6, 20), random.NextFloat(10, 100), random.NextFloat(6, 20)); var meshNode = new MeshNode(boxMesh) { PoseLocal = new Pose(position, orientation), ScaleLocal = scale, IsStatic = true, UserFlags = 1, // Mark the distant huge objects. Used in render callbacks in the CompositeShadowSample. }; graphicsScreen.Scene.Children.Add(meshNode); } // "Hills" for (int i = 0; i < 20; i++) { Vector3F position = new Vector3F(random.NextFloat(-90, -100), 0, random.NextFloat(-100, 100)); Vector3F scale = new Vector3F(random.NextFloat(10, 20), random.NextFloat(10, 30), random.NextFloat(10, 20)); var meshNode = new MeshNode(sphereMesh) { PoseLocal = new Pose(position), ScaleLocal = scale, IsStatic = true, UserFlags = 1, // Mark the distant huge objects. Used in render callbacks in the CompositeShadowSample. }; graphicsScreen.Scene.Children.Add(meshNode); } }
static int SplitByX (MeshNode[] nodes, int from, int to, int divider) { int mx = to; for (int i = from; i < mx; i++) { if (nodes[i].position.x > divider) { // swap with mx mx--; var tmp = nodes[mx]; nodes[mx] = nodes[i]; nodes[i] = tmp; i--; } } return mx; }
static void Main(string[] args) { if (args != null && args.Length > 0) { ParseArguments(args, out _Ip, out _Port, out _PeerIpPorts); _IpPort = _Ip + ":" + _Port; } else { _IpPort = InputString("Local IP:port:", "127.0.0.1:8000", false); ParseIpPort(_IpPort, out _Ip, out _Port); } _Settings = new MeshSettings(); _Settings.AcceptInvalidCertificates = true; _Settings.AutomaticReconnect = true; _Settings.MutuallyAuthenticate = false; _Settings.PresharedKey = null; _Settings.StreamBufferSize = 65536; _Settings.ReconnectIntervalMs = 1000; _Mesh = new MeshNode(_Ip, _Port); _Mesh.PeerConnected += PeerConnected; _Mesh.PeerDisconnected += PeerDisconnected; _Mesh.MessageReceived += MessageReceived; _Mesh.SyncMessageReceived = SyncMessageReceived; // _Mesh.Logger = Logger; _Mesh.Start(); if (_PeerIpPorts != null && _PeerIpPorts.Count > 0) { Console.Write("Adding peers: "); foreach (string curr in _PeerIpPorts) { Console.Write(curr + " "); _Mesh.Add(new MeshPeer(curr, false)); } Console.WriteLine(""); } while (_RunForever) { string userInput = InputString("WatsonMesh [? for help] >", null, false); List <MeshPeer> peers; switch (userInput) { case "?": Menu(); break; case "q": case "quit": _RunForever = false; break; case "c": case "cls": Console.Clear(); break; case "list": peers = _Mesh.GetPeers(); if (peers != null && peers.Count > 0) { Console.WriteLine("Configured peers: " + peers.Count); foreach (MeshPeer curr in peers) { Console.WriteLine(" " + curr.ToString()); } } else { Console.WriteLine("None"); } break; case "failed": peers = _Mesh.GetDisconnectedPeers(); if (peers != null && peers.Count > 0) { Console.WriteLine("Failed peers: " + peers.Count); foreach (MeshPeer currPeer in peers) { Console.WriteLine(" " + currPeer.ToString()); } } else { Console.WriteLine("None"); } break; case "send": Send(); break; case "send md": SendMetadata(); break; case "sendsync": SendSync(); break; case "sendsync md": SendSyncMetadata(); break; case "bcast": Broadcast(); break; case "add": _Mesh.Add( new MeshPeer( InputString("IP:port:", "127.0.0.1:8000", false), false)); break; case "del": _Mesh.Remove( new MeshPeer( InputString("IP:port:", "127.0.0.1:8000", false), false)); break; case "health": Console.WriteLine("Healthy: " + _Mesh.IsHealthy); break; case "nodehealth": Console.WriteLine( _Mesh.IsServerConnected( InputString("IP:Port", "127.0.0.1:8000", false))); break; } } }