private void RotateHead(VoxelModelPartState partState, VoxelModelInstance instance, BoundingBox bb, out Matrix result) { var move = (bb.Maximum - bb.Minimum) / 2; var partTransform = partState.GetTransformation(); // get the point of the head center move = Vector3.TransformCoordinate(move, partTransform * Matrix.RotationQuaternion(instance.Rotation)); result = partTransform * Matrix.RotationQuaternion(instance.Rotation) * Matrix.Translation(-move) * Matrix.RotationQuaternion(Quaternion.Invert(instance.Rotation)) * Matrix.RotationQuaternion(instance.HeadRotation) * Matrix.Translation(move); }
private static bool IsCollidingWithModel(VisualEntity entityTesting, BoundingBox playerBoundingBox2Evaluate) { var visualVoxelEntity = entityTesting as VisualVoxelEntity; if (visualVoxelEntity == null) { return(false); } var instance = visualVoxelEntity.VoxelEntity.ModelInstance; if (instance == null) { return(false); } int index; bool collisionDetected = false; //Check Against all existing "Sub-Cube" model //Get current Active state = A model can have multiple "State" (Like open, close, mid open, ...) var activeModelState = instance.State; var visualModel = visualVoxelEntity.VisualVoxelModel; //For each Part in the model (A model can be composed of several parts) for (int partId = 0; partId < visualModel.VoxelModel.Parts.Count && !collisionDetected; partId++) { VoxelModelPartState partState = activeModelState.PartsStates[partId]; // it is possible that there is no frame, so no need to check anything if (partState.ActiveFrame == byte.MaxValue) { continue; } VoxelModelPart part = visualModel.VoxelModel.Parts[partId]; BoundingBox frameBoundingBox = visualModel.VisualVoxelFrames[partState.ActiveFrame].BoundingBox; //Get Current Active part Frame = In animation case, the frame will be different when time passing by ... (Time depends) var activeframe = visualModel.VoxelModel.Frames[partState.ActiveFrame]; //one active at a time Matrix invertedEntityWorldMatrix = partState.GetTransformation() * Matrix.RotationQuaternion(instance.Rotation) * instance.World; invertedEntityWorldMatrix.Invert(); BoundingBox PlayerBBInEntitySpace = playerBoundingBox2Evaluate.Transform(invertedEntityWorldMatrix); // if we don't intersect part BB then there is no reason to check each block BB if (!frameBoundingBox.Intersects(ref PlayerBBInEntitySpace)) { continue; } //Check each frame Body part Vector3I chunkSize = activeframe.BlockData.ChunkSize; byte[] data = activeframe.BlockData.BlockBytes; index = -1; //Get all sub block not empty for (int z = 0; z < chunkSize.Z && !collisionDetected; z++) { for (int x = 0; x < chunkSize.X && !collisionDetected; x++) { for (int y = 0; y < chunkSize.Y && !collisionDetected; y++) { index++; //Get cube if (data[index] > 0) { //Collision checking against this point. if (PlayerBBInEntitySpace.Minimum.X > x + 1 || x > PlayerBBInEntitySpace.Maximum.X) { continue; //No collision } if (PlayerBBInEntitySpace.Minimum.Y > y + 1 || y > PlayerBBInEntitySpace.Maximum.Y) { continue; //No collision } if (PlayerBBInEntitySpace.Minimum.Z > z + 1 || z > PlayerBBInEntitySpace.Maximum.Z) { continue; //No collision } //Collision HERE !!! collisionDetected = true; } } } } } return(collisionDetected); }
/// <summary> /// Checks each part of the model for intersection /// </summary> /// <param name="entity"></param> /// <param name="pickRay"></param> /// <param name="intersectionPoint"></param> /// <param name="normal"></param> /// <param name="dist"></param> /// <returns></returns> public static bool ModelRayIntersection(VisualEntity entity, Ray pickRay, out Vector3 intersectionPoint, out Vector3I normal, out float dist) { intersectionPoint = new Vector3(); normal = new Vector3I(); dist = float.MaxValue; var visualVoxelEntity = entity as VisualVoxelEntity; if (visualVoxelEntity == null) { return(false); } var instance = visualVoxelEntity.VoxelEntity.ModelInstance; bool collisionDetected = false; //Check Against all existing "Sub-Cube" model //Get current Active state = A model can have multiple "State" (Like open, close, mid open, ...) var activeModelState = instance.State; var visualModel = visualVoxelEntity.VisualVoxelModel; if (visualModel == null || visualModel.VoxelModel != instance.VoxelModel) { return(false); } //For each Part in the model (A model can be composed of several parts) for (int partId = 0; partId < visualModel.VoxelModel.Parts.Count; partId++) { VoxelModelPartState partState = activeModelState.PartsStates[partId]; // it is possible that there is no frame, so no need to check it if (partState.ActiveFrame == byte.MaxValue) { continue; } BoundingBox frameBoundingBox = visualModel.VisualVoxelFrames[partState.ActiveFrame].BoundingBox; //Get Current Active part Frame = In animation case, the frame will be different when time passing by ... (Time depends) var activeframe = visualModel.VoxelModel.Frames[partState.ActiveFrame]; //one active at a time Matrix invertedEntityWorldMatrix = partState.GetTransformation() * Matrix.RotationQuaternion(instance.Rotation) * instance.World; Matrix entityWorldMatrix = invertedEntityWorldMatrix; invertedEntityWorldMatrix.Invert(); // convert ray to entity space var ray = pickRay.Transform(invertedEntityWorldMatrix); float partDistance; // if we don't intersect part BB then there is no reason to check each block BB if (!Collision.RayIntersectsBox(ref ray, ref frameBoundingBox, out partDistance)) { continue; } // don't check part that is far than already found intersection if (partDistance >= dist) { continue; } //Check each frame Body part Vector3I chunkSize = activeframe.BlockData.ChunkSize; byte[] data = activeframe.BlockData.BlockBytes; int index = -1; //Get all sub block not empty for (var z = 0; z < chunkSize.Z; z++) { for (var x = 0; x < chunkSize.X; x++) { for (var y = 0; y < chunkSize.Y; y++) { index++; //Get cube if (data[index] > 0) { //Collision checking against this ray var box = new BoundingBox(new Vector3(x, y, z), new Vector3(x + 1, y + 1, z + 1)); float blockDist; if (Collision.RayIntersectsBox(ref ray, ref box, out blockDist) && blockDist < dist) { dist = blockDist; Collision.RayIntersectsBox(ref ray, ref box, out intersectionPoint); normal = box.GetPointNormal(intersectionPoint); intersectionPoint = Vector3.TransformCoordinate(intersectionPoint, entityWorldMatrix); collisionDetected = true; } } } } } } return(collisionDetected); }