Bullet API in dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cstdlib> | |
#include <cstdio> | |
#include <iostream> | |
#include <cstring> | |
#include <string> | |
#include "dart_api.h" | |
#include "dart_native_api.h" | |
#include <btBulletDynamicsCommon.h> | |
Dart_NativeFunction ResolveName(Dart_Handle name, int argc, bool* auto_setup_scope); | |
struct HandleException { | |
explicit HandleException(Dart_Handle handle) : handle(handle) {} | |
Dart_Handle handle; | |
}; | |
static Dart_Handle handleError(Dart_Handle handle) { | |
if (Dart_IsError(handle)) throw HandleException(handle); | |
return handle; | |
} | |
template<typename T, void destruct(T*)> T* constructWeak(Dart_NativeArguments arguments) { | |
auto s = new T(); | |
Dart_NewWeakPersistentHandle( | |
handleError(Dart_GetNativeArgument(arguments, 0)), | |
static_cast<T*>(s), | |
sizeof(s), | |
[]( | |
void* isolate_callback_data, | |
Dart_WeakPersistentHandle handle, | |
void* peer | |
){ | |
destruct(static_cast<T*>(peer)); | |
} | |
); | |
Dart_SetReturnValue(arguments, Dart_NewInteger(reinterpret_cast<int64_t>(s))); | |
return s; | |
} | |
template<void code(Dart_NativeArguments arguments)> void safeHandle(Dart_NativeArguments arguments) { | |
try { | |
code(arguments); | |
} catch (HandleException& handle) { | |
Dart_PropagateError(handle.handle); | |
} | |
} | |
double doubleFromArgs(Dart_NativeArguments arguments, int index) { | |
double x; | |
handleError(Dart_GetNativeDoubleArgument(arguments, index, &x)); | |
return x; | |
} | |
int64_t intFromArgs(Dart_NativeArguments arguments, int index) { | |
int64_t x; | |
handleError(Dart_GetNativeIntegerArgument(arguments, index, &x)); | |
return x; | |
} | |
template<typename T> T* ptrFromArg(Dart_NativeArguments arguments, int index) { | |
int64_t i; | |
handleError(Dart_GetNativeIntegerArgument(arguments, index, &i)); | |
return reinterpret_cast<T*>(i); | |
}; | |
struct WorldState { | |
btBroadphaseInterface* broadphase = nullptr; | |
btDefaultCollisionConfiguration* collisionConfiguration = nullptr; | |
btCollisionDispatcher* dispatcher = nullptr; | |
btDiscreteDynamicsWorld* dynamicsWorld = nullptr; | |
btSequentialImpulseConstraintSolver* solver = nullptr; | |
}; | |
struct CollisionShape { | |
btCollisionShape* shape = nullptr; | |
}; | |
struct MotionState { | |
btMotionState* state; | |
}; | |
struct RigidBody { | |
btRigidBody* body; | |
}; | |
std::string vec3str(btVector3 v) { | |
return std::to_string(v.x()) + "," + std::to_string(v.y()) + "," + std::to_string(v.z()); | |
} | |
DART_EXPORT Dart_Handle phys_Init(Dart_Handle parent_library) { | |
if (Dart_IsError(parent_library)) return parent_library; | |
Dart_Handle result_code = | |
Dart_SetNativeResolver(parent_library, ResolveName, nullptr); | |
if (Dart_IsError(result_code)) return result_code; | |
return Dart_Null(); | |
} | |
btVector3 vec3FromArgs(Dart_NativeArguments arguments, int index) { | |
return btVector3( | |
doubleFromArgs(arguments, index), | |
doubleFromArgs(arguments, index + 1), | |
doubleFromArgs(arguments, index + 2) | |
); | |
} | |
btQuaternion quatFromArgs(Dart_NativeArguments arguments, int index) { | |
return btQuaternion( | |
doubleFromArgs(arguments, index), | |
doubleFromArgs(arguments, index + 1), | |
doubleFromArgs(arguments, index + 2), | |
doubleFromArgs(arguments, index + 3) | |
); | |
} | |
void d_world_destruct(WorldState* state) { | |
delete state->dynamicsWorld; | |
delete state->solver; | |
delete state->collisionConfiguration; | |
delete state->dispatcher; | |
delete state->broadphase; | |
delete state; | |
} | |
void d_world_construct(Dart_NativeArguments arguments) { | |
constructWeak<WorldState, d_world_destruct>(arguments); | |
} | |
void d_world_init_lazy(Dart_NativeArguments arguments) { | |
auto w = ptrFromArg<WorldState>(arguments, 1); | |
w->broadphase = new btDbvtBroadphase(); | |
w->collisionConfiguration = new btDefaultCollisionConfiguration(); | |
w->dispatcher = new btCollisionDispatcher(w->collisionConfiguration); | |
w->solver = new btSequentialImpulseConstraintSolver; | |
w->dynamicsWorld = new btDiscreteDynamicsWorld(w->dispatcher, w->broadphase, w->solver, w->collisionConfiguration); | |
} | |
void d_world_set_gravity(Dart_NativeArguments arguments) { | |
auto w = ptrFromArg<WorldState>(arguments, 1); | |
w->dynamicsWorld->setGravity(vec3FromArgs(arguments, 2)); | |
} | |
void d_world_add_rigid_body(Dart_NativeArguments arguments) { | |
auto w = ptrFromArg<WorldState>(arguments, 1); | |
auto body = ptrFromArg<RigidBody>(arguments, 2); | |
w->dynamicsWorld->addRigidBody(body->body); | |
} | |
void d_world_step(Dart_NativeArguments arguments) { | |
auto w = ptrFromArg<WorldState>(arguments, 1); | |
w->dynamicsWorld->stepSimulation(doubleFromArgs(arguments, 2), intFromArgs(arguments, 3)); | |
} | |
void shape_destruct(CollisionShape* collisionShape) { | |
delete collisionShape->shape; | |
delete collisionShape; | |
} | |
void d_shape_construct(Dart_NativeArguments arguments) { | |
auto collisionshape = constructWeak<CollisionShape, shape_destruct>(arguments); | |
collisionshape->shape = new btEmptyShape(); | |
} | |
void d_shape_static_plane_construct(Dart_NativeArguments arguments) { | |
auto collisionshape = constructWeak<CollisionShape, shape_destruct>(arguments); | |
//collisionshape->shape = new btStaticPlaneShape(vec3FromArgs(arguments, 1), doubleFromArgs(arguments, 4)); | |
collisionshape->shape = new btStaticPlaneShape(btVector3(0, 1, 0), 1); | |
} | |
void d_shape_sphere_construct(Dart_NativeArguments arguments) { | |
auto collisionshape = constructWeak<CollisionShape, shape_destruct>(arguments); | |
collisionshape->shape = new btSphereShape(doubleFromArgs(arguments, 1)); | |
} | |
void d_shape_calc_inertia(Dart_NativeArguments arguments) { | |
auto collisionshape = ptrFromArg<CollisionShape>(arguments, 1); | |
auto out = Dart_GetNativeArgument(arguments, 3); | |
btVector3 inertia(0.0, 0.0, 0.0); | |
collisionshape->shape->calculateLocalInertia(doubleFromArgs(arguments, 2), inertia); | |
handleError(Dart_ListSetAt(out, 0, Dart_NewDouble(inertia.x()))); | |
handleError(Dart_ListSetAt(out, 1, Dart_NewDouble(inertia.y()))); | |
handleError(Dart_ListSetAt(out, 2, Dart_NewDouble(inertia.z()))); | |
} | |
void motion_state_destruct(MotionState* motionState) { | |
delete motionState->state; | |
delete motionState; | |
} | |
void d_motion_state_construct(Dart_NativeArguments arguments) { | |
auto motionState = constructWeak<MotionState, motion_state_destruct>(arguments); | |
motionState->state = new btDefaultMotionState( | |
btTransform(quatFromArgs(arguments, 4), vec3FromArgs(arguments, 1)) | |
); | |
} | |
void d_motion_state_get_pos(Dart_NativeArguments arguments) { | |
auto motionState = ptrFromArg<MotionState>(arguments, 1); | |
auto out = Dart_GetNativeArgument(arguments, 2); | |
btTransform transform; | |
motionState->state->getWorldTransform(transform); | |
auto origin = transform.getOrigin(); | |
handleError(Dart_ListSetAt(out, 0, Dart_NewDouble(origin.x()))); | |
handleError(Dart_ListSetAt(out, 1, Dart_NewDouble(origin.y()))); | |
handleError(Dart_ListSetAt(out, 2, Dart_NewDouble(origin.z()))); | |
} | |
void d_motion_state_set_pos(Dart_NativeArguments arguments) { | |
auto motionState = ptrFromArg<MotionState>(arguments, 1); | |
auto out = Dart_GetNativeArgument(arguments, 2); | |
btTransform transform; | |
motionState->state->getWorldTransform(transform); | |
transform.setOrigin(btVector3( | |
doubleFromArgs(arguments, 1), | |
doubleFromArgs(arguments, 2), | |
doubleFromArgs(arguments, 3) | |
)); | |
motionState->state->setWorldTransform(transform); | |
} | |
void d_motion_state_get_angle(Dart_NativeArguments arguments) { | |
auto motionState = ptrFromArg<MotionState>(arguments, 1); | |
auto out = Dart_GetNativeArgument(arguments, 2); | |
btTransform transform; | |
motionState->state->getWorldTransform(transform); | |
auto origin = transform.getOrigin(); | |
handleError(Dart_ListSetAt(out, 0, Dart_NewDouble(origin.x()))); | |
handleError(Dart_ListSetAt(out, 1, Dart_NewDouble(origin.y()))); | |
handleError(Dart_ListSetAt(out, 2, Dart_NewDouble(origin.z()))); | |
} | |
void d_motion_state_set_angle(Dart_NativeArguments arguments) { | |
auto motionState = ptrFromArg<MotionState>(arguments, 1); | |
auto out = Dart_GetNativeArgument(arguments, 2); | |
btTransform transform; | |
motionState->state->getWorldTransform(transform); | |
transform.setOrigin(btVector3( | |
doubleFromArgs(arguments, 1), | |
doubleFromArgs(arguments, 2), | |
doubleFromArgs(arguments, 3) | |
)); | |
motionState->state->setWorldTransform(transform); | |
} | |
void rigid_body_destruct(RigidBody* motionState) { | |
delete motionState->body; | |
delete motionState; | |
} | |
void d_rigid_body_construct(Dart_NativeArguments arguments) { | |
auto rigidBody = constructWeak<RigidBody, rigid_body_destruct>(arguments); | |
auto mass = doubleFromArgs(arguments, 1); | |
auto motionState = ptrFromArg<MotionState>(arguments, 2); | |
auto collisionShape = ptrFromArg<CollisionShape>(arguments, 3); | |
auto inertia = vec3FromArgs(arguments, 4); | |
auto restitution = doubleFromArgs(arguments, 7); | |
auto friction = doubleFromArgs(arguments, 8); | |
btRigidBody::btRigidBodyConstructionInfo fallRigidBodyCI( | |
mass, motionState->state, collisionShape->shape, inertia | |
); | |
fallRigidBodyCI.m_restitution = restitution; | |
fallRigidBodyCI.m_friction = friction; | |
rigidBody->body = new btRigidBody(fallRigidBodyCI); | |
} | |
Dart_NativeFunction ResolveName(Dart_Handle name, int argc, bool* auto_setup_scope) { | |
if (!Dart_IsString(name)) return nullptr; | |
Dart_NativeFunction result = nullptr; | |
const char* cname; | |
auto cres = Dart_StringToCString(name, &cname); | |
if (Dart_IsError(cres)) Dart_PropagateError(cres); | |
if (strcmp("world_construct", cname) == 0) result = safeHandle<d_world_construct>; | |
if (strcmp("world_init_lazy", cname) == 0) result = safeHandle<d_world_init_lazy>; | |
if (strcmp("world_set_gravity", cname) == 0) result = safeHandle<d_world_set_gravity>; | |
if (strcmp("world_add_rigid_body", cname) == 0) result = safeHandle<d_world_add_rigid_body>; | |
if (strcmp("world_step", cname) == 0) result = safeHandle<d_world_step>; | |
if (strcmp("shape_construct", cname) == 0) result = safeHandle<d_shape_construct>; | |
if (strcmp("shape_static_plane_construct", cname) == 0) result = safeHandle<d_shape_static_plane_construct>; | |
if (strcmp("shape_sphere_construct", cname) == 0) result = safeHandle<d_shape_sphere_construct>; | |
if (strcmp("shape_calc_inertia", cname) == 0) result = safeHandle<d_shape_calc_inertia>; | |
if (strcmp("motion_state_construct", cname) == 0) result = safeHandle<d_motion_state_construct>; | |
if (strcmp("motion_state_get_pos", cname) == 0) result = safeHandle<d_motion_state_get_pos>; | |
if (strcmp("motion_state_set_pos", cname) == 0) result = safeHandle<d_motion_state_set_pos>; | |
if (strcmp("motion_state_get_angle", cname) == 0) result = safeHandle<d_motion_state_get_angle>; | |
if (strcmp("motion_state_set_angle", cname) == 0) result = safeHandle<d_motion_state_set_angle>; | |
if (strcmp("rigid_body_construct", cname) == 0) result = safeHandle<d_rigid_body_construct>; | |
return result; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment