Files
Webcam/include/modules/script_squirrel/legacy/collision_binding.cpp

542 lines
15 KiB
C++

/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "scene3d/mitem.h"
#include "binding_helpers.h"
using namespace GS;
using namespace GS::S3D;
using namespace GS::Script;
//------------------------------------------------------------------------------
#define __SQ_TEST_ITEM_PHYSIC if (!item->physic_item) return sq_throwerror(vm, "No physic interface.");
SQInteger ItemSetSelfMask(HSQUIRRELVM vm)
{
__SQ_GETSTART(2)
__SQ_GETSAFEPTR(item, MItem, typetag_Item)
__SQ_GETINT(mask)
__SQ_GETEND
__SQ_TEST_ITEM_PHYSIC
item->physic_item->SetSelfMask(mask);
__SQ_RETURN
}
SQInteger ItemCollisionActivate(HSQUIRRELVM vm)
{
__SQ_GETSTART(2)
__SQ_GETSAFEPTR(item, MItem, typetag_Item)
__SQ_GETBOOL(active)
__SQ_GETEND
__SQ_TEST_ITEM_PHYSIC
item->physic_item->SetActive(asbool(active));
__SQ_RETURN
}
SQInteger ItemSetCollisionMask(HSQUIRRELVM vm)
{
__SQ_GETSTART(2)
__SQ_GETSAFEPTR(item, MItem, typetag_Item)
__SQ_GETINT(mask)
__SQ_GETEND
__SQ_TEST_ITEM_PHYSIC
item->physic_item->SetCollisionMask(mask);
__SQ_RETURN
}
SQInteger ItemGetShapeFromIndex(HSQUIRRELVM vm)
{
__SQ_GETSTART(2)
__SQ_GETSAFEPTR(item, MItem, typetag_Item)
__SQ_GETINT(idx)
__SQ_GETEND
__SQ_TEST_ITEM_PHYSIC
if (idx < (SQInteger)item->physic_item_desc.shape_list.GetCount())
__SQ_RETURNSAFEPTR(item->physic_item_desc.shape_list[idx], typetag_ColShape)
__SQ_RETURNNULL
}
SQInteger ItemAddCollisionShape(HSQUIRRELVM vm)
{
__SQ_GETSINGLESAFEPTR(item, MItem, typetag_Item)
__SQ_TEST_ITEM_PHYSIC
PhysicShape *shape = new PhysicShape;
if (!shape)
return sq_throwerror(vm, "Failed to allocate collision shape.");
item->physic_item_desc.shape_list.Add(shape);
__SQ_RETURNSAFEPTR(shape, typetag_ColShape)
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
SQInteger ShapeSetMesh(HSQUIRRELVM vm)
{
__SQ_GETSTART(2)
__SQ_GETSAFEPTR(shape, PhysicShape, typetag_ColShape)
__SQ_GETSTRING(path)
bool r = path ? shape->Set(PhysicShape::TypeMesh, path) : false;
__SQ_GETEND
__SQ_RETURNBOOL(r)
}
SQInteger ShapeSetConvex(HSQUIRRELVM vm)
{
__SQ_GETSTART(2)
__SQ_GETSAFEPTR(shape, PhysicShape, typetag_ColShape)
__SQ_GETSTRING(path)
bool r = path ? shape->Set(PhysicShape::TypeConvex, path) : false;
__SQ_GETEND
__SQ_RETURNBOOL(r)
}
SQInteger ShapeSetSphere(HSQUIRRELVM vm)
{
__SQ_GETSTART(2)
__SQ_GETSAFEPTR(shape, PhysicShape, typetag_ColShape)
__SQ_GETFLOAT(radius)
__SQ_GETEND
__SQ_RETURNBOOL(shape->Set(PhysicShape::TypeSphere, Vector4(radius, 0, 0)))
}
SQInteger ShapeSetBox(HSQUIRRELVM vm)
{
__SQ_GETSTART(2)
__SQ_GETSAFEPTR(shape, PhysicShape, typetag_ColShape)
__SQ_GETVECTOR(scale)
__SQ_GETEND
__SQ_RETURNBOOL(shape->Set(PhysicShape::TypeBox, scale))
}
SQInteger ShapeSetCapsule(HSQUIRRELVM vm)
{
__SQ_GETSTART(3)
__SQ_GETSAFEPTR(shape, PhysicShape, typetag_ColShape)
__SQ_GETFLOAT(radius)
__SQ_GETFLOAT(length)
__SQ_GETEND
__SQ_RETURNBOOL(shape->Set(PhysicShape::TypeCapsule, Vector4(radius, length, 0.0)))
}
SQInteger ShapeSetCylinder(HSQUIRRELVM vm)
{
__SQ_GETSTART(3)
__SQ_GETSAFEPTR(shape, PhysicShape, typetag_ColShape)
__SQ_GETFLOAT(radius)
__SQ_GETFLOAT(length)
__SQ_GETEND
__SQ_RETURNBOOL(shape->Set(PhysicShape::TypeCylinder, Vector4(radius, length, 0.0)))
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
SQInteger ShapeGetItem(HSQUIRRELVM vm)
{
__SQ_GETSINGLESAFEPTR(shape, PhysicShape, typetag_ColShape)
__SQ_RETURNSAFEPTR(NULL, typetag_Item);
}
SQInteger ShapeGetPosition(HSQUIRRELVM vm)
{
__SQ_GETSINGLESAFEPTR(shape, PhysicShape, typetag_ColShape)
__SQ_RETURNVECTOR(shape->position)
}
SQInteger ShapeSetPosition(HSQUIRRELVM vm)
{
__SQ_GETSTART(2)
__SQ_GETSAFEPTR(shape, PhysicShape, typetag_ColShape)
__SQ_GETVECTOR(p)
__SQ_GETEND
shape->position = p;
__SQ_RETURN
}
SQInteger ShapeGetRotation(HSQUIRRELVM vm)
{
__SQ_GETSINGLESAFEPTR(shape, PhysicShape, typetag_ColShape)
__SQ_RETURNVECTOR(shape->rotation)
}
SQInteger ShapeSetRotation(HSQUIRRELVM vm)
{
__SQ_GETSTART(2)
__SQ_GETSAFEPTR(shape, PhysicShape, typetag_ColShape)
__SQ_GETVECTOR(e)
__SQ_GETEND
shape->rotation = e;
__SQ_RETURN
}
SQInteger ShapeSetRestitution(HSQUIRRELVM vm)
{
__SQ_GETSTART(2)
__SQ_GETSAFEPTR(shape, PhysicShape, typetag_ColShape)
__SQ_GETFLOAT(r)
__SQ_GETEND
shape->restitution = r;
__SQ_RETURN
}
SQInteger ShapeSetFriction(HSQUIRRELVM vm)
{
__SQ_GETSTART(3)
__SQ_GETSAFEPTR(shape, PhysicShape, typetag_ColShape)
__SQ_GETFLOAT(df)
__SQ_GETFLOAT(sf)
__SQ_GETEND
shape->dynamic_friction = df;
shape->static_friction = sf;
__SQ_RETURN
}
SQInteger ShapeGetMass(HSQUIRRELVM vm)
{
__SQ_GETSINGLESAFEPTR(shape, PhysicShape, typetag_ColShape)
__SQ_RETURNFLOAT(shape->mass)
}
SQInteger ShapeSetMass(HSQUIRRELVM vm)
{
__SQ_GETSTART(2)
__SQ_GETSAFEPTR(shape, PhysicShape, typetag_ColShape)
__SQ_GETFLOAT(mass)
__SQ_GETEND
shape->mass = mass;
__SQ_RETURN
}
//------------------------------------------------------------------------------
// //poly poly intersection
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Gather up one-dimensional extents of the projection of the polygon
// onto this axis.
void gatherPolygonProjectionExtents(GS::Array<GS::Vector4> poly, GS::Vector4 v, float &outMin, float &outMax)
{
// Initialize extents to a single point, the first vertex
outMin = outMax = v.Dot(poly[0]);
// Now scan all the rest, growing extents to include them
for (uint i = 1; i < poly.GetCount(); ++i) {
float d = v.Dot(poly[i]);
if (d < outMin)
outMin = d;
else if (d > outMax)
outMax = d;
}
}
// Helper routine: test if two convex polygons overlap, using only the edges of
// the first polygon (polygon "a") to build the list of candidate separating axes.
bool findSeparatingAxis(GS::Array<Vector4> poly_a, GS::Array<Vector4> poly_b)
{
// Iterate over all the edges
uint prev = poly_a.GetCount() - 1;
for (uint cur = 0; cur < poly_a.GetCount(); ++cur)
{
// Get edge vector. (Assume operator- is overloaded)
GS::Vector4 edge = poly_a[cur] - poly_a[prev];
edge.y = 0;
edge.Normalize();
// Rotate vector 90 degrees (doesn't matter which way) to get
// candidate separating axis.
GS::Vector4 v(edge.z, 0, -edge.x);
// Gather extents of both polygons projected onto this axis
float result_poly_a_min, result_poly_a_max;
gatherPolygonProjectionExtents(poly_a, v, result_poly_a_min, result_poly_a_max);
float result_poly_b_min, result_poly_b_max;
gatherPolygonProjectionExtents(poly_b, v, result_poly_b_min, result_poly_b_max);
// Is this a separating axis?
if (result_poly_a_max < result_poly_b_min) return true;
if (result_poly_b_max < result_poly_a_min) return true;
// Next edge, please
prev = cur;
}
// Failed to find a separating axis
return false;
}
// Here is our high level entry point. It tests whether two polygons intersect. The
// polygons must be convex, and they must not be degenerate.
bool convexPolygonOverlap(GS::Array<GS::Vector4> poly_a, GS::Array<Vector4> poly_b) //poly[a, b, c, d]
{
// First, use all of A's edges to get candidate separating axes
if (findSeparatingAxis(poly_a, poly_b))
return false;
// Now swap roles, and use B's edges
if (findSeparatingAxis(poly_b, poly_a))
return false;
// No separating axis found. They must overlap
return true;
}
SQInteger convexPolygonOverlapBind(HSQUIRRELVM vm)
{
__SQ_GETSTART(2)
GS::Array<GS::Vector4> poly_a(4);
sq_pushnull(vm);//null iterator
for (int i = 0; i < 4; ++i)
{
sq_next(vm, __SQ_STACKPOS - 1);
GetVector(vm, -1, poly_a[i]);
sq_pop(vm, 2);
}
sq_pop(vm, 1); //pops the null iterator
__SQ_GETUPDATESTACK
GS::Array<GS::Vector4> poly_b(4);
sq_pushnull(vm);//null iterator
for (int i = 0; i < 4; ++i)
{
sq_next(vm, __SQ_STACKPOS - 1);
GetVector(vm, -1, poly_b[i]);
sq_pop(vm, 2);
}
sq_pop(vm, 1); //pops the null iterator
__SQ_GETEND
__SQ_RETURNBOOL(convexPolygonOverlap(poly_a, poly_b));
}
//------------------------------------------------------------
bool PointInPoly2D(GS::Vector4 point, GS::Array<GS::Vector4> poly) // poly = [Vector(), Vector(), Vector(), Vector()]
//------------------------------------------------------------
{
bool oddNodes = false;
float x2 = poly[3].x;
float z2 = poly[3].z;
float x1, z1;
// vertex a
x1 = poly[0].x;
z1 = poly[0].z;
if (((z1 < point.z) && (z2 >= point.z)) || (z1 >= point.z) && (z2 < point.z)) {
if ((point.z - z1) / (z2 - z1) * (x2 - x1) < (point.x - x1))
oddNodes = !oddNodes;
}
x2 = x1;
z2 = z1;
// vertex b
x1 = poly[1].x;
z1 = poly[1].z;
if (((z1 < point.z) && (z2 >= point.z)) || (z1 >= point.z) && (z2 < point.z)) {
if ((point.z - z1) / (z2 - z1) * (x2 - x1) < (point.x - x1))
oddNodes = !oddNodes;
}
x2 = x1;
z2 = z1;
// vertex c
x1 = poly[2].x;
z1 = poly[2].z;
if (((z1 < point.z) && (z2 >= point.z)) || (z1 >= point.z) && (z2 < point.z)) {
if ((point.z - z1) / (z2 - z1) * (x2 - x1) < (point.x - x1))
oddNodes = !oddNodes;
}
x2 = x1;
z2 = z1;
// vertex d
x1 = poly[3].x;
z1 = poly[3].z;
if (((z1 < point.z) && (z2 >= point.z)) || (z1 >= point.z) && (z2 < point.z)) {
if ((point.z - z1) / (z2 - z1) * (x2 - x1) < (point.x - x1))
oddNodes = !oddNodes;
}
return oddNodes;
}
SQInteger PointInPoly2DBind(HSQUIRRELVM vm)
{
__SQ_GETSTART(2)
__SQ_GETVECTOR(p);
GS::Array<GS::Vector4> poly_a(4);
sq_pushnull(vm);//null iterator
for (int i = 0; i < 4; ++i)
{
sq_next(vm, __SQ_STACKPOS - 1);
GetVector(vm, -1, poly_a[i]);
sq_pop(vm, 2);
}
sq_pop(vm, 1); //pops the null iterator
__SQ_GETUPDATESTACK
__SQ_GETEND
__SQ_RETURNBOOL(PointInPoly2D(p, poly_a));
}
//----------------------------------------------------------
void RegisterCollisionBinding(HSQUIRRELVM vm)
//----------------------------------------------------------
{
/*#
Func: convexPolygonOverlapBind
Proto: void:array polyA, array polyB
Desc: return if the 2 poly overlap
#*/
sq_register(vm, convexPolygonOverlapBind, "convexPolygonOverlapBind", _SC(".aa"));
/*#
Func: convexPolygonOverlapBind
Proto: void:Vector p, array polyA
Desc: return if the 2 poly overlap
#*/
sq_register(vm, PointInPoly2DBind, "PointInPoly2DBind", _SC(".xa"));
/*#
Topic: Collision
Type: ColShape
#*/
/*#
Section: CollisionShapeType
Desc: Collision Shape Type functions
#*/
/*#
Func: ShapeSetMesh
Proto: bool:ColShape shape,string path
Desc: Set the shape as a collision mesh.
#*/
sq_register(vm, ShapeSetMesh, "ShapeSetMesh", _SC(".xs"));
/*#
Func: ShapeSetConvex
Proto: bool:ColShape shape,string path
Desc: Set the shape as a convex collision.
#*/
sq_register(vm, ShapeSetConvex, "ShapeSetConvex", _SC(".xs"));
/*#
Func: ShapeSetSphere
Proto: bool:ColShape shape,float radius
Desc: Set the shape as a sphere.
#*/
sq_register(vm, ShapeSetSphere, "ShapeSetSphere", _SC(".xn"));
/*#
Func: ShapeSetBox
Proto: bool:ColShape shape,Vector dimensions
Desc: Set the shape as a box collision shape.
#*/
sq_register(vm, ShapeSetBox, "ShapeSetBox", _SC(".xx"));
/*#
Func: ShapeSetCapsule
Proto: bool:ColShape shape,float radius,float length
Desc: Set the shape as a Z-oriented capsule collision shape.
#*/
sq_register(vm, ShapeSetCapsule, "ShapeSetCapsule", _SC(".xnn"));
/*#
Func: ShapeSetCylinder
Proto: bool:ColShape shape,float radius,float length
Desc: Set the shape as a Z-oriented cylinder collision shape.
#*/
sq_register(vm, ShapeSetCylinder, "ShapeSetCylinder", _SC(".xnn"));
/*#
Section: CollisionShape
Desc: Collision Shape functions
#*/
/*#
Func: ShapeSetPosition
Proto: void:ColShape shape,Vector position
Desc: Set the collision shape position in item space.
#*/
sq_register(vm, ShapeSetPosition, "ShapeSetPosition", _SC(".xx"));
/*#
Func: ShapeGetPosition
Proto: Vector:ColShape shape
Desc: Get the collision shape position in item space.
#*/
sq_register(vm, ShapeGetPosition, "ShapeGetPosition", _SC(".x"));
/*#
Func: ShapeSetRotation
Proto: void:ColShape shape,Vector position
Desc: Set the collision shape position from a Euler triplet in item space.
#*/
sq_register(vm, ShapeSetRotation, "ShapeSetRotation", _SC(".xx"));
/*#
Func: ShapeGetRotation
Proto: Vector:ColShape shape
Desc: Get the collision shape rotation as an Euler triplet in item space.
#*/
sq_register(vm, ShapeGetRotation, "ShapeGetRotation", _SC(".x"));
/*#
Func: ShapeSetMass
Proto: void:ColShape shape,float mass
Desc: Set the collision shape mass. Do not forget to update the item collision setup to update changes.
#*/
sq_register(vm, ShapeSetMass, "ShapeSetMass", _SC(".xn"));
/*#
Func: ShapeGetMass
Proto: float:ColShape shape
Desc: Get the collision shape mass.
#*/
sq_register(vm, ShapeGetMass, "ShapeGetMass", _SC(".x"));
/*#
Func: ShapeSetFriction
Proto: void:ColShape shape,float dynamic_friction,float static_friction
Desc: Set collision shape dynamic and static friction.
#*/
sq_register(vm, ShapeSetFriction, "ShapeSetFriction", _SC(".xnn"));
/*#
Func: ShapeSetRestitution
Proto: void:ColShape shape,float restitution
Desc: Set collision shape restitution (1 for a perfect elastic collision).
#*/
sq_register(vm, ShapeSetRestitution, "ShapeSetRestitution", _SC(".xn"));
/*#
Func: ShapeGetItem
Proto: Item:ColShape shape
Desc: Get the item this collision shape belongs to.
#*/
sq_register(vm, ShapeGetItem, "ShapeGetItem", _SC(".x"));
/*#
Section: CollisionItem
Desc: Item functions
#*/
/*#
Func: ItemAddCollisionShape
Proto: ColShape:Item
Desc: Add a new collision shape to item.
#*/
sq_register(vm, ItemAddCollisionShape, "ItemAddCollisionShape", _SC(".x"));
/*#
Func: ItemCollisionActivate
Proto: void:Item,bool active
Desc: Activate or deactivate item collision.
#*/
sq_register(vm, ItemCollisionActivate, "ItemCollisionActivate", _SC(".xb"));
/*#
Func: ItemSetSelfMask
Proto: void:Item,int self_mask
Desc: Set item self mask, this mask is a bit field.
#*/
sq_register(vm, ItemSetSelfMask, "ItemSetSelfMask", _SC(".xi"));
/*#
Func: ItemSetCollisionMask
Proto: void:Item,int collision_mask
Desc: Set item collision mask, this mask is a bit field.
#*/
sq_register(vm, ItemSetCollisionMask, "ItemSetCollisionMask", _SC(".xi"));
/*#
Func: ItemGetShapeFromIndex
Proto: ColShape:item,int index
Desc: Get item collision shape from index.
#*/
sq_register(vm, ItemGetShapeFromIndex, "ItemGetShapeFromIndex", _SC(".xi"));
// Push defines.
sq_pushroottable(vm);
/*#
Enum: ShapeMask
Desc: Shape mask to filter out certain type of shape from intersection tests.
Values: CollisionTraceMesh,CollisionTraceSphere,CollisionTraceCuboid,CollisionTraceAll
#*/
sq_pushstring(vm, "CollisionTraceMesh", -1); sq_pushinteger(vm, -1); sq_newslot(vm, -3, true);
sq_pushstring(vm, "CollisionTraceSphere", -1); sq_pushinteger(vm, -1); sq_newslot(vm, -3, true);
sq_pushstring(vm, "CollisionTraceCuboid", -1); sq_pushinteger(vm, -1); sq_newslot(vm, -3, true);
sq_pushstring(vm, "CollisionTraceAll", -1); sq_pushinteger(vm, ~0); sq_newslot(vm, -3, true);
sq_pop(vm, 1);
}