public void Execute(int i_arrayIndex) { Entity octreeRootNodeEntity = a_collisionChecksEntities [i_arrayIndex]; // Its value should be 0, if no collision is detected. // And >= 1, if instance collision is detected, or there is more than one collision, // indicating number of collisions. IsCollidingData isCollidingData = a_isCollidingData [octreeRootNodeEntity]; // Stores reference to detected colliding instance. DynamicBuffer <CollisionInstancesBufferElement> a_collisionInstancesBuffer = collisionInstancesBufferElement [octreeRootNodeEntity]; isCollidingData.i_nearestInstanceCollisionIndex = 0; isCollidingData.f_nearestDistance = float.PositiveInfinity; isCollidingData.i_collisionsCount = 0; // Reset colliding instances counter. RootNodeData octreeRootNodeData = a_octreeRootNodeData [octreeRootNodeEntity]; DynamicBuffer <NodeBufferElement> a_nodesBuffer = nodeBufferElement [octreeRootNodeEntity]; DynamicBuffer <NodeInstancesIndexBufferElement> a_nodeInstancesIndexBuffer = nodeInstancesIndexBufferElement [octreeRootNodeEntity]; DynamicBuffer <NodeChildrenBufferElement> a_nodeChildrenBuffer = nodeChildrenBufferElement [octreeRootNodeEntity]; DynamicBuffer <InstanceBufferElement> a_instanceBuffer = instanceBufferElement [octreeRootNodeEntity]; BoundsEntityPair4CollisionData rayEntityPair4CollisionData = a_boundsEntityPair4CollisionData [octreeRootNodeEntity]; // Ray entity pair, for collision checks Entity bounds2CheckEntity = rayEntityPair4CollisionData.bounds2CheckEntity; // Is target octree active if (a_isActiveTag.Exists(bounds2CheckEntity)) { BoundsData checkBounds = a_boundsData [bounds2CheckEntity]; // To even allow instances collision checks, octree must have at least one instance. if (octreeRootNodeData.i_totalInstancesCountInTree > 0) { if (GetCollidingBoundsInstances_Common._GetNodeColliding(octreeRootNodeData, octreeRootNodeData.i_rootNodeIndex, checkBounds.bounds, ref a_collisionInstancesBuffer, ref isCollidingData, a_nodesBuffer, a_nodeChildrenBuffer, a_nodeInstancesIndexBuffer, a_instanceBuffer)) { /* * // Debug * Debug.Log ( "Is colliding." ) ; */ } } } a_isCollidingData [octreeRootNodeEntity] = isCollidingData; // Set back. }
public void Execute(int i_arrayIndex) { Entity octreeRayEntity = a_collisionChecksEntities [i_arrayIndex]; // Its value should be 0, if no collision is detected. // And >= 1, if instance collision is detected, or there is more than one collision, // indicating number of collisions. IsCollidingData isCollidingData = a_isCollidingData [octreeRayEntity]; isCollidingData.i_collisionsCount = 0; // Reset colliding instances counter. // isCollidingData.i_nearestInstanceCollisionIndex = 0 ; // Unused // isCollidingData.f_nearestDistance = float.PositiveInfinity ; // Unused OctreeEntityPair4CollisionData octreeEntityPair4CollisionData = a_octreeEntityPair4CollisionData [octreeRayEntity]; RayData rayData = a_rayData [octreeRayEntity]; RayMaxDistanceData rayMaxDistanceData = a_rayMaxDistanceData [octreeRayEntity]; // Octree entity pair, for collision checks Entity octreeRootNodeEntity = octreeEntityPair4CollisionData.octree2CheckEntity; // Is target octree active if (a_isActiveTag.Exists(octreeRootNodeEntity)) { RootNodeData octreeRootNodeData = a_octreeRootNodeData [octreeRootNodeEntity]; DynamicBuffer <NodeBufferElement> a_nodesBuffer = nodeBufferElement [octreeRootNodeEntity]; DynamicBuffer <NodeInstancesIndexBufferElement> a_nodeInstancesIndexBuffer = nodeInstancesIndexBufferElement [octreeRootNodeEntity]; DynamicBuffer <NodeChildrenBufferElement> a_nodeChildrenBuffer = nodeChildrenBufferElement [octreeRootNodeEntity]; DynamicBuffer <InstanceBufferElement> a_instanceBuffer = instanceBufferElement [octreeRootNodeEntity]; // To even allow instances collision checks, octree must have at least one instance. if (octreeRootNodeData.i_totalInstancesCountInTree > 0) { if (IsRayColliding_Common._IsNodeColliding(octreeRootNodeData, octreeRootNodeData.i_rootNodeIndex, rayData.ray, ref isCollidingData, a_nodesBuffer, a_nodeChildrenBuffer, a_nodeInstancesIndexBuffer, a_instanceBuffer, rayMaxDistanceData.f)) { /* * // Debug * Debug.Log ( "Is colliding." ) ; */ } } } a_isCollidingData [octreeRayEntity] = isCollidingData; // Set back. }
static public void _DebugRays(EntityArray a_collisionChecksEntities, ComponentDataFromEntity <RayData> a_rayData, ComponentDataFromEntity <RayMaxDistanceData> a_rayMaxDistanceData, ComponentDataFromEntity <IsCollidingData> a_isCollidingData, ComponentDataFromEntity <RayEntityPair4CollisionData> a_rayEntityPair4CollisionData, bool canDebugAllChecks, bool canDebugAllrays) { // Debug all, or only one check int i_debugCollisionChecksCount = canDebugAllChecks ? a_collisionChecksEntities.Length : 1; // Debug // ! Ensure test this only with single, or at most few ray entiities. for (int i_collisionChecksIndex = 0; i_collisionChecksIndex < i_debugCollisionChecksCount; i_collisionChecksIndex++) { Entity octreeRayEntity = a_collisionChecksEntities [i_collisionChecksIndex]; Entity octreeRayEntity2; if (!a_rayData.Exists(octreeRayEntity)) { RayEntityPair4CollisionData rayEntityPair4CollisionData = a_rayEntityPair4CollisionData [octreeRayEntity]; octreeRayEntity2 = rayEntityPair4CollisionData.ray2CheckEntity; } else { octreeRayEntity2 = octreeRayEntity; } // Draw all available rays, or signle ray if (canDebugAllrays) { RayData rayData = a_rayData [octreeRayEntity2]; RayMaxDistanceData rayMaxDistanceData = a_rayMaxDistanceData [octreeRayEntity2]; Debug.DrawLine(rayData.ray.origin, rayData.ray.origin + rayData.ray.direction * rayMaxDistanceData.f, Color.red); } else if (i_collisionChecksIndex == 0) { RayData rayData = a_rayData [octreeRayEntity2]; RayMaxDistanceData rayMaxDistanceData = a_rayMaxDistanceData [octreeRayEntity2]; Debug.DrawLine(rayData.ray.origin, rayData.ray.origin + rayData.ray.direction * rayMaxDistanceData.f, Color.red); } IsCollidingData isCollidingData = a_isCollidingData [octreeRayEntity]; if (isCollidingData.i_collisionsCount > 0) { Debug.Log("Is colliding."); } } }
/// <summary> /// /// </summary> /// <param name="a_collisionChecksEntities"></param> /// <param name="a_isCollidingData"></param> /// <param name="collisionInstancesBufferElement"></param> /// <param name="canDebugAllChecks">Debug Log all checks, or only one (first one)</param> static public void _DebugBounds(EntityCommandBuffer ecb, EntityArray a_collisionChecksEntities, ComponentDataFromEntity <IsCollidingData> a_isCollidingData, BufferFromEntity <CollisionInstancesBufferElement> collisionInstancesBufferElement, bool canDebugAllChecks) { // Debug // ! Ensure test this only with single, or at most few ray entiities. // Debug all, or only one check int i_debugCollisionChecksCount = canDebugAllChecks ? a_collisionChecksEntities.Length : 1; for (int i_collisionChecksIndex = 0; i_collisionChecksIndex < i_debugCollisionChecksCount; i_collisionChecksIndex++) { Entity octreeRayEntity = a_collisionChecksEntities [i_collisionChecksIndex]; // Last known instances collisions count. IsCollidingData isCollidingData = a_isCollidingData [octreeRayEntity]; if (isCollidingData.i_collisionsCount > 0) { // Debug.Log ( "Octree: Last known instances collisions count #" + isCollidingData.i_collisionsCount ) ; // Stores reference to detected colliding instance. DynamicBuffer <CollisionInstancesBufferElement> a_collisionInstancesBuffer = collisionInstancesBufferElement [octreeRayEntity]; string s_collidingIDs = ""; CollisionInstancesBufferElement collisionInstancesBuffer; for (int i = 0; i < isCollidingData.i_collisionsCount; i++) { collisionInstancesBuffer = a_collisionInstancesBuffer [i]; s_collidingIDs += collisionInstancesBuffer.i_ID + ", "; } // Test highlight // Highlight.SwitchMethods._Switch ( ecb, closestInstanceEntity ) ; Debug.Log("Is colliding with #" + isCollidingData.i_collisionsCount + " instances of IDs: " + s_collidingIDs); } } // for }
/// <summary> /// /// </summary> /// <param name="a_collisionChecksEntities"></param> /// <param name="a_isCollidingData"></param> /// <param name="canDebugAllChecks">Debug Log all checks, or only one (first one)</param> static public void _DebugBounds(EntityArray a_collisionChecksEntities, ComponentDataFromEntity <IsCollidingData> a_isCollidingData, bool canDebugAllChecks) { // Debug // ! Ensure test this only with single, or at most few ray entiities. // Debug all, or only one check int i_debugCollisionChecksCount = canDebugAllChecks ? a_collisionChecksEntities.Length : 1; for (int i_collisionChecksIndex = 0; i_collisionChecksIndex < i_debugCollisionChecksCount; i_collisionChecksIndex++) // for ( int i_collisionChecksIndex = 0; i_collisionChecksIndex < a_collisionChecksEntities.Length; i_collisionChecksIndex ++ ) { Entity octreeEntity = a_collisionChecksEntities [i_collisionChecksIndex]; IsCollidingData isCollidingData = a_isCollidingData [octreeEntity]; if (isCollidingData.i_collisionsCount > 0) { Debug.Log("Is colliding."); } } }
public void Execute(int i_arrayIndex) { Entity octreeRootNodeEntity = a_collisionChecksEntities [i_arrayIndex]; // Its value should be 0, if no collision is detected. // And >= 1, if instance collision is detected, or there is more than one collision, // indicating number of collisions. IsCollidingData isCollidingData = a_isCollidingData [octreeRootNodeEntity]; // Stores reference to detected colliding instance. DynamicBuffer <CollisionInstancesBufferElement> a_collisionInstancesBuffer = collisionInstancesBufferElement [octreeRootNodeEntity]; isCollidingData.i_nearestInstanceCollisionIndex = 0; isCollidingData.f_nearestDistance = float.PositiveInfinity; isCollidingData.i_collisionsCount = 0; // Reset colliding instances counter. RootNodeData octreeRootNodeData = a_octreeRootNodeData [octreeRootNodeEntity]; DynamicBuffer <NodeBufferElement> a_nodesBuffer = nodeBufferElement [octreeRootNodeEntity]; DynamicBuffer <NodeInstancesIndexBufferElement> a_nodeInstancesIndexBuffer = nodeInstancesIndexBufferElement [octreeRootNodeEntity]; DynamicBuffer <NodeChildrenBufferElement> a_nodeChildrenBuffer = nodeChildrenBufferElement [octreeRootNodeEntity]; DynamicBuffer <InstanceBufferElement> a_instanceBuffer = instanceBufferElement [octreeRootNodeEntity]; RayEntityPair4CollisionData rayEntityPair4CollisionData = a_rayEntityPair4CollisionData [octreeRootNodeEntity]; // Ray entity pair, for collision checks Entity ray2CheckEntity = rayEntityPair4CollisionData.ray2CheckEntity; // Is target octree active if (a_isActiveTag.Exists(ray2CheckEntity)) { RayData rayData = a_rayData [ray2CheckEntity]; RayMaxDistanceData rayMaxDistanceData = a_rayMaxDistanceData [ray2CheckEntity]; // To even allow instances collision checks, octree must have at least one instance. if (octreeRootNodeData.i_totalInstancesCountInTree > 0) { if (GetCollidingRayInstances_Common._GetNodeColliding(octreeRootNodeData, octreeRootNodeData.i_rootNodeIndex, rayData.ray, ref a_collisionInstancesBuffer, ref isCollidingData, a_nodesBuffer, a_nodeChildrenBuffer, a_nodeInstancesIndexBuffer, a_instanceBuffer, rayMaxDistanceData.f)) { /* * // Debug * string s_collidingIDs = "" ; * int i_collisionsCount = isCollidingData.i_collisionsCount ; * * for ( int i = 0; i < i_collisionsCount; i ++ ) * { * CollisionInstancesBufferElement collisionInstancesBuffer = a_collisionInstancesBuffer [i] ; * s_collidingIDs += collisionInstancesBuffer.i_ID + ", " ; * } * * Debug.Log ( "Is colliding with #" + i_collisionsCount + " instances of IDs: " + s_collidingIDs + "; Nearest collided instance is at " + isCollidingData.f_nearestDistance + "m, with index #" + isCollidingData.i_nearestInstanceCollisionIndex ) ; */ } } } a_isCollidingData [octreeRootNodeEntity] = isCollidingData; // Set back. }
/// <summary> /// Returns an collection of instances, that intersect with the specified bounds, if any. Otherwise returns an empty array. See also: IsColliding. /// </summary> /// <param name="i_nodeIndex">Internal octree node index.</param> /// <param name="checkBounds">Bounds to check. Passing by ref as it improves performance with structs.</param> /// <param name="l_resultInstanceIDs">List result.</param> static public bool _GetNodeColliding(RootNodeData octreeRootNodeData, int i_nodeIndex, Bounds checkBounds, ref DynamicBuffer <CollisionInstancesBufferElement> a_collisionInstancesBuffer, ref IsCollidingData isCollidingData, DynamicBuffer <NodeBufferElement> a_nodesBuffer, DynamicBuffer <NodeChildrenBufferElement> a_nodeChildrenBuffer, DynamicBuffer <NodeInstancesIndexBufferElement> a_nodeInstancesIndexBuffer, DynamicBuffer <InstanceBufferElement> a_instanceBuffer) { // float f_distance ; CollisionInstancesBufferElement collisionInstancesBuffer = new CollisionInstancesBufferElement(); NodeBufferElement nodeBuffer = a_nodesBuffer [i_nodeIndex]; // Are the input bounds at least partially in this node? if (!nodeBuffer.bounds.Intersects(checkBounds)) { return(isCollidingData.i_collisionsCount > 0 ? true : false); } if (nodeBuffer.i_instancesCount >= 0) { int i_nodeInstancesIndexOffset = i_nodeIndex * octreeRootNodeData.i_instancesAllowedCount; // Check against any objects in this node for (int i = 0; i < octreeRootNodeData.i_instancesAllowedCount; i++) { NodeInstancesIndexBufferElement nodeInstancesIndexBuffer = a_nodeInstancesIndexBuffer [i_nodeInstancesIndexOffset + i]; // Get index of instance int i_instanceIndex = nodeInstancesIndexBuffer.i; // Check if instance exists, and if has intersecting bounds. if (i_instanceIndex >= 0) { InstanceBufferElement instanceBuffer = a_instanceBuffer [i_instanceIndex]; // Check if instance exists, and if has intersecting bounds. if (instanceBuffer.bounds.Intersects(checkBounds)) { // l_resultInstanceIDs.Add ( instanceBuffer.i_ID ) ; //if ( f_distance < isCollidingData.f_nearestDistance ) //{ // isCollidingData.f_nearestDistance = f_distance ; // isCollidingData.i_nearestInstanceCollisionIndex = isCollidingData.i_collisionsCount ; //} // Is expected, that the required length is no greater than current length + 1 // And is not negative. int i_collisionsCount = isCollidingData.i_collisionsCount; collisionInstancesBuffer.i_ID = instanceBuffer.i_ID; collisionInstancesBuffer.i_version = instanceBuffer.i_entityVersion; // Optional, used when Id is used as entity index // Assign colliding instance ID to buffer. if (a_collisionInstancesBuffer.Length <= i_collisionsCount) { // Expand buffer if needed a_collisionInstancesBuffer.Add(collisionInstancesBuffer); } else { a_collisionInstancesBuffer [i_collisionsCount] = collisionInstancesBuffer; } isCollidingData.i_collisionsCount++; } } } } // Check children for collisions // Check if having children if (nodeBuffer.i_childrenCount > 0) { int i_nodeChildrenIndexOffset = i_nodeIndex * 8; // We checked that is having children. for (int i = 0; i < 8; i++) { NodeChildrenBufferElement nodeChildrenBuffer = a_nodeChildrenBuffer [i_nodeChildrenIndexOffset + i]; int i_nodeChildIndex = nodeChildrenBuffer.i_nodesIndex; // Check if node exists if (i_nodeChildIndex >= 0) { _GetNodeColliding(octreeRootNodeData, i_nodeChildIndex, checkBounds, ref a_collisionInstancesBuffer, ref isCollidingData, a_nodesBuffer, a_nodeChildrenBuffer, a_nodeInstancesIndexBuffer, a_instanceBuffer); } } } return(isCollidingData.i_collisionsCount > 0 ? true : false); }
/// <summary> /// Check if the specified bounds intersect with anything in the tree. See also: GetColliding. /// </summary> /// <param name="i_nodeIndex">Internal octree node index.</param> /// <param name="checkBounds">Bounds to check.</param> /// <returns>True if there was a collision.</returns> static public bool _IsNodeColliding(RootNodeData rootNodeData, int i_nodeIndex, Bounds checkBounds, ref IsCollidingData isCollidingData, DynamicBuffer <NodeBufferElement> a_nodesBuffer, DynamicBuffer <NodeChildrenBufferElement> a_nodeChildrenBuffer, DynamicBuffer <NodeInstancesIndexBufferElement> a_nodeInstancesIndexBuffer, DynamicBuffer <InstanceBufferElement> a_instanceBuffer) { NodeBufferElement nodeBuffer = a_nodesBuffer [i_nodeIndex]; // Are the input bounds at least partially in this node? if (!nodeBuffer.bounds.Intersects(checkBounds)) { return(false); } if (nodeBuffer.i_instancesCount >= 0) { int i_nodeInstancesIndexOffset = i_nodeIndex * rootNodeData.i_instancesAllowedCount; // Check against any objects in this node for (int i = 0; i < rootNodeData.i_instancesAllowedCount; i++) { NodeInstancesIndexBufferElement nodeInstancesIndexBuffer = a_nodeInstancesIndexBuffer [i_nodeInstancesIndexOffset + i]; // Get index of instance int i_instanceIndex = nodeInstancesIndexBuffer.i; // Check if instance exists, and if has intersecting bounds. if (i_instanceIndex >= 0) { InstanceBufferElement instanceBuffer = a_instanceBuffer [i_instanceIndex]; // Check if instance exists, and if has intersecting bounds. if (instanceBuffer.bounds.Intersects(checkBounds)) { isCollidingData.i_collisionsCount = 1; return(true); } } } } // Check children for collisions // Check if having children if (nodeBuffer.i_childrenCount > 0) { int i_nodeChildrenIndexOffset = i_nodeIndex * 8; // We checked that is having children. for (int i = 0; i < 8; i++) { NodeChildrenBufferElement nodeChildrenBuffer = a_nodeChildrenBuffer [i_nodeChildrenIndexOffset + i]; int i_nodeChildIndex = nodeChildrenBuffer.i_nodesIndex; // Check if node exists if (i_nodeChildIndex >= 0) { if (_IsNodeColliding(rootNodeData, i_nodeChildIndex, checkBounds, ref isCollidingData, a_nodesBuffer, a_nodeChildrenBuffer, a_nodeInstancesIndexBuffer, a_instanceBuffer)) { isCollidingData.i_collisionsCount = 1; return(true); } } } } return(false); }
/// <summary> /// Check if the specified ray intersects with anything in the tree. See also: GetColliding. /// </summary> /// <param name="i_nodeIndex">Internal octree node index.</param> /// <param name="checkRay">Ray to check.</param> /// <param name="f_maxDistance">Distance to check.</param> /// <returns>True if there was a collision.</returns> static public bool _IsNodeColliding(RootNodeData rootNodeData, int i_nodeIndex, Ray checkRay, ref IsCollidingData isCollidingData, DynamicBuffer <NodeBufferElement> a_nodesBuffer, DynamicBuffer <NodeChildrenBufferElement> a_nodeChildrenBuffer, DynamicBuffer <NodeInstancesIndexBufferElement> a_nodeInstancesIndexBuffer, DynamicBuffer <InstanceBufferElement> a_instanceBuffer, float f_maxDistance = float.PositiveInfinity) { // Is the input ray at least partially in this node? float f_distance; NodeBufferElement nodeBuffer = a_nodesBuffer [i_nodeIndex]; if (!nodeBuffer.bounds.IntersectRay(checkRay, out f_distance) || f_distance > f_maxDistance) { return(false); } if (nodeBuffer.i_instancesCount >= 0) { int i_nodeInstancesIndexOffset = i_nodeIndex * rootNodeData.i_instancesAllowedCount; // Check against any objects in this node for (int i = 0; i < rootNodeData.i_instancesAllowedCount; i++) { NodeInstancesIndexBufferElement nodeInstancesIndexBuffer = a_nodeInstancesIndexBuffer [i_nodeInstancesIndexOffset + i]; // Get index of instance int i_instanceIndex = nodeInstancesIndexBuffer.i; // Check if instance exists, and if has intersecting bounds. if (i_instanceIndex >= 0) { InstanceBufferElement instanceBuffer = a_instanceBuffer [i_instanceIndex]; if (instanceBuffer.bounds.IntersectRay(checkRay, out f_distance) && f_distance <= f_maxDistance) { isCollidingData.i_collisionsCount = 1; // Is colliding return(true); } } } } // Check children for collisions // Check if having children if (nodeBuffer.i_childrenCount > 0) { int i_nodeChildrenIndexOffset = i_nodeIndex * 8; // We checked that is having children. for (int i = 0; i < 8; i++) { NodeChildrenBufferElement nodeChildrenBuffer = a_nodeChildrenBuffer [i_nodeChildrenIndexOffset + i]; int i_nodeChildIndex = nodeChildrenBuffer.i_nodesIndex; // Check if node exists if (i_nodeChildIndex >= 0) { if (_IsNodeColliding(rootNodeData, i_nodeChildIndex, checkRay, ref isCollidingData, a_nodesBuffer, a_nodeChildrenBuffer, a_nodeInstancesIndexBuffer, a_instanceBuffer, f_maxDistance)) { isCollidingData.i_collisionsCount = 1; // Is colliding return(true); } } } } return(false); }
/// <summary> /// /// </summary> /// <param name="a_collisionChecksEntities"></param> /// <param name="a_rayData"></param> /// <param name="a_rayMaxDistanceData"></param> /// <param name="a_isCollidingData"></param> /// <param name="collisionInstancesBufferElement"></param> /// <param name="canDebugAllChecks">Debug Log all checks, or only one (first one)</param> /// <param name="canDebugAllrays">Draw all, or only single ray (first one).</param> static public void _DebugRays(EntityCommandBuffer ecb, EntityArray a_collisionChecksEntities, ComponentDataFromEntity <RayData> a_rayData, ComponentDataFromEntity <RayMaxDistanceData> a_rayMaxDistanceData, ComponentDataFromEntity <IsCollidingData> a_isCollidingData, BufferFromEntity <CollisionInstancesBufferElement> collisionInstancesBufferElement, ComponentDataFromEntity <RayEntityPair4CollisionData> a_rayEntityPair4CollisionData, bool canDebugAllChecks, bool canDebugAllrays) { // Debug // ! Ensure test this only with single, or at most few ray entiities. // if ( !canDebugAllrays ) // Debug all, or only one check int i_debugCollisionChecksCount = canDebugAllChecks ? a_collisionChecksEntities.Length : 1; for (int i_collisionChecksIndex = 0; i_collisionChecksIndex < i_debugCollisionChecksCount; i_collisionChecksIndex++) { Entity octreeRayEntity = a_collisionChecksEntities [i_collisionChecksIndex]; Entity octreeRayEntity2; if (!a_rayData.Exists(octreeRayEntity)) { RayEntityPair4CollisionData rayEntityPair4CollisionData = a_rayEntityPair4CollisionData [octreeRayEntity]; octreeRayEntity2 = rayEntityPair4CollisionData.ray2CheckEntity; } else { octreeRayEntity2 = octreeRayEntity; } // Draw all available rays, or signle ray if (canDebugAllrays) { RayData rayData = a_rayData [octreeRayEntity2]; RayMaxDistanceData rayMaxDistanceData = a_rayMaxDistanceData [octreeRayEntity2]; Debug.DrawLine(rayData.ray.origin, rayData.ray.origin + rayData.ray.direction * rayMaxDistanceData.f, Color.red); } else if (i_collisionChecksIndex == 0) { RayData rayData = a_rayData [octreeRayEntity2]; RayMaxDistanceData rayMaxDistanceData = a_rayMaxDistanceData [octreeRayEntity2]; Debug.DrawLine(rayData.ray.origin, rayData.ray.origin + rayData.ray.direction * rayMaxDistanceData.f, Color.red); } //} // Last known instances collisions count. IsCollidingData isCollidingData = a_isCollidingData [octreeRayEntity]; if (isCollidingData.i_collisionsCount > 0) { // Debug.Log ( "Octree: Last known instances collisions count #" + isCollidingData.i_collisionsCount ) ; // Stores reference to detected colliding instance. DynamicBuffer <CollisionInstancesBufferElement> a_collisionInstancesBuffer = collisionInstancesBufferElement [octreeRayEntity]; string s_collidingIDs = ""; CollisionInstancesBufferElement collisionInstancesBuffer; for (int i = 0; i < isCollidingData.i_collisionsCount; i++) { collisionInstancesBuffer = a_collisionInstancesBuffer [i]; s_collidingIDs += collisionInstancesBuffer.i_ID + ", "; } CollisionInstancesBufferElement closestCollisionInstance = a_collisionInstancesBuffer [isCollidingData.i_nearestInstanceCollisionIndex]; Entity closestInstanceEntity = new Entity() { Index = closestCollisionInstance.i_ID, Version = closestCollisionInstance.i_version }; // Test highlight Highlight.SwitchMethods._Switch(ecb, closestInstanceEntity); Debug.Log("Is colliding with #" + isCollidingData.i_collisionsCount + " instances of IDs: " + s_collidingIDs + "; Nearest collided instance is at " + isCollidingData.f_nearestDistance + "m, with ID #" + a_collisionInstancesBuffer [isCollidingData.i_nearestInstanceCollisionIndex].i_ID); } } // for }
/// <summary> /// Returns an array of objects that intersect with the specified ray, if any. Otherwise returns an empty array. See also: IsColliding. /// </summary> /// <param name="i_nodeIndex">Internal octree node index.</param> /// <param name="checkRay">Ray to check. Passing by ref as it improves performance with structs.</param> /// <param name="l_resultInstanceIDs">List result.</param> /// <param name="i_nearestIndex">Nerest collision index from the lits.</param> /// <param name="f_nearestDistance">Nerest collision distance.</param> /// <param name="maxDistance">Distance to check.</param> /// <returns>Instances index, that intersect with the specified ray.</returns> static public bool _GetNodeColliding(RootNodeData rootNodeData, int i_nodeIndex, Ray checkRay, ref DynamicBuffer <CollisionInstancesBufferElement> a_collisionInstancesBuffer, ref IsCollidingData isCollidingData, DynamicBuffer <NodeBufferElement> a_nodesBuffer, DynamicBuffer <NodeChildrenBufferElement> a_nodeChildrenBuffer, DynamicBuffer <NodeInstancesIndexBufferElement> a_nodeInstancesIndexBuffer, DynamicBuffer <InstanceBufferElement> a_instanceBuffer, float f_maxDistance = float.PositiveInfinity) { float f_distance; NodeBufferElement nodeBuffer = a_nodesBuffer [i_nodeIndex]; if (!nodeBuffer.bounds.IntersectRay(checkRay, out f_distance) || f_distance > f_maxDistance) { return(isCollidingData.i_collisionsCount > 0 ? true : false); } if (nodeBuffer.i_instancesCount > 0) { int i_nodeInstancesIndexOffset = i_nodeIndex * rootNodeData.i_instancesAllowedCount; CollisionInstancesBufferElement collisionInstancesBuffer = new CollisionInstancesBufferElement(); // Check against any objects in this node for (int i = 0; i < rootNodeData.i_instancesAllowedCount; i++) { NodeInstancesIndexBufferElement nodeInstancesIndexBuffer = a_nodeInstancesIndexBuffer [i_nodeInstancesIndexOffset + i]; // Get index of instance int i_instanceIndex = nodeInstancesIndexBuffer.i; // Check if instance exists, and if has intersecting bounds. if (i_instanceIndex >= 0) { InstanceBufferElement instanceBuffer = a_instanceBuffer [i_instanceIndex]; if (instanceBuffer.bounds.IntersectRay(checkRay, out f_distance) && f_distance <= f_maxDistance) { if (f_distance < isCollidingData.f_nearestDistance) { isCollidingData.f_nearestDistance = f_distance; isCollidingData.i_nearestInstanceCollisionIndex = isCollidingData.i_collisionsCount; } // Is expected, that the required length is no greater than current length + 1 // And is not negative. int i_collisionsCount = isCollidingData.i_collisionsCount; collisionInstancesBuffer.i_ID = instanceBuffer.i_ID; collisionInstancesBuffer.i_version = instanceBuffer.i_entityVersion; // Optional, used when Id is used as entity index // Assign colliding instance ID to buffer. if (a_collisionInstancesBuffer.Length <= i_collisionsCount) { // Expand buffer if needed a_collisionInstancesBuffer.Add(collisionInstancesBuffer); } else { a_collisionInstancesBuffer [i_collisionsCount] = collisionInstancesBuffer; } isCollidingData.i_collisionsCount++; } } } } // Check children for collisions // Check if having children if (nodeBuffer.i_childrenCount > 0) { int i_nodeChildrenIndexOffset = i_nodeIndex * 8; // We checked that is having children. for (int i = 0; i < 8; i++) { NodeChildrenBufferElement nodeChildrenBuffer = a_nodeChildrenBuffer [i_nodeChildrenIndexOffset + i]; int i_nodeChildIndex = nodeChildrenBuffer.i_nodesIndex; // Check if node exists if (i_nodeChildIndex >= 0) { _GetNodeColliding(rootNodeData, i_nodeChildIndex, checkRay, ref a_collisionInstancesBuffer, ref isCollidingData, a_nodesBuffer, a_nodeChildrenBuffer, a_nodeInstancesIndexBuffer, a_instanceBuffer, f_maxDistance); } } } return(isCollidingData.i_collisionsCount > 0 ? true : false); }