/* * SOLID - Software Library for Interference Detection * * Copyright (C) 2001-2003 Dtecta. All rights reserved. * * This library may be distributed under the terms of the Q Public License * (QPL) as defined by Trolltech AS of Norway and appearing in the file * LICENSE.QPL included in the packaging of this file. * * This library may be distributed and/or modified under the terms of the * GNU General Public License (GPL) version 2 as published by the Free Software * Foundation and appearing in the file LICENSE.GPL included in the * packaging of this file. * * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Commercial use or any other use of this library not covered by either * the QPL or the GPL requires an additional license from Dtecta. * Please contact info@dtecta.com for enquiries about the terms of commercial * use of this library. */ #include "SOLID.h" #include "DT_Box.h" #include "DT_Cone.h" #include "DT_Cylinder.h" #include "DT_Sphere.h" #include "DT_Complex.h" #include "DT_Polytope.h" #include "DT_Polyhedron.h" #include "DT_Point.h" #include "DT_LineSegment.h" #include "DT_Triangle.h" #include "DT_Minkowski.h" #include "DT_Hull.h" #include "DT_Response.h" #include "DT_RespTable.h" #include "DT_Scene.h" #include "DT_Object.h" #include "DT_VertexBase.h" #include "DT_Accuracy.h" typedef MT::Tuple3 T_Vertex; typedef std::vector T_VertexBuf; typedef std::vector T_IndexBuf; typedef std::vector T_PolyList; static T_VertexBuf vertexBuf; static T_IndexBuf indexBuf; static T_PolyList polyList; static DT_Complex *currentComplex = 0; static DT_Polyhedron *currentPolyhedron = 0; static DT_VertexBase *currentBase = 0; DT_VertexBaseHandle DT_NewVertexBase(const void *pointer, DT_Size stride) { return (DT_VertexBaseHandle)new DT_VertexBase(pointer, stride); } void DT_DeleteVertexBase(DT_VertexBaseHandle vertexBase) { delete (DT_VertexBase *)vertexBase; } void DT_ChangeVertexBase(DT_VertexBaseHandle vertexBase, const void *pointer) { DT_VertexBase *base = (DT_VertexBase *)vertexBase; base->setPointer(pointer); const DT_ComplexList& complexList = base->getComplexList(); DT_ComplexList::const_iterator it; for (it = complexList.begin(); it != complexList.end(); ++it) { (*it)->refit(); } } DT_ShapeHandle DT_NewBox(DT_Scalar x, DT_Scalar y, DT_Scalar z) { return (DT_ShapeHandle)new DT_Box(MT_Scalar(x) * MT_Scalar(0.5), MT_Scalar(y) * MT_Scalar(0.5), MT_Scalar(z) * MT_Scalar(0.5)); } DT_ShapeHandle DT_NewCone(DT_Scalar radius, DT_Scalar height) { return (DT_ShapeHandle)new DT_Cone(MT_Scalar(radius), MT_Scalar(height)); } DT_ShapeHandle DT_NewCylinder(DT_Scalar radius, DT_Scalar height) { return (DT_ShapeHandle)new DT_Cylinder(MT_Scalar(radius), MT_Scalar(height)); } DT_ShapeHandle DT_NewSphere(DT_Scalar radius) { return (DT_ShapeHandle)new DT_Sphere(MT_Scalar(radius)); } DT_ShapeHandle DT_NewPoint(const DT_Vector3 point) { return (DT_ShapeHandle)new DT_Point(MT_Point3(point)); } DT_ShapeHandle DT_NewLineSegment(const DT_Vector3 source, const DT_Vector3 target) { return (DT_ShapeHandle)new DT_LineSegment(MT_Point3(source), MT_Point3(target)); } DT_ShapeHandle DT_NewMinkowski(DT_ShapeHandle shape1, DT_ShapeHandle shape2) { if (((DT_Shape *)shape1)->getType() != CONVEX || ((DT_Shape *)shape2)->getType() != CONVEX) { return 0; } return (DT_ShapeHandle)new DT_Minkowski(*(DT_Convex *)shape1, *(DT_Convex *)shape2); } DT_ShapeHandle DT_NewHull(DT_ShapeHandle shape1, DT_ShapeHandle shape2) { if (((DT_Shape *)shape1)->getType() != CONVEX || ((DT_Shape *)shape2)->getType() != CONVEX) { return 0; } return (DT_ShapeHandle)new DT_Hull(*(DT_Convex *)shape1, *(DT_Convex *)shape2); } DT_ShapeHandle DT_NewComplexShape(const DT_VertexBaseHandle vertexBase) { if (!currentComplex) { currentBase = vertexBase ? (DT_VertexBase *)vertexBase : new DT_VertexBase; currentComplex = new DT_Complex(currentBase); } return (DT_ShapeHandle)currentComplex; } void DT_EndComplexShape() { if (currentComplex) { if (currentBase->getPointer() == 0) { T_Vertex *vertexArray = new T_Vertex[vertexBuf.size()]; assert(vertexArray); std::copy(vertexBuf.begin(), vertexBuf.end(), &vertexArray[0]); currentBase->setPointer(vertexArray, true); } vertexBuf.clear(); currentComplex->finish(polyList.size(), &polyList[0]); polyList.clear(); currentComplex = 0; currentBase = 0; } } DT_ShapeHandle DT_NewPolytope(const DT_VertexBaseHandle vertexBase) { if (!currentPolyhedron) { currentBase = vertexBase ? (DT_VertexBase *)vertexBase : new DT_VertexBase; currentPolyhedron = new DT_Polyhedron; } return (DT_ShapeHandle)currentPolyhedron; } void DT_EndPolytope() { if (currentPolyhedron) { if (currentBase->getPointer() == 0) { currentBase->setPointer(&vertexBuf[0]); new (currentPolyhedron) DT_Polyhedron(currentBase, indexBuf.size(), &indexBuf[0]); delete currentBase; } else { new (currentPolyhedron) DT_Polyhedron(currentBase, indexBuf.size(), &indexBuf[0]); } vertexBuf.clear(); indexBuf.clear(); currentPolyhedron = 0; currentBase = 0; } } void DT_Begin() {} void DT_End() { if (currentComplex) { DT_VertexIndices(indexBuf.size(), &indexBuf[0]); indexBuf.clear(); } } void DT_Vertex(const DT_Vector3 vertex) { MT::Vector3 p(vertex); int i = GEN_max((int)vertexBuf.size() - 20, 0); int n = static_cast(vertexBuf.size()); while (i != n && !(vertexBuf[i] == p)) { ++i; } if (i == n) { vertexBuf.push_back(p); } indexBuf.push_back(i); } void DT_VertexIndex(DT_Index index) { indexBuf.push_back(index); } void DT_VertexIndices(DT_Count count, const DT_Index *indices) { if (currentComplex) { DT_Convex *poly = count == 3 ? static_cast(new DT_Triangle(currentBase, indices[0], indices[1], indices[2])) : static_cast(new DT_Polytope(currentBase, count, indices)); polyList.push_back(poly); } if (currentPolyhedron) { int i; for (i = 0; i < count; ++i) { indexBuf.push_back(indices[i]); } } } void DT_VertexRange(DT_Index first, DT_Count count) { DT_Index *indices = new DT_Index[count]; DT_Index i; for (i = 0; i != count; ++i) { indices[i] = first + i; } DT_VertexIndices(count, indices); delete [] indices; } void DT_DeleteShape(DT_ShapeHandle shape) { delete (DT_Shape *)shape; } // Scene DT_SceneHandle DT_CreateScene() { return (DT_SceneHandle)new DT_Scene; } void DT_DestroyScene(DT_SceneHandle scene) { delete (DT_Scene *)scene; } void DT_AddObject(DT_SceneHandle scene, DT_ObjectHandle object) { assert(scene); assert(object); ((DT_Scene *)scene)->addObject(*(DT_Object *)object); } void DT_RemoveObject(DT_SceneHandle scene, DT_ObjectHandle object) { assert(scene); assert(object); ((DT_Scene *)scene)->removeObject(*(DT_Object *)object); } // Object instantiation DT_ObjectHandle DT_CreateObject(void *client_object, DT_ShapeHandle shape) { return (DT_ObjectHandle)new DT_Object(client_object, *(DT_Shape *)shape); } void DT_DestroyObject(DT_ObjectHandle object) { delete (DT_Object *)object; } void DT_SetMargin(DT_ObjectHandle object, DT_Scalar margin) { ((DT_Object *)object)->setMargin(MT_Scalar(margin)); } void DT_SetScaling(DT_ObjectHandle object, const DT_Vector3 scaling) { ((DT_Object *)object)->setScaling(MT_Vector3(scaling)); } void DT_SetPosition(DT_ObjectHandle object, const DT_Vector3 position) { ((DT_Object *)object)->setPosition(MT_Point3(position)); } void DT_SetOrientation(DT_ObjectHandle object, const DT_Quaternion orientation) { ((DT_Object *)object)->setOrientation(MT_Quaternion(orientation)); } void DT_SetMatrixf(DT_ObjectHandle object, const float *m) { ((DT_Object *)object)->setMatrix(m); } void DT_GetMatrixf(DT_ObjectHandle object, float *m) { ((DT_Object *)object)->getMatrix(m); } void DT_SetMatrixd(DT_ObjectHandle object, const double *m) { ((DT_Object *)object)->setMatrix(m); } void DT_GetMatrixd(DT_ObjectHandle object, double *m) { ((DT_Object *)object)->getMatrix(m); } void DT_GetBBox(DT_ObjectHandle object, DT_Vector3 min, DT_Vector3 max) { const MT_BBox& bbox = ((DT_Object *)object)->getBBox(); bbox.getMin().getValue(min); bbox.getMax().getValue(max); } DT_Scalar DT_GetClosestPair(DT_ObjectHandle object1, DT_ObjectHandle object2, DT_Vector3 point1, DT_Vector3 point2) { MT_Point3 p1, p2; MT_Scalar result = closest_points(*(DT_Object *)object1, *(DT_Object *)object2, p1, p2); p1.getValue(point1); p2.getValue(point2); return MT_sqrt(result); } DT_Bool DT_GetCommonPoint(DT_ObjectHandle object1, DT_ObjectHandle object2, DT_Vector3 point) { MT_Point3 p1, p2; MT_Vector3 v(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0)); bool result = common_point(*(DT_Object *)object1, *(DT_Object *)object2, v, p1, p2); if (result) { p1.getValue(point); } return result; } DT_Bool DT_GetPenDepth(DT_ObjectHandle object1, DT_ObjectHandle object2, DT_Vector3 point1, DT_Vector3 point2) { MT_Point3 p1, p2; MT_Vector3 v(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0)); bool result = penetration_depth(*(DT_Object *)object1, *(DT_Object *)object2, v, p1, p2); if (result) { p1.getValue(point1); p2.getValue(point2); } return result; } // Response DT_RespTableHandle DT_CreateRespTable() { return (DT_RespTableHandle)new DT_RespTable; } void DT_DestroyRespTable(DT_RespTableHandle respTable) { delete (DT_RespTable *)respTable; } DT_ResponseClass DT_GenResponseClass(DT_RespTableHandle respTable) { return ((DT_RespTable *)respTable)->genResponseClass(); } void DT_SetResponseClass(DT_RespTableHandle respTable, DT_ObjectHandle object, DT_ResponseClass responseClass) { ((DT_RespTable *)respTable)->setResponseClass(object, responseClass); } void DT_ClearResponseClass(DT_RespTableHandle respTable, DT_ObjectHandle object) { ((DT_RespTable *)respTable)->clearResponseClass(object); } void DT_CallResponse(DT_RespTableHandle respTable, DT_ObjectHandle object1, DT_ObjectHandle object2, const DT_CollData *coll_data) { const DT_ResponseList& responseList = ((DT_RespTable *)respTable)->find(object1, object2); if (responseList.getType() != DT_NO_RESPONSE) { responseList(((DT_Object *)object1)->getClientObject(), ((DT_Object *)object2)->getClientObject(), coll_data); } } void DT_AddDefaultResponse(DT_RespTableHandle respTable, DT_ResponseCallback response, DT_ResponseType type, void *client_data) { ((DT_RespTable *)respTable)->addDefault(DT_Response(response, type, client_data)); } void DT_RemoveDefaultResponse(DT_RespTableHandle respTable, DT_ResponseCallback response) { ((DT_RespTable *)respTable)->removeDefault(DT_Response(response)); } void DT_AddClassResponse(DT_RespTableHandle respTable, DT_ResponseClass responseClass, DT_ResponseCallback response, DT_ResponseType type, void *client_data) { ((DT_RespTable *)respTable)->addSingle(responseClass, DT_Response(response, type, client_data)); } void DT_RemoveClassResponse(DT_RespTableHandle respTable, DT_ResponseClass responseClass, DT_ResponseCallback response) { ((DT_RespTable *)respTable)->removeSingle(responseClass, DT_Response(response)); } void DT_AddPairResponse(DT_RespTableHandle respTable, DT_ResponseClass responseClass1, DT_ResponseClass responseClass2, DT_ResponseCallback response, DT_ResponseType type, void *client_data) { ((DT_RespTable *)respTable)->addPair(responseClass1, responseClass2, DT_Response(response, type, client_data)); } void DT_RemovePairResponse(DT_RespTableHandle respTable, DT_ResponseClass responseClass1, DT_ResponseClass responseClass2, DT_ResponseCallback response) { ((DT_RespTable *)respTable)->removePair(responseClass1, responseClass2, DT_Response(response)); } // Runtime void DT_SetAccuracy(DT_Scalar max_error) { if (max_error > MT_Scalar(0.0)) { DT_Accuracy::setAccuracy(MT_Scalar(max_error)); } } void DT_SetTolerance(DT_Scalar tol_error) { if (tol_error > MT_Scalar(0.0)) { DT_Accuracy::setTolerance(MT_Scalar(tol_error)); } } DT_Count DT_Test(DT_SceneHandle scene, DT_RespTableHandle respTable) { return ((DT_Scene *)scene)->handleCollisions((DT_RespTable *)respTable); } void *DT_RayCast(DT_SceneHandle scene, void *ignore_client, const DT_Vector3 source, const DT_Vector3 target, DT_Scalar max_param, DT_Scalar *param, DT_Vector3 normal) { DT_Scalar lambda = max_param; void *client_object = ((DT_Scene *)scene)->rayCast(ignore_client, source, target, lambda, normal); if (client_object) { *param = lambda; } return client_object; } DT_Bool DT_ObjectRayCast(DT_ObjectHandle object, const DT_Vector3 source, const DT_Vector3 target, DT_Scalar max_param, DT_Scalar *param, DT_Vector3 hit_normal) { MT_Scalar lambda = MT_Scalar(max_param); MT_Vector3 normal; bool result = ((DT_Object *)object)->ray_cast(MT_Point3(source), MT_Point3(target), lambda, normal); if (result) { *param = lambda; normal.getValue(hit_normal); } return result; }