public bool Pointcast(Vector3 point) { var jPoint = point.ToJVector(); return(GJKCollide.Pointcast(this.body.Shape, ref this.body.orientation, ref this.body.position, ref jPoint)); }
protected override void Update(GameTime gameTime) { // Allows the game to exit if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) { this.Exit(); } KeyboardState keys = Keyboard.GetState(); JVector moveVector = JVector.Zero; float amountOfMovement = 0.05f; if (keys.IsKeyDown(Keys.Right)) { moveVector.X += amountOfMovement; } if (keys.IsKeyDown(Keys.Left)) { moveVector.X -= amountOfMovement; } if (keys.IsKeyDown(Keys.Down)) { moveVector.Y -= amountOfMovement; } if (keys.IsKeyDown(Keys.Up)) { moveVector.Y += amountOfMovement; } body1.Position += moveVector; if (keys.IsKeyDown(Keys.OemPlus) && oldState.IsKeyUp(Keys.OemPlus)) { GJKCollide.MaxIterations++; } if (keys.IsKeyDown(Keys.OemMinus) && oldState.IsKeyUp(Keys.OemMinus)) { GJKCollide.MaxIterations--; } GJKCollide.MaxIterations = (int)JMath.Clamp(GJKCollide.MaxIterations, 0, 25); bool changeShape = false; if (keys.IsKeyDown(Keys.D1) && oldState.IsKeyUp(Keys.D1)) { shapeType++; changeShape = true; } if (keys.IsKeyDown(Keys.D2) && oldState.IsKeyUp(Keys.D2)) { shapeType--; changeShape = true; } shapeType = (int)JMath.Clamp(shapeType, 0, 2); if (changeShape) { Random r = new Random(); switch (shapeType) { case 0: // circle body1 = new RigidBody(new CircleShape((float)r.NextDouble() * 3f)); break; case 1: // capsule body1 = new RigidBody(new CapsuleShape((float)r.NextDouble() * 3f, (float)r.NextDouble() * 1f)); break; case 2: // box body1 = new RigidBody(new BoxShape((float)r.NextDouble() * 3f, (float)r.NextDouble() * 3f)); break; } } body1.Orientation += 0.005f; body2.Orientation -= 0.005f; JMatrix o1 = JMatrix.CreateRotationZ(body1.Orientation); JMatrix o2 = JMatrix.CreateRotationZ(body2.Orientation); JVector pos1 = body1.Position; JVector pos2 = body2.Position; JVector point2; sw.Start(); hit = GJKCollide.ClosestPoints(body1.Shape, body2.Shape, ref o1, ref o2, ref pos1, ref pos2, out point, out point2, out normal); sw.Stop(); penetration = JVector.Distance(point, point2); ticks = sw.ElapsedTicks; sw.Reset(); DebugDrawer.DrawPoint(point2); DebugDrawer.DrawPoint(point); DebugDrawer.Color = Color.Red; DebugDrawer.DrawLine(JVector.Zero, normal); DebugDrawer.Color = Color.Black; DebugDrawer.DrawLine(JVector.Up, JVector.Down); DebugDrawer.DrawLine(JVector.Left, JVector.Right); body1.DebugDraw(DebugDrawer); body2.DebugDraw(DebugDrawer); oldState = keys; base.Update(gameTime); }
/// <summary> /// Adds a body to the fluid. Only bodies which where added /// to the fluidvolume gets affected by buoyancy forces. /// </summary> /// <param name="body">The body which should be added.</param> /// <param name="subdivisions">The object is subdivided in smaller objects /// for which buoyancy force is calculated. The more subdivisons the better /// the results. Note that the total number of subdivisions is subdivisions³.</param> public void Add(RigidBody body, int subdivisions) { List <JVector> massPoints = new List <JVector>(); JVector testVector; JVector diff = body.Shape.BoundingBox.Max - body.Shape.BoundingBox.Min; if (diff.IsNearlyZero()) { throw new InvalidOperationException("BoundingBox volume of the shape is zero."); } Multishape ms = body.Shape as Multishape; int values = 0; if (ms != null) { JBBox largeBox = JBBox.LargeBox; values = ms.Prepare(ref largeBox); } for (int i = 0; i < subdivisions; i++) { for (int e = 0; e < subdivisions; e++) { for (int k = 0; k < subdivisions; k++) { testVector.X = body.Shape.BoundingBox.Min.X + (diff.X / (float)(subdivisions - 1)) * ((float)i); testVector.Y = body.Shape.BoundingBox.Min.Y + (diff.Y / (float)(subdivisions - 1)) * ((float)e); testVector.Z = body.Shape.BoundingBox.Min.Z + (diff.Z / (float)(subdivisions - 1)) * ((float)k); JMatrix ident = JMatrix.Identity; JVector zero = JVector.Zero; if (ms != null) { for (int j = 0; j < values; j++) { ms.SetCurrentShape(j); if (GJKCollide.Pointcast(body.Shape, ref ident, ref zero, ref testVector)) { massPoints.Add(testVector); } } } else { if (GJKCollide.Pointcast(body.Shape, ref ident, ref zero, ref testVector)) { massPoints.Add(testVector); } } } } } samples.Add(body.Shape, massPoints.ToArray()); bodies.Add(body); }
//int sampleCount = 50; //float distance = 4.0f; public void UpdateAmbientOcclusion(Model model, Group occluders, string mapName) { #if false // \todo fix GeometryMesh mesh = model.Batch.MeshSource as GeometryMesh; if (mesh == null) { return; } Geometry geometry = mesh.Geometry; model.UpdateOctree(); var shape = new TriangleMeshShape(model.Octree); shape.SphericalExpansion = 0.0f; #if VISUALIZE_RAYS sceneManager.DebugLineRenderer.Begin(); #endif var pointLocations = geometry.PointAttributes.Find <Vector3>("point_locations"); var polygonCentroids = geometry.PolygonAttributes.Find <Vector3>("polygon_centroids"); var pointNormals = geometry.PointAttributes.Find <Vector3>(mapName); var cornerNormals = geometry.CornerAttributes.Contains <Vector3>("corner_normals") ? geometry.CornerAttributes.Find <Vector3>("corner_normals") : null; var cornerColors = geometry.CornerAttributes.FindOrCreate <Vector4>("corner_colors"); cornerColors.Clear(); int badCount = 0; foreach (Polygon polygon in geometry.Polygons) { foreach (Corner corner in polygon.Corners) { Point point = corner.Point; // Start from corner position slightly moved towards polygon center Vector3 initialEye = Vector3.Mix(pointLocations[point], polygonCentroids[polygon], 0.001f); Vector3 normal; if ( (cornerNormals != null) && (cornerNormals.ContainsKey(corner) == true) ) { normal = cornerNormals[corner]; } else { normal = pointNormals[point]; } JMatrix orientation = JMatrix.Identity; JMatrix invOrientation = JMatrix.Identity; Vector3 modelPosition = Vector3.Zero; // Slightly up from surface initialEye += normal * 0.01f; int visibility = sampleCount; JVector position = Conversions.JVector(modelPosition); JVector direction; JVector jnormal; Vector3 eye = initialEye; JVector origin = Conversions.JVector(eye); // Sample a few directions for (int c = 0; c < sampleCount; ++c) { // Get a random direction until it points up from the surface Vector3 sampleDirection; float dot; do { sampleDirection = Random(); dot = Vector3.Dot(normal, sampleDirection); }while(dot < 0.25f); // Scale direction = Conversions.JVector(sampleDirection * distance); bool hit = false; { float tempFraction; if (shape is Multishape) { Multishape ms = (shape as Multishape).RequestWorkingClone(); JVector tempNormal; int msLength = ms.Prepare(ref origin, ref direction); for (int i = 0; i < msLength; i++) { ms.SetCurrentShape(i); if ( GJKCollide.Raycast( ms, ref orientation, ref invOrientation, ref position, ref origin, ref direction, out tempFraction, out tempNormal ) ) { hit = true; break; } } ms.ReturnWorkingClone(); } else { hit = GJKCollide.Raycast( shape, ref orientation, ref invOrientation, ref position, ref origin, ref direction, out tempFraction, out jnormal ); } } if (hit) { visibility -= 1; } Vector3 root = new Vector3(origin.X, origin.Y, origin.Z); Vector3 tip = root + 0.02f * new Vector3(direction.X, direction.Y, direction.Z); #if VISUALIZE_RAYS sceneManager.DebugLineRenderer.Line( root, Vector4.Zero, tip, (hit ? Vector4.UnitX : Vector4.UnitY) ); #endif } float visibilityFloat = (float)(visibility) / (float)(sampleCount); cornerColors[corner] = new Vector4(visibilityFloat, visibilityFloat, visibilityFloat, 1.0f); } } mesh.Geometry.ComputePolygonCentroids(); mesh.Geometry.ComputePolygonNormals(); mesh.Geometry.SmoothNormalize("corner_normals", "polygon_normals", (2.0f * (float)Math.PI)); mesh.Geometry.SmoothAverage("corner_colors", mapName); mesh.BuildMeshFromGeometry(BufferUsageHint.StaticDraw, NormalStyle.CornerNormals); //UpdateMeshCornerColors(mesh); Debug.WriteLine("bad count = " + badCount.ToString()); #if VISUALIZE_RAYS sceneManager.DebugLineRenderer.End(); sceneManager.DebugFrame = model.Frame; #endif //model.Name = "AmbientOcclusion(" + model.Name + ")"; #endif }