mirror of
https://github.com/RandomityGuy/MBHaxe.git
synced 2025-10-30 08:11:25 +00:00
166 lines
4.6 KiB
Haxe
166 lines
4.6 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):Bool {
|
|
var invMatrix = transform.clone();
|
|
invMatrix.invert();
|
|
var rStart = rayOrigin.transformed(invMatrix);
|
|
var rDir = rayDirection.transformed(invMatrix);
|
|
var intersections = octree.raycast(rStart, rDir);
|
|
for (i in intersections) {
|
|
i.point.transform(transform);
|
|
}
|
|
if (intersections.length > 0) {
|
|
intersectionPoint.load(intersections[0].point);
|
|
}
|
|
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; // surface.normals[surface.indices[i]];
|
|
cinfo.point = closest;
|
|
// cinfo.collider = this;
|
|
cinfo.velocity = this.velocity;
|
|
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;
|
|
}
|
|
}
|