mirror of
				https://github.com/RandomityGuy/MBHaxe.git
				synced 2025-10-30 08:11:25 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			169 lines
		
	
	
	
		
			4.7 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
	
		
			4.7 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
package collision;
 | 
						|
 | 
						|
import src.TimeState;
 | 
						|
import src.GameObject;
 | 
						|
import dif.math.Point3F;
 | 
						|
import dif.math.PlaneF;
 | 
						|
import h3d.col.Plane;
 | 
						|
import octree.Octree;
 | 
						|
import h3d.col.Ray;
 | 
						|
import h3d.Vector;
 | 
						|
import octree.IOctreeObject;
 | 
						|
import h3d.Matrix;
 | 
						|
import h3d.col.Bounds;
 | 
						|
 | 
						|
class CollisionEntity implements IOctreeObject {
 | 
						|
	public var boundingBox:Bounds;
 | 
						|
 | 
						|
	public var octree:Octree;
 | 
						|
 | 
						|
	public var surfaces:Array<CollisionSurface>;
 | 
						|
 | 
						|
	public var priority:Int;
 | 
						|
	public var position:Int;
 | 
						|
	public var velocity:Vector = new Vector();
 | 
						|
 | 
						|
	public var transform:Matrix;
 | 
						|
	public var go:GameObject;
 | 
						|
 | 
						|
	public var userData:Int;
 | 
						|
 | 
						|
	public function new(go:GameObject) {
 | 
						|
		this.go = go;
 | 
						|
		this.octree = new Octree();
 | 
						|
		this.surfaces = [];
 | 
						|
		this.transform = Matrix.I();
 | 
						|
	}
 | 
						|
 | 
						|
	public function addSurface(surface:CollisionSurface) {
 | 
						|
		if (surface.points.length > 0) {
 | 
						|
			this.octree.insert(surface);
 | 
						|
			this.surfaces.push(surface);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	public function setTransform(transform:Matrix) {
 | 
						|
		if (this.transform == transform)
 | 
						|
			return;
 | 
						|
		this.transform = transform;
 | 
						|
		generateBoundingBox();
 | 
						|
	}
 | 
						|
 | 
						|
	public function generateBoundingBox() {
 | 
						|
		var boundingBox = new Bounds();
 | 
						|
		for (surface in this.surfaces) {
 | 
						|
			var tform = surface.boundingBox.clone();
 | 
						|
			tform.transform(transform);
 | 
						|
			boundingBox.add(tform);
 | 
						|
		}
 | 
						|
		this.boundingBox = boundingBox;
 | 
						|
	}
 | 
						|
 | 
						|
	public function isIntersectedByRay(rayOrigin:Vector, rayDirection:Vector, intersectionPoint:Vector, intersectionNormal:Vector):Bool {
 | 
						|
		var invMatrix = transform.clone();
 | 
						|
		invMatrix.invert();
 | 
						|
		var rStart = rayOrigin.clone();
 | 
						|
		rStart.transform(invMatrix);
 | 
						|
		var rDir = rayDirection.transformed3x3(invMatrix);
 | 
						|
		var intersections = octree.raycast(rStart, rDir);
 | 
						|
		for (i in intersections) {
 | 
						|
			i.point.transform(transform);
 | 
						|
			i.normal.transform3x3(transform);
 | 
						|
		}
 | 
						|
		if (intersections.length > 0) {
 | 
						|
			intersectionPoint.load(intersections[0].point);
 | 
						|
			intersectionNormal.load(intersections[0].normal);
 | 
						|
		}
 | 
						|
		return intersections.length > 0;
 | 
						|
	}
 | 
						|
 | 
						|
	public function getElementType() {
 | 
						|
		return 2;
 | 
						|
	}
 | 
						|
 | 
						|
	public function setPriority(priority:Int) {
 | 
						|
		this.priority = priority;
 | 
						|
	}
 | 
						|
 | 
						|
	public function sphereIntersection(collisionEntity:SphereCollisionEntity, timeState:TimeState) {
 | 
						|
		var position = collisionEntity.transform.getPosition();
 | 
						|
		var velocity = collisionEntity.velocity;
 | 
						|
		var radius = collisionEntity.radius;
 | 
						|
 | 
						|
		var invMatrix = transform.clone();
 | 
						|
		invMatrix.invert();
 | 
						|
		var localpos = position.clone();
 | 
						|
		localpos.transform(invMatrix);
 | 
						|
		var sphereBounds = new Bounds();
 | 
						|
		sphereBounds.addSpherePos(localpos.x, localpos.y, localpos.z, radius * 1.1);
 | 
						|
		var surfaces = octree.boundingSearch(sphereBounds);
 | 
						|
 | 
						|
		var tform = transform.clone();
 | 
						|
		// tform.setPosition(tform.getPosition().add(this.velocity.multiply(timeState.dt)));
 | 
						|
 | 
						|
		function toDifPoint(pt:Vector) {
 | 
						|
			return new Point3F(pt.x, pt.y, pt.z);
 | 
						|
		}
 | 
						|
 | 
						|
		function fromDifPoint(pt:Point3F) {
 | 
						|
			return new Vector(pt.x, pt.y, pt.z);
 | 
						|
		}
 | 
						|
 | 
						|
		var contacts = [];
 | 
						|
 | 
						|
		for (obj in surfaces) {
 | 
						|
			var surface:CollisionSurface = cast obj;
 | 
						|
 | 
						|
			var surfaceBestContact:CollisionInfo = null;
 | 
						|
			var bestDot:Float = Math.NEGATIVE_INFINITY;
 | 
						|
 | 
						|
			var i = 0;
 | 
						|
			while (i < surface.indices.length) {
 | 
						|
				var v0 = surface.points[surface.indices[i]].transformed(tform);
 | 
						|
				var v = surface.points[surface.indices[i + 1]].transformed(tform);
 | 
						|
				var v2 = surface.points[surface.indices[i + 2]].transformed(tform);
 | 
						|
 | 
						|
				var surfacenormal = surface.normals[surface.indices[i]].transformed3x3(transform);
 | 
						|
 | 
						|
				var res = Collision.IntersectTriangleSphere(v0, v, v2, surfacenormal, position, radius);
 | 
						|
				var closest = res.point;
 | 
						|
				// var closest = Collision.ClosestPtPointTriangle(position, radius, v0, v, v2, surfacenormal);
 | 
						|
				if (closest != null) {
 | 
						|
					if (position.sub(closest).lengthSq() <= radius * radius) {
 | 
						|
						var normal = res.normal;
 | 
						|
 | 
						|
						if (position.sub(closest).dot(surfacenormal) > 0) {
 | 
						|
							normal.normalize();
 | 
						|
 | 
						|
							// We find the normal that is closest to the surface normal, sort of fixes weird edge cases of when colliding with
 | 
						|
							var testDot = normal.dot(surfacenormal);
 | 
						|
							if (testDot > bestDot) {
 | 
						|
								bestDot = testDot;
 | 
						|
 | 
						|
								var cinfo = new CollisionInfo();
 | 
						|
								cinfo.normal = normal;
 | 
						|
								cinfo.point = closest;
 | 
						|
								// cinfo.collider = this;
 | 
						|
								cinfo.velocity = this.velocity.clone();
 | 
						|
								cinfo.contactDistance = closest.distance(position);
 | 
						|
								cinfo.otherObject = this.go;
 | 
						|
								// cinfo.penetration = radius - (position.sub(closest).dot(normal));
 | 
						|
								cinfo.restitution = surface.restitution;
 | 
						|
								cinfo.force = surface.force;
 | 
						|
								cinfo.friction = surface.friction;
 | 
						|
								surfaceBestContact = cinfo;
 | 
						|
							}
 | 
						|
						}
 | 
						|
					}
 | 
						|
				}
 | 
						|
 | 
						|
				i += 3;
 | 
						|
			}
 | 
						|
 | 
						|
			if (surfaceBestContact != null)
 | 
						|
				contacts.push(surfaceBestContact);
 | 
						|
		}
 | 
						|
 | 
						|
		return contacts;
 | 
						|
	}
 | 
						|
}
 |