├── .DS_Store ├── KinectSimulator_IR.m ├── example_CAD ├── Cube.mat ├── Teapot.mat ├── BoxGrid.mat └── XboxController.mat ├── KinectSimulatorPic.png ├── KinectSimulator_Depth.m ├── opcodemesh ├── opcode │ ├── ReadMe.txt │ ├── scales TODO.txt │ ├── OPC_RayTriOverlap.h │ ├── OPC_TriBoxOverlap.h │ ├── OPC_PlanesAABBOverlap.h │ ├── StdAfx.cpp │ ├── Stdafx.h │ ├── Ice │ │ ├── IceRandom.cpp │ │ ├── IceAxes.h │ │ ├── IceRandom.h │ │ ├── IceUtils.cpp │ │ ├── IcePairs.h │ │ ├── IceMatrix3x3.cpp │ │ ├── IceSegment.cpp │ │ ├── IcePlane.cpp │ │ ├── IceTriList.h │ │ ├── IceTriangle.h │ │ ├── IceSegment.h │ │ ├── IceRay.cpp │ │ ├── IceRevisitedRadix.h │ │ ├── IceIndexedTriangle.h │ │ ├── IceHPoint.cpp │ │ ├── IceLSS.h │ │ ├── IcePreprocessor.h │ │ ├── IceMemoryMacros.h │ │ ├── IceRay.h │ │ ├── IcePlane.h │ │ ├── IceBoundingSphere.h │ │ └── IceHPoint.h │ ├── TemporalCoherence.txt │ ├── OPC_PlanesTriOverlap.h │ ├── OPC_IceHook.h │ ├── OPC_BoxPruning.h │ ├── OPC_Picking.h │ ├── OPC_Common.cpp │ ├── OPC_Collider.cpp │ ├── Opcode.cpp │ ├── OPC_SphereAABBOverlap.h │ ├── OPC_Settings.h │ ├── OPC_Model.h │ ├── OPC_SweepAndPrune.h │ ├── OPC_AABBCollider.h │ ├── Opcode.h │ ├── OPC_RayAABBOverlap.h │ ├── OPC_VolumeCollider.cpp │ ├── OPC_Common.h │ ├── OPC_SphereCollider.h │ ├── OPC_LSSCollider.h │ ├── OPC_SphereTriOverlap.h │ ├── OPC_Picking.cpp │ ├── OPC_PlanesCollider.h │ ├── OPC_HybridModel.h │ ├── OPC_TriTriOverlapGilvan.h │ ├── OPC_BaseModel.cpp │ ├── OPC_OBBCollider.h │ └── OPC_VolumeCollider.h ├── OpcodeUserManual.pdf ├── matlab │ ├── opcodemeshmex.mexw64 │ ├── opcodemesh.m │ ├── patch_display.m │ ├── opcodemeshdemo.m │ └── opcodemeshdemo_clean.m ├── opcodemesh_license.txt ├── src_matlab │ ├── class_handle.hpp │ └── mexall.m └── README.txt ├── default_load_files ├── distReal.mat └── kinect-pattern_3x3.mat ├── license.txt └── demo_KinectSimulator.m /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael0113/KinectSimulator/HEAD/.DS_Store -------------------------------------------------------------------------------- /KinectSimulator_IR.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael0113/KinectSimulator/HEAD/KinectSimulator_IR.m -------------------------------------------------------------------------------- /example_CAD/Cube.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael0113/KinectSimulator/HEAD/example_CAD/Cube.mat -------------------------------------------------------------------------------- /KinectSimulatorPic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael0113/KinectSimulator/HEAD/KinectSimulatorPic.png -------------------------------------------------------------------------------- /example_CAD/Teapot.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael0113/KinectSimulator/HEAD/example_CAD/Teapot.mat -------------------------------------------------------------------------------- /KinectSimulator_Depth.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael0113/KinectSimulator/HEAD/KinectSimulator_Depth.m -------------------------------------------------------------------------------- /example_CAD/BoxGrid.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael0113/KinectSimulator/HEAD/example_CAD/BoxGrid.mat -------------------------------------------------------------------------------- /example_CAD/XboxController.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael0113/KinectSimulator/HEAD/example_CAD/XboxController.mat -------------------------------------------------------------------------------- /opcodemesh/opcode/ReadMe.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael0113/KinectSimulator/HEAD/opcodemesh/opcode/ReadMe.txt -------------------------------------------------------------------------------- /default_load_files/distReal.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael0113/KinectSimulator/HEAD/default_load_files/distReal.mat -------------------------------------------------------------------------------- /opcodemesh/OpcodeUserManual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael0113/KinectSimulator/HEAD/opcodemesh/OpcodeUserManual.pdf -------------------------------------------------------------------------------- /opcodemesh/opcode/scales TODO.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael0113/KinectSimulator/HEAD/opcodemesh/opcode/scales TODO.txt -------------------------------------------------------------------------------- /opcodemesh/opcode/OPC_RayTriOverlap.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael0113/KinectSimulator/HEAD/opcodemesh/opcode/OPC_RayTriOverlap.h -------------------------------------------------------------------------------- /opcodemesh/opcode/OPC_TriBoxOverlap.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael0113/KinectSimulator/HEAD/opcodemesh/opcode/OPC_TriBoxOverlap.h -------------------------------------------------------------------------------- /opcodemesh/matlab/opcodemeshmex.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael0113/KinectSimulator/HEAD/opcodemesh/matlab/opcodemeshmex.mexw64 -------------------------------------------------------------------------------- /default_load_files/kinect-pattern_3x3.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael0113/KinectSimulator/HEAD/default_load_files/kinect-pattern_3x3.mat -------------------------------------------------------------------------------- /opcodemesh/opcode/OPC_PlanesAABBOverlap.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael0113/KinectSimulator/HEAD/opcodemesh/opcode/OPC_PlanesAABBOverlap.h -------------------------------------------------------------------------------- /opcodemesh/opcode/StdAfx.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /* 3 | * OPCODE - Optimized Collision Detection 4 | * Copyright (C) 2001 Pierre Terdiman 5 | * Homepage: http://www.codercorner.com/Opcode.htm 6 | */ 7 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | //#define ICE_MAIN 10 | #include "Stdafx.h" 11 | -------------------------------------------------------------------------------- /opcodemesh/matlab/opcodemesh.m: -------------------------------------------------------------------------------- 1 | classdef opcodemesh < handle 2 | properties (SetAccess = private, Hidden = true) 3 | objectHandle; % Handle to the underlying C++ class instance 4 | end 5 | methods 6 | %% Constructor - Create a new C++ class instance 7 | function this = opcodemesh(varargin) 8 | this.objectHandle = opcodemeshmex('create', varargin{:}); 9 | end 10 | 11 | %% Destructor - Destroy the C++ class instance 12 | function delete(this) 13 | opcodemeshmex('delete', this.objectHandle); 14 | end 15 | 16 | function varargout = intersect(this, varargin) 17 | [varargout{1:nargout}] = opcodemeshmex('intersect', this.objectHandle, varargin{:}); 18 | end 19 | 20 | function update(this, varargin) 21 | opcodemeshmex('update', this.objectHandle, varargin{:}); 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /opcodemesh/opcode/Stdafx.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /* 3 | * OPCODE - Optimized Collision Detection 4 | * Copyright (C) 2001 Pierre Terdiman 5 | * Homepage: http://www.codercorner.com/Opcode.htm 6 | */ 7 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | #if !defined(AFX_STDAFX_H__EFB95044_1D31_11D5_8B0F_0050BAC83302__INCLUDED_) 10 | #define AFX_STDAFX_H__EFB95044_1D31_11D5_8B0F_0050BAC83302__INCLUDED_ 11 | 12 | #if _MSC_VER > 1000 13 | #pragma once 14 | #endif // _MSC_VER > 1000 15 | 16 | // Insert your headers here 17 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 18 | 19 | #include "Opcode.h" 20 | 21 | //{{AFX_INSERT_LOCATION}} 22 | // Microsoft Visual C++ will insert additional declarations immediately before the previous line. 23 | 24 | #endif // !defined(AFX_STDAFX_H__EFB95044_1D31_11D5_8B0F_0050BAC83302__INCLUDED_) 25 | -------------------------------------------------------------------------------- /opcodemesh/matlab/patch_display.m: -------------------------------------------------------------------------------- 1 | function h = patch_display( fv ,showfacecolor, showtexture) 2 | %SHOWMESH Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | V = fv.vertices; 6 | F = fv.faces; 7 | 8 | pmax = max(fv.vertices); 9 | pmin = min(fv.vertices); 10 | pabs = 1*max(abs(pmax),abs(pmin)); 11 | pmax = pmax + pabs; 12 | pmin = pmin - pabs; 13 | 14 | if nargin<2 15 | showfacecolor=0; 16 | end 17 | if nargin<3, 18 | showtexture = 0; 19 | end 20 | if ~showfacecolor 21 | h = trisurf(F,V(:,1),V(:,2),V(:,3),'facecolor',[.9 .8 .6],'edgecolor','none'); 22 | else 23 | h = trisurf(F,V(:,1),V(:,2),V(:,3),'facecolor',[.9 .8 .6],'edgecolor',[1 0 0]); 24 | end 25 | axis equal, view([ 0 0 100]), axis vis3d, zoom(1.5); 26 | axis([pmin(1) pmax(1) pmin(2) pmax(2) pmin(3) pmax(3)]); 27 | camlight('headlight'); camlight right; 28 | material shiny; 29 | 30 | if showtexture && isfield(fv,'textureimage'), 31 | img(:,:,1) = adapthisteq(fv.textureimage(:,:,1)); 32 | img(:,:,2) = adapthisteq(fv.textureimage(:,:,2)); 33 | img(:,:,3) = adapthisteq(fv.textureimage(:,:,3)); 34 | %img = decorrstretch(fv.textureimage); 35 | patch_texture(h,img,fv.texturevertices); 36 | end 37 | rotate3d on; 38 | 39 | -------------------------------------------------------------------------------- /opcodemesh/opcode/Ice/IceRandom.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /** 3 | * Contains code for random generators. 4 | * \file IceRandom.cpp 5 | * \author Pierre Terdiman 6 | * \date August, 9, 2001 7 | */ 8 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | // Precompiled Header 12 | #include "Stdafx.h" 13 | 14 | using namespace IceCore; 15 | 16 | void IceCore:: SRand(udword seed) 17 | { 18 | srand(seed); 19 | } 20 | 21 | udword IceCore::Rand() 22 | { 23 | return rand(); 24 | } 25 | 26 | 27 | static BasicRandom gRandomGenerator(42); 28 | 29 | udword IceCore::GetRandomIndex(udword max_index) 30 | { 31 | // We don't use rand() since it's limited to RAND_MAX 32 | udword Index = gRandomGenerator.Randomize(); 33 | return Index % max_index; 34 | } 35 | 36 | -------------------------------------------------------------------------------- /opcodemesh/opcode/TemporalCoherence.txt: -------------------------------------------------------------------------------- 1 | 2 | > Hi John, 3 | > 4 | > I know I'll forget to tell you this if I don't write it right now.... 5 | > 6 | > >(2) How is the receiving geometry for the shadow decided? 7 | > 8 | > I wrote about an LSS-test but actually performing a new VFC test (from the 9 | > light's view) is the same. In both cases, here's a trick to take advantage 10 | > of temporal coherence : test the world against a slightly larger than 11 | > necessary LSS or frustum. Keep the list of touched surfaces. Then next 12 | > frame, if the new volume is still contained within the previous one used 13 | for 14 | > the query, you can reuse the same list immediately. Actually it's a bit 15 | > similar to what you did in your sphere-tree, I think. Anyway, now the 16 | O(log 17 | > N) VFC is O(1) for some frames. It's not worth it for the "real" VFC, but 18 | > when you have N virtual frustum to test to drop N shadows, that's another 19 | > story. 20 | > 21 | > Two downsides: 22 | > - You need more ram to keep track of one list of meshes / shadow, but 23 | > usually it's not a lot. 24 | > - By using a larger volume for the query you possibly touch more 25 | > faces/surfaces, which will be rendered in the shadow pass. Usually it's 26 | not 27 | > a problem either since rendering is simply faster than geometric queries 28 | > those days. But of course, "your mileage may vary". 29 | > 30 | > Happy new year ! 31 | > 32 | > Pierre 33 | -------------------------------------------------------------------------------- /opcodemesh/opcodemesh_license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Vipin Vijayan 2 | Copyright (c) 2010, Dirk-Jan Kroon 3 | Copyright (c) 2012, Oliver Woodford 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are 8 | met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /opcodemesh/matlab/opcodemeshdemo.m: -------------------------------------------------------------------------------- 1 | function opcodemeshdemo() 2 | 3 | % Very simple shape 4 | % f = [1 2 3]'; v = [-1 0 0 ; 1 1 0 ; 1 -1 0]'; 5 | % [hit,d,trix,bary] = opcodemeshmex('intersect',t,1,1,[0 0 0.5]',[0 0 -1]'); 6 | 7 | % More complex shape 8 | obj = read_obj('deer_bound.obj'); 9 | v = obj.vertices; 10 | f = obj.objects(3).data.vertices; 11 | 12 | patch_display(struct('vertices',v,'faces',f)) 13 | 14 | minb = min(v(:,[3 2])); 15 | maxb = max(v(:,[3 2])); 16 | %t = opcodemeshmex('create',v',f'); 17 | t = opcodemesh(v',f'); 18 | 19 | 20 | imgsize = 300; 21 | 22 | x = (1:imgsize) ./ imgsize .* (maxb(1) - minb(1)) + minb(1); 23 | y = (1:imgsize) ./ imgsize .* (maxb(2) - minb(2)) + minb(2); 24 | [X,Y] = meshgrid(x,y); 25 | Y = flipud(Y); 26 | Z = 1000*ones(size(X)); 27 | 28 | from = [-Z(:) Y(:) X(:)]'; 29 | to = [Z(:) Y(:) X(:)]'; 30 | 31 | %[hit,d,trix,bary] = opcodemeshmex('intersect',t,from,to-from); 32 | [hit,d,trix,bary] = t.intersect(from,to-from); 33 | img_d = reshape(d,size(Z)); 34 | figure,imagesc(img_d); 35 | 36 | % You can update the vertices on the fly 37 | v=v+0.2; 38 | %opcodemeshmex('update',t,v'); 39 | t.update(v'); 40 | 41 | %[hit,d,trix,bary] = opcodemeshmex('intersect',t,from,to-from); 42 | [hit,d,trix,bary] = t.intersect(from,to-from); 43 | img_d = reshape(d,size(Z)); 44 | figure,imagesc(img_d); 45 | 46 | % For correct values of d, normaize each column of the (to-from) 3xN matrix 47 | [hit,d,trix,bary] = t.intersect(from,normc(to-from)); 48 | img_d = reshape(d,size(Z)); 49 | figure,imagesc(img_d); 50 | 51 | % opcodemeshmex('delete',t); -------------------------------------------------------------------------------- /opcodemesh/opcode/OPC_PlanesTriOverlap.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /** 3 | * Planes-triangle overlap test. 4 | * \param in_clip_mask [in] bitmask for active planes 5 | * \return TRUE if triangle overlap planes 6 | * \warning THIS IS A CONSERVATIVE TEST !! Some triangles will be returned as intersecting, while they're not! 7 | */ 8 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | inline_ BOOL PlanesCollider::PlanesTriOverlap(udword in_clip_mask) 10 | { 11 | // Stats 12 | mNbVolumePrimTests++; 13 | 14 | const IceMaths::Plane* p = mPlanes; 15 | udword Mask = 1; 16 | 17 | while(Mask<=in_clip_mask) 18 | { 19 | if(in_clip_mask & Mask) 20 | { 21 | // distance with scaled vertices 22 | float d0 = p->Distance( (*mVP.Vertex[0])*mLocalScale ); 23 | float d1 = p->Distance( (*mVP.Vertex[1])*mLocalScale ); 24 | float d2 = p->Distance( (*mVP.Vertex[2])*mLocalScale ); 25 | if(d0>0.0f && d1>0.0f && d2>0.0f) return FALSE; 26 | // if(!(IR(d0)&SIGN_BITMASK) && !(IR(d1)&SIGN_BITMASK) && !(IR(d2)&SIGN_BITMASK)) return FALSE; 27 | } 28 | Mask+=Mask; 29 | p++; 30 | } 31 | /* 32 | for(udword i=0;i<6;i++) 33 | { 34 | float d0 = p[i].Distance(mLeafVerts[0]); 35 | float d1 = p[i].Distance(mLeafVerts[1]); 36 | float d2 = p[i].Distance(mLeafVerts[2]); 37 | if(d0>0.0f && d1>0.0f && d2>0.0f) return false; 38 | } 39 | */ 40 | return TRUE; 41 | } 42 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Michael Landau 2 | Copyright (c) 2014, Vipin Vijayan 3 | Copyright (c) 2012, Oliver Woodford 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are 8 | met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution 15 | * Neither the name of the University of Virginia nor the names 16 | of its contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /opcodemesh/opcode/Ice/IceAxes.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /** 3 | * Contains axes definition. 4 | * \file IceAxes.h 5 | * \author Pierre Terdiman 6 | * \date January, 29, 2000 7 | */ 8 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | // Include Guard 12 | #ifndef __ICEAXES_H__ 13 | #define __ICEAXES_H__ 14 | 15 | enum PointComponent 16 | { 17 | _X = 0, 18 | _Y = 1, 19 | _Z = 2, 20 | _W = 3, 21 | 22 | _FORCE_DWORD = 0x7fffffff 23 | }; 24 | 25 | enum AxisOrder 26 | { 27 | AXES_XYZ = (_X)|(_Y<<2)|(_Z<<4), 28 | AXES_XZY = (_X)|(_Z<<2)|(_Y<<4), 29 | AXES_YXZ = (_Y)|(_X<<2)|(_Z<<4), 30 | AXES_YZX = (_Y)|(_Z<<2)|(_X<<4), 31 | AXES_ZXY = (_Z)|(_X<<2)|(_Y<<4), 32 | AXES_ZYX = (_Z)|(_Y<<2)|(_X<<4), 33 | 34 | AXES_FORCE_DWORD = 0x7fffffff 35 | }; 36 | 37 | class ICEMATHS_API Axes 38 | { 39 | public: 40 | 41 | inline_ Axes(AxisOrder order) 42 | { 43 | mAxis0 = (order ) & 3; 44 | mAxis1 = (order>>2) & 3; 45 | mAxis2 = (order>>4) & 3; 46 | } 47 | inline_ ~Axes() {} 48 | 49 | udword mAxis0; 50 | udword mAxis1; 51 | udword mAxis2; 52 | }; 53 | 54 | #endif // __ICEAXES_H__ 55 | -------------------------------------------------------------------------------- /opcodemesh/opcode/Ice/IceRandom.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /** 3 | * Contains code for random generators. 4 | * \file IceRandom.h 5 | * \author Pierre Terdiman 6 | * \date August, 9, 2001 7 | */ 8 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | // Include Guard 12 | #ifndef __ICERANDOM_H__ 13 | #define __ICERANDOM_H__ 14 | 15 | FUNCTION ICECORE_API void SRand(udword seed); 16 | FUNCTION ICECORE_API udword Rand(); 17 | 18 | //! Returns a unit random floating-point value 19 | inline_ float UnitRandomFloat() { return float(Rand()) * ONE_OVER_RAND_MAX; } 20 | 21 | //! Returns a random index so that 0<= index < max_index 22 | ICECORE_API udword GetRandomIndex(udword max_index); 23 | 24 | class ICECORE_API BasicRandom 25 | { 26 | public: 27 | 28 | //! Constructor 29 | inline_ BasicRandom(udword seed=0) : mRnd(seed) {} 30 | //! Destructor 31 | inline_ ~BasicRandom() {} 32 | 33 | inline_ void SetSeed(udword seed) { mRnd = seed; } 34 | inline_ udword GetCurrentValue() const { return mRnd; } 35 | inline_ udword Randomize() { mRnd = mRnd * 2147001325 + 715136305; return mRnd; } 36 | 37 | private: 38 | udword mRnd; 39 | }; 40 | 41 | #endif // __ICERANDOM_H__ 42 | 43 | -------------------------------------------------------------------------------- /opcodemesh/src_matlab/class_handle.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __CLASS_HANDLE_HPP__ 2 | #define __CLASS_HANDLE_HPP__ 3 | #include "mex.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define CLASS_HANDLE_SIGNATURE 0xFF00F0A5 10 | template class class_handle 11 | { 12 | public: 13 | class_handle(base *ptr) : ptr_m(ptr), name_m(typeid(base).name()) { signature_m = CLASS_HANDLE_SIGNATURE; } 14 | ~class_handle() { signature_m = 0; delete ptr_m; } 15 | bool isValid() { return ((signature_m == CLASS_HANDLE_SIGNATURE) && !strcmp(name_m.c_str(), typeid(base).name())); } 16 | base *ptr() { return ptr_m; } 17 | 18 | private: 19 | uint32_t signature_m; 20 | std::string name_m; 21 | base *ptr_m; 22 | }; 23 | 24 | template inline mxArray *convertPtr2Mat(base *ptr) 25 | { 26 | mexLock(); 27 | mxArray *out = mxCreateNumericMatrix(1, 1, mxUINT64_CLASS, mxREAL); 28 | *((uint64_t *)mxGetData(out)) = reinterpret_cast(new class_handle(ptr)); 29 | return out; 30 | } 31 | 32 | template inline class_handle *convertMat2HandlePtr(const mxArray *in) 33 | { 34 | if (mxGetNumberOfElements(in) != 1 || mxGetClassID(in) != mxUINT64_CLASS || mxIsComplex(in)) 35 | mexErrMsgTxt("Input must be a real uint64 scalar."); 36 | class_handle *ptr = reinterpret_cast *>(*((uint64_t *)mxGetData(in))); 37 | if (!ptr->isValid()) 38 | mexErrMsgTxt("Handle not valid."); 39 | return ptr; 40 | } 41 | 42 | template inline base *convertMat2Ptr(const mxArray *in) 43 | { 44 | return convertMat2HandlePtr(in)->ptr(); 45 | } 46 | 47 | template inline void destroyObject(const mxArray *in) 48 | { 49 | delete convertMat2HandlePtr(in); 50 | mexUnlock(); 51 | } 52 | 53 | #endif // __CLASS_HANDLE_HPP__ 54 | -------------------------------------------------------------------------------- /opcodemesh/opcode/Ice/IceUtils.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /** 3 | * Contains misc. useful macros & defines. 4 | * \file IceUtils.cpp 5 | * \author Pierre Terdiman (collected from various sources) 6 | * \date April, 4, 2000 7 | */ 8 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | // Precompiled Header 12 | #include "Stdafx.h" 13 | 14 | using namespace IceCore; 15 | 16 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 | /** 18 | * Returns the alignment of the input address. 19 | * \fn Alignment() 20 | * \param address [in] address to check 21 | * \return the best alignment (e.g. 1 for odd addresses, etc) 22 | */ 23 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 24 | udword IceCore::Alignment(udword address) 25 | { 26 | // Returns 0 for null addresses 27 | if(!address) return 0; 28 | 29 | // Test all bits 30 | udword Align = 1; 31 | for(udword i=1;i<32;i++) 32 | { 33 | // Returns as soon as the alignment is broken 34 | if(address&Align) return Align; 35 | Align<<=1; 36 | } 37 | // Here all bits are null, except the highest one (else the address would be null) 38 | return Align; 39 | } 40 | -------------------------------------------------------------------------------- /opcodemesh/opcode/Ice/IcePairs.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /** 3 | * Contains a simple pair class. 4 | * \file IcePairs.h 5 | * \author Pierre Terdiman 6 | * \date January, 13, 2003 7 | */ 8 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | // Include Guard 12 | #ifndef __ICEPAIRS_H__ 13 | #define __ICEPAIRS_H__ 14 | 15 | //! A generic couple structure 16 | struct ICECORE_API Pair 17 | { 18 | inline_ Pair() {} 19 | inline_ Pair(udword i0, udword i1) : id0(i0), id1(i1) {} 20 | 21 | udword id0; //!< First index of the pair 22 | udword id1; //!< Second index of the pair 23 | }; 24 | 25 | class ICECORE_API Pairs : private Container 26 | { 27 | public: 28 | // Constructor / Destructor 29 | Pairs() {} 30 | ~Pairs() {} 31 | 32 | inline_ udword GetNbPairs() const { return GetNbEntries()>>1; } 33 | inline_ const Pair* GetPairs() const { return (const Pair*)GetEntries(); } 34 | inline_ const Pair* GetPair(udword i) const { return (const Pair*)&GetEntries()[i+i]; } 35 | 36 | inline_ BOOL HasPairs() const { return IsNotEmpty(); } 37 | 38 | inline_ void ResetPairs() { Reset(); } 39 | inline_ void DeleteLastPair() { DeleteLastEntry(); DeleteLastEntry(); } 40 | 41 | inline_ void AddPair(const Pair& p) { Add(p.id0).Add(p.id1); } 42 | inline_ void AddPair(udword id0, udword id1) { Add(id0).Add(id1); } 43 | }; 44 | 45 | #endif // __ICEPAIRS_H__ 46 | -------------------------------------------------------------------------------- /opcodemesh/opcode/OPC_IceHook.h: -------------------------------------------------------------------------------- 1 | 2 | // Should be included by Opcode.h if needed 3 | 4 | #define ICE_DONT_CHECK_COMPILER_OPTIONS 5 | 6 | // From Windows... 7 | typedef int BOOL; 8 | #ifndef FALSE 9 | #define FALSE 0 10 | #endif 11 | 12 | #ifndef TRUE 13 | #define TRUE 1 14 | #endif 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #ifndef ASSERT 24 | #define ASSERT(exp) {} 25 | #endif 26 | #define ICE_COMPILE_TIME_ASSERT(exp) extern char ICE_Dummy[ (exp) ? 1 : -1 ] 27 | 28 | extern void Opcode_Log (const char* msg, ...); 29 | extern bool Opcode_Err (const char* msg, ...); 30 | 31 | #define Log Opcode_Log 32 | #define SetIceError Opcode_Err 33 | // #define Log {} 34 | // #define SetIceError(a,b) false 35 | 36 | #define EC_OUTOFMEMORY "Out of memory" 37 | 38 | #include "Ice/IcePreprocessor.h" 39 | 40 | #undef ICECORE_API 41 | #define ICECORE_API OPCODE_API 42 | 43 | #include "Ice/IceTypes.h" 44 | #include "Ice/IceFPU.h" 45 | #include "Ice/IceMemoryMacros.h" 46 | 47 | namespace IceCore 48 | { 49 | #include "Ice/IceUtils.h" 50 | #include "Ice/IceContainer.h" 51 | #include "Ice/IcePairs.h" 52 | #include "Ice/IceRevisitedRadix.h" 53 | #include "Ice/IceRandom.h" 54 | } 55 | using namespace IceCore; 56 | 57 | #define ICEMATHS_API OPCODE_API 58 | namespace IceMaths 59 | { 60 | #include "Ice/IceAxes.h" 61 | #include "Ice/IcePoint.h" 62 | #include "Ice/IceHPoint.h" 63 | #include "Ice/IceMatrix3x3.h" 64 | #include "Ice/IceMatrix4x4.h" 65 | #include "Ice/IcePlane.h" 66 | #include "Ice/IceRay.h" 67 | #include "Ice/IceIndexedTriangle.h" 68 | #include "Ice/IceTriangle.h" 69 | #include "Ice/IceTriList.h" 70 | #include "Ice/IceAABB.h" 71 | #include "Ice/IceOBB.h" 72 | #include "Ice/IceBoundingSphere.h" 73 | #include "Ice/IceSegment.h" 74 | #include "Ice/IceLSS.h" 75 | } 76 | //using namespace IceMaths; 77 | -------------------------------------------------------------------------------- /opcodemesh/opcode/Ice/IceMatrix3x3.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /** 3 | * Contains code for 3x3 matrices. 4 | * \file IceMatrix3x3.cpp 5 | * \author Pierre Terdiman 6 | * \date April, 4, 2000 7 | */ 8 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | /** 12 | * 3x3 matrix. 13 | * DirectX-compliant, ie row-column order, ie m[Row][Col]. 14 | * Same as: 15 | * m11 m12 m13 first row. 16 | * m21 m22 m23 second row. 17 | * m31 m32 m33 third row. 18 | * Stored in memory as m11 m12 m13 m21... 19 | * 20 | * Multiplication rules: 21 | * 22 | * [x'y'z'] = [xyz][M] 23 | * 24 | * x' = x*m11 + y*m21 + z*m31 25 | * y' = x*m12 + y*m22 + z*m32 26 | * z' = x*m13 + y*m23 + z*m33 27 | * 28 | * \class Matrix3x3 29 | * \author Pierre Terdiman 30 | * \version 1.0 31 | */ 32 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 33 | 34 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 35 | // Precompiled Header 36 | #include "Stdafx.h" 37 | 38 | using namespace IceMaths; 39 | 40 | // Cast operator 41 | Matrix3x3::operator Matrix4x4() const 42 | { 43 | return Matrix4x4( 44 | m[0][0], m[0][1], m[0][2], 0.0f, 45 | m[1][0], m[1][1], m[1][2], 0.0f, 46 | m[2][0], m[2][1], m[2][2], 0.0f, 47 | 0.0f, 0.0f, 0.0f, 1.0f); 48 | } 49 | -------------------------------------------------------------------------------- /opcodemesh/opcode/OPC_BoxPruning.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /* 3 | * OPCODE - Optimized Collision Detection 4 | * Copyright (C) 2001 Pierre Terdiman 5 | * Homepage: http://www.codercorner.com/Opcode.htm 6 | */ 7 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 10 | /** 11 | * Contains code for box pruning. 12 | * \file IceBoxPruning.h 13 | * \author Pierre Terdiman 14 | * \date January, 29, 2000 15 | */ 16 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | // Include Guard 20 | #ifndef __OPC_BOXPRUNING_H__ 21 | #define __OPC_BOXPRUNING_H__ 22 | 23 | // Optimized versions 24 | FUNCTION OPCODE_API bool CompleteBoxPruning(udword nb, const IceMaths::AABB** array, Pairs& pairs, const IceMaths::Axes& axes); 25 | FUNCTION OPCODE_API bool BipartiteBoxPruning(udword nb0, const IceMaths::AABB** array0, udword nb1, const IceMaths::AABB** array1, Pairs& pairs, const IceMaths::Axes& axes); 26 | 27 | // Brute-force versions 28 | FUNCTION OPCODE_API bool BruteForceCompleteBoxTest(udword nb, const IceMaths::AABB** array, Pairs& pairs); 29 | FUNCTION OPCODE_API bool BruteForceBipartiteBoxTest(udword nb0, const IceMaths::AABB** array0, udword nb1, const IceMaths::AABB** array1, Pairs& pairs); 30 | 31 | #endif //__OPC_BOXPRUNING_H__ 32 | -------------------------------------------------------------------------------- /opcodemesh/src_matlab/mexall.m: -------------------------------------------------------------------------------- 1 | %mex -c -v -I../opcode -I../opcode/Ice 2 | mex -I../opcode -I../opcode/Ice opcodemeshmex.cpp ... 3 | ../opcode/OPC_AABBCollider.cpp ... 4 | ../opcode/OPC_AABBTree.cpp ... 5 | ../opcode/OPC_BaseModel.cpp ... 6 | ../opcode/OPC_BoxPruning.cpp ... 7 | ../opcode/OPC_Collider.cpp ... 8 | ../opcode/OPC_Common.cpp ... 9 | ../opcode/OPC_HybridModel.cpp ... 10 | ../opcode/OPC_LSSCollider.cpp ... 11 | ../opcode/OPC_MeshInterface.cpp ... 12 | ../opcode/OPC_Model.cpp ... 13 | ../opcode/OPC_OBBCollider.cpp ... 14 | ../opcode/Opcode.cpp ... 15 | ../opcode/OPC_OptimizedTree.cpp ... 16 | ../opcode/OPC_Picking.cpp ... 17 | ../opcode/OPC_PlanesCollider.cpp ... 18 | ../opcode/OPC_RayCollider.cpp ... 19 | ../opcode/OPC_SphereCollider.cpp ... 20 | ../opcode/OPC_SweepAndPrune.cpp ... 21 | ../opcode/OPC_TreeBuilders.cpp ... 22 | ../opcode/OPC_TreeCollider.cpp ... 23 | ../opcode/OPC_VolumeCollider.cpp ... 24 | ../opcode/StdAfx.cpp ... 25 | ../opcode/Ice/IceAABB.cpp ... 26 | ../opcode/Ice/IceContainer.cpp ... 27 | ../opcode/Ice/IceHPoint.cpp ... 28 | ../opcode/Ice/IceIndexedTriangle.cpp ... 29 | ../opcode/Ice/IceMatrix3x3.cpp ... 30 | ../opcode/Ice/IceMatrix4x4.cpp ... 31 | ../opcode/Ice/IceOBB.cpp ... 32 | ../opcode/Ice/IcePlane.cpp ... 33 | ../opcode/Ice/IcePoint.cpp ... 34 | ../opcode/Ice/IceRandom.cpp ... 35 | ../opcode/Ice/IceRay.cpp ... 36 | ../opcode/Ice/IceRevisitedRadix.cpp ... 37 | ../opcode/Ice/IceSegment.cpp ... 38 | ../opcode/Ice/IceTriangle.cpp ... 39 | ../opcode/Ice/IceUtils.cpp 40 | 41 | 42 | 43 | movefile(sprintf('opcodemeshmex.%s',mexext),'../matlab'); 44 | -------------------------------------------------------------------------------- /opcodemesh/opcode/Ice/IceSegment.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /** 3 | * Contains code for segments. 4 | * \file IceSegment.cpp 5 | * \author Pierre Terdiman 6 | * \date April, 4, 2000 7 | */ 8 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | /** 12 | * Segment class. 13 | * A segment is defined by S(t) = mP0 * (1 - t) + mP1 * t, with 0 <= t <= 1 14 | * Alternatively, a segment is S(t) = Origin + t * Direction for 0 <= t <= 1. 15 | * Direction is not necessarily unit length. The end points are Origin = mP0 and Origin + Direction = mP1. 16 | * 17 | * \class Segment 18 | * \author Pierre Terdiman 19 | * \version 1.0 20 | */ 21 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 22 | 23 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 24 | // Precompiled Header 25 | #include "Stdafx.h" 26 | 27 | using namespace IceMaths; 28 | 29 | float Segment::SquareDistance(const Point& point, float* t) const 30 | { 31 | Point Diff = point - mP0; 32 | Point Dir = mP1 - mP0; 33 | float fT = Diff | Dir; 34 | 35 | if(fT<=0.0f) 36 | { 37 | fT = 0.0f; 38 | } 39 | else 40 | { 41 | float SqrLen= Dir.SquareMagnitude(); 42 | if(fT>=SqrLen) 43 | { 44 | fT = 1.0f; 45 | Diff -= Dir; 46 | } 47 | else 48 | { 49 | fT /= SqrLen; 50 | Diff -= fT*Dir; 51 | } 52 | } 53 | 54 | if(t) *t = fT; 55 | 56 | return Diff.SquareMagnitude(); 57 | } 58 | -------------------------------------------------------------------------------- /opcodemesh/opcode/Ice/IcePlane.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /** 3 | * Contains code for planes. 4 | * \file IcePlane.cpp 5 | * \author Pierre Terdiman 6 | * \date April, 4, 2000 7 | */ 8 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | /** 12 | * Plane class. 13 | * \class Plane 14 | * \author Pierre Terdiman 15 | * \version 1.0 16 | */ 17 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 18 | 19 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 20 | // Precompiled Header 21 | #include "Stdafx.h" 22 | 23 | using namespace IceMaths; 24 | 25 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 26 | /** 27 | * Computes the plane equation from 3 points. 28 | * \param p0 [in] first point 29 | * \param p1 [in] second point 30 | * \param p2 [in] third point 31 | * \return Self-reference 32 | */ 33 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 34 | Plane& Plane::Set(const Point& p0, const Point& p1, const Point& p2) 35 | { 36 | Point Edge0 = p1 - p0; 37 | Point Edge1 = p2 - p0; 38 | 39 | n = Edge0 ^ Edge1; 40 | n.Normalize(); 41 | 42 | d = -(p0 | n); 43 | 44 | return *this; 45 | } 46 | -------------------------------------------------------------------------------- /opcodemesh/opcode/OPC_Picking.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /* 3 | * OPCODE - Optimized Collision Detection 4 | * Copyright (C) 2001 Pierre Terdiman 5 | * Homepage: http://www.codercorner.com/Opcode.htm 6 | */ 7 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 10 | /** 11 | * Contains code to perform "picking". 12 | * \file OPC_Picking.h 13 | * \author Pierre Terdiman 14 | * \date March, 20, 2001 15 | */ 16 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | // Include Guard 20 | #ifndef __OPC_PICKING_H__ 21 | #define __OPC_PICKING_H__ 22 | 23 | #ifdef OPC_RAYHIT_CALLBACK 24 | 25 | enum CullMode 26 | { 27 | CULLMODE_NONE = 0, 28 | CULLMODE_CW = 1, 29 | CULLMODE_CCW = 2 30 | }; 31 | 32 | typedef CullMode (*CullModeCallback)(udword triangle_index, void* user_data); 33 | 34 | OPCODE_API bool SetupAllHits (RayCollider& collider, CollisionFaces& contacts); 35 | OPCODE_API bool SetupClosestHit (RayCollider& collider, CollisionFace& closest_contact); 36 | OPCODE_API bool SetupShadowFeeler (RayCollider& collider); 37 | OPCODE_API bool SetupInOutTest (RayCollider& collider); 38 | 39 | OPCODE_API bool Picking( 40 | CollisionFace& picked_face, 41 | const Ray& world_ray, const Model& model, const Matrix4x4* world, 42 | float min_dist, float max_dist, const Point& view_point, CullModeCallback callback, void* user_data); 43 | #endif 44 | 45 | #endif //__OPC_PICKING_H__ 46 | -------------------------------------------------------------------------------- /opcodemesh/README.txt: -------------------------------------------------------------------------------- 1 | This is a Matlab wrapper for OPCODE, which is a collision detection 2 | or ray casting library for triangular 3D meshes. 3 | 4 | OPCODE uses a couple of different aabb trees to store the mesh and this is 5 | a pretty simple wrapper for one of the trees. 6 | 7 | Nice thing about opcode is that it allows for deformable meshes, 8 | meaning that you can update the mesh while it is stored in the tree, 9 | which is much faster than what it takes to rebuild the aabb tree. 10 | 11 | Input and output: 12 | 13 | To make the tree: 14 | tree = opcodemesh(v,f); 15 | where 16 | vertices v : 3 x nv 17 | faces f : 3 x nf 18 | 19 | To intersect: 20 | [hit,d,trix,bary] = tree.intersect(orig,dir); 21 | where 22 | starting points orig : 3 x nc 23 | direction dir : 3 x nc 24 | whether hit or not hit : nc x 1 logical 25 | distance from orig to intersection point d : nc x 1 26 | index into f of the intersection triangle trix : 3 x nc 27 | barycentric coordinates of the triangle that the rays intersected bary : 2 x nc 28 | If a ray misses, then you have 0's for trix and nan's for the rest at that index. 29 | 30 | To get the actual points, just 31 | Q = repmat(B(1,:),3,1).*verts(faces(trix,1),:)' + ... 32 | repmat(B(2,:),3,1).*verts(faces(trix,2),:)' + ... 33 | repmat(1-B(1,:)-B(2,:),3,1).*verts(faces(trix,3),:)'; 34 | where verts = v, faces = f, B = bary. 35 | 36 | To update the mesh with a new set of vertices (as in deform the mesh): 37 | tree.update(vnew); 38 | vnew : 3 x nv 39 | vnew must be the same size and the original set of vertices. 40 | The topology of the mesh cannot change. 41 | 42 | To delete the tree (which is actually done automatically by Matlab): 43 | tree.delete(); 44 | 45 | To compile, go to ./src_matlab 46 | and run mexall.m 47 | which compiles the mex code and copies it to ./matlab 48 | (I compile it against everything in opcode, so it's a bit slow.) 49 | 50 | To run the demo, go to ./matlab 51 | and run opcodemeshdemo.m 52 | 53 | OPCODE is in 54 | http://www.lia.ufc.br/~gilvan/cd/ 55 | (which is a more portable version) 56 | and 57 | http://www.codercorner.com/Opcode.htm 58 | (the original site) 59 | 60 | Also has code from 61 | http://www.mathworks.com/matlabcentral/fileexchange/27982 62 | for reading wavefront files for the demo 63 | and much appreciated code from 64 | http://www.mathworks.com/matlabcentral/fileexchange/38964 65 | for nicely wrapping C++ functions in a Matlab class. 66 | -------------------------------------------------------------------------------- /opcodemesh/opcode/Ice/IceTriList.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /** 3 | * Contains code for a triangle container. 4 | * \file IceTrilist.h 5 | * \author Pierre Terdiman 6 | * \date April, 4, 2000 7 | */ 8 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | // Include Guard 12 | #ifndef __ICETRILIST_H__ 13 | #define __ICETRILIST_H__ 14 | 15 | class ICEMATHS_API TriList : public Container 16 | { 17 | public: 18 | // Constructor / Destructor 19 | TriList() {} 20 | ~TriList() {} 21 | 22 | inline_ udword GetNbTriangles() const { return GetNbEntries()/9; } 23 | inline_ Triangle* GetTriangles() const { return (Triangle*)GetEntries(); } 24 | 25 | void AddTri(const Triangle& tri) 26 | { 27 | Add(tri.mVerts[0].x).Add(tri.mVerts[0].y).Add(tri.mVerts[0].z); 28 | Add(tri.mVerts[1].x).Add(tri.mVerts[1].y).Add(tri.mVerts[1].z); 29 | Add(tri.mVerts[2].x).Add(tri.mVerts[2].y).Add(tri.mVerts[2].z); 30 | } 31 | 32 | void AddTri(const Point& p0, const Point& p1, const Point& p2) 33 | { 34 | Add(p0.x).Add(p0.y).Add(p0.z); 35 | Add(p1.x).Add(p1.y).Add(p1.z); 36 | Add(p2.x).Add(p2.y).Add(p2.z); 37 | } 38 | }; 39 | 40 | class ICEMATHS_API TriangleList : public Container 41 | { 42 | public: 43 | // Constructor / Destructor 44 | TriangleList() {} 45 | ~TriangleList() {} 46 | 47 | inline_ udword GetNbTriangles() const { return GetNbEntries()/3; } 48 | inline_ IndexedTriangle* GetTriangles() const { return (IndexedTriangle*)GetEntries();} 49 | 50 | void AddTriangle(const IndexedTriangle& tri) 51 | { 52 | Add(tri.mVRef[0]).Add(tri.mVRef[1]).Add(tri.mVRef[2]); 53 | } 54 | 55 | void AddTriangle(udword vref0, udword vref1, udword vref2) 56 | { 57 | Add(vref0).Add(vref1).Add(vref2); 58 | } 59 | }; 60 | 61 | #endif //__ICETRILIST_H__ 62 | -------------------------------------------------------------------------------- /opcodemesh/matlab/opcodemeshdemo_clean.m: -------------------------------------------------------------------------------- 1 | function opcodemeshdemo_clean() 2 | 3 | close all 4 | 5 | % Very simple shape 6 | % f = [1 2 3]'; v = [-1 0 0 ; 1 1 0 ; 1 -1 0]'; 7 | % [hit,d,trix,bary] = opcodemeshmex('intersect',t,1,1,[0 0 0.5]',[0 0 -1]'); 8 | 9 | % More complex shape 10 | obj = read_obj('deer_bound.obj'); 11 | v = obj.vertices; 12 | f = obj.objects(3).data.vertices; 13 | 14 | % CLEAN: Reshape vertices 15 | v = v'; 16 | f = f'; 17 | temp = v; 18 | v(1,:) = v(3,:); 19 | v(3,:) = temp(1,:); 20 | 21 | % Add wall CAD model (2 large facets) after shifting and rotating object -- 22 | wallX1 = 3; 23 | wallX2 = -3; 24 | wallY1 = 3; 25 | wallY2 = -3; 26 | wallZ = 3; 27 | 28 | v(:,end+1:end+4) = [wallX1 wallX1 wallX2 wallX2;... 29 | wallY1 wallY2 wallY1 wallY2;... 30 | wallZ wallZ wallZ wallZ]; 31 | f(:,end+1:end+2) = [size(v,2)-3 size(v,2)-3;... 32 | size(v,2)-1 size(v,2)-2;... 33 | size(v,2)-0 size(v,2)-0]; 34 | % ------------------------------------------------------------------------- 35 | 36 | figure, patch_display(struct('vertices',v','faces',f')) 37 | daspect([1 1 1]),set(gca,'XDir','reverse'),set(gca,'ZDir','reverse') 38 | xlabel('X-axis (mm)'),ylabel('Y-axis (mm)'),zlabel('Z-axis (mm)') 39 | 40 | minb = min(v,[],2); 41 | maxb = max(v,[],2); 42 | %t = opcodemeshmex('create',v',f'); 43 | t = opcodemesh(v,f); 44 | 45 | imgsize = 300; 46 | 47 | x = (imgsize:-1:1) ./ imgsize .* (maxb(1) - minb(1)) + minb(1); 48 | y = (1:imgsize) ./ imgsize .* (maxb(2) - minb(2)) + minb(2); 49 | [X,Y] = meshgrid(x,y); 50 | Y = flipud(Y); 51 | Z = 1000*ones(size(X)); 52 | 53 | from = [X(:)+10 Y(:) -Z(:)]' 54 | to = [X(:)-10 Y(:) Z(:)]' 55 | 56 | %[hit,d,trix,bary] = opcodemeshmex('intersect',t,from,to-from); 57 | [hit,d,trix,bary] = t.intersect(from,to-from); 58 | img_d = reshape(d,size(Z)); 59 | figure,imagesc(img_d); 60 | figure,imshow(img_d); 61 | 62 | bary(isnan(bary)) = size(f,2); 63 | trix(trix==0) = 1; 64 | xvals = bary(1,:).*v(1,f(1,trix)) + bary(2,:).*v(1,f(2,trix)) + (1-bary(1,:)-bary(2,:)).*v(1,f(3,trix)); 65 | figure, imshow(reshape(xvals,size(Z)),[min(xvals(:)) max(xvals(:))]) 66 | 67 | % You can update the vertices on the fly 68 | v=v+0.2; 69 | %opcodemeshmex('update',t,v'); 70 | t.update(v); 71 | 72 | %[hit,d,trix,bary] = opcodemeshmex('intersect',t,from,to-from); 73 | [hit,d,trix,bary] = t.intersect(from,to-from); 74 | img_d = reshape(d,size(Z)); 75 | figure,imagesc(img_d); 76 | 77 | % For correct values of d, normaize each column of the (to-from) 3xN matrix 78 | [hit,d,trix,bary] = t.intersect(from,normc(to-from)); 79 | img_d = reshape(d,size(Z)); 80 | figure,imagesc(img_d); 81 | 82 | % opcodemeshmex('delete',t); -------------------------------------------------------------------------------- /opcodemesh/opcode/Ice/IceTriangle.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /** 3 | * Contains a handy triangle class. 4 | * \file IceTriangle.h 5 | * \author Pierre Terdiman 6 | * \date January, 17, 2000 7 | */ 8 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | // Include Guard 12 | #ifndef __ICETRIANGLE_H__ 13 | #define __ICETRIANGLE_H__ 14 | 15 | // Forward declarations 16 | class Moment; 17 | 18 | // Partitioning values 19 | enum PartVal 20 | { 21 | TRI_MINUS_SPACE = 0, //!< Triangle is in the negative space 22 | TRI_PLUS_SPACE = 1, //!< Triangle is in the positive space 23 | TRI_INTERSECT = 2, //!< Triangle intersects plane 24 | TRI_ON_PLANE = 3, //!< Triangle and plane are coplanar 25 | 26 | TRI_FORCEDWORD = 0x7fffffff 27 | }; 28 | 29 | // A triangle class. 30 | class ICEMATHS_API Triangle 31 | { 32 | public: 33 | //! Constructor 34 | inline_ Triangle() {} 35 | //! Constructor 36 | inline_ Triangle(const Point& p0, const Point& p1, const Point& p2) { mVerts[0]=p0; mVerts[1]=p1; mVerts[2]=p2; } 37 | //! Copy constructor 38 | inline_ Triangle(const Triangle& triangle) 39 | { 40 | mVerts[0] = triangle.mVerts[0]; 41 | mVerts[1] = triangle.mVerts[1]; 42 | mVerts[2] = triangle.mVerts[2]; 43 | } 44 | //! Destructor 45 | inline_ ~Triangle() {} 46 | //! Vertices 47 | Point mVerts[3]; 48 | 49 | // Methods 50 | void Flip(); 51 | float Area() const; 52 | float Perimeter() const; 53 | float Compacity() const; 54 | void Normal(Point& normal) const; 55 | void DenormalizedNormal(Point& normal) const; 56 | void Center(Point& center) const; 57 | inline_ Plane PlaneEquation() const { return Plane(mVerts[0], mVerts[1], mVerts[2]); } 58 | 59 | PartVal TestAgainstPlane(const Plane& plane, float epsilon) const; 60 | // float Distance(Point& cp, Point& cq, Tri& tri); 61 | void ComputeMoment(Moment& m); 62 | float MinEdgeLength() const; 63 | float MaxEdgeLength() const; 64 | void ComputePoint(float u, float v, Point& pt, udword* nearvtx=null) const; 65 | void Inflate(float fat_coeff, bool constant_border); 66 | }; 67 | 68 | #endif // __ICETRIANGLE_H__ 69 | -------------------------------------------------------------------------------- /opcodemesh/opcode/Ice/IceSegment.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /** 3 | * Contains code for segments. 4 | * \file IceSegment.h 5 | * \author Pierre Terdiman 6 | * \date April, 4, 2000 7 | */ 8 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | // Include Guard 12 | #ifndef __ICESEGMENT_H__ 13 | #define __ICESEGMENT_H__ 14 | 15 | class ICEMATHS_API Segment 16 | { 17 | public: 18 | //! Constructor 19 | inline_ Segment() {} 20 | //! Constructor 21 | inline_ Segment(const Point& p0, const Point& p1) : mP0(p0), mP1(p1) {} 22 | //! Copy constructor 23 | inline_ Segment(const Segment& seg) : mP0(seg.mP0), mP1(seg.mP1) {} 24 | //! Destructor 25 | inline_ ~Segment() {} 26 | 27 | inline_ const Point& GetOrigin() const { return mP0; } 28 | inline_ Point ComputeDirection() const { return mP1 - mP0; } 29 | inline_ void ComputeDirection(Point& dir) const { dir = mP1 - mP0; } 30 | inline_ float ComputeLength() const { return mP1.Distance(mP0); } 31 | inline_ float ComputeSquareLength() const { return mP1.SquareDistance(mP0); } 32 | 33 | inline_ void SetOriginDirection(const Point& origin, const Point& direction) 34 | { 35 | mP0 = mP1 = origin; 36 | mP1 += direction; 37 | } 38 | 39 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 40 | /** 41 | * Computes a point on the segment 42 | * \param pt [out] point on segment 43 | * \param t [in] point's parameter [t=0 => pt = mP0, t=1 => pt = mP1] 44 | */ 45 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 46 | inline_ void ComputePoint(Point& pt, float t) const { pt = mP0 + t * (mP1 - mP0); } 47 | 48 | float SquareDistance(const Point& point, float* t=null) const; 49 | inline_ float Distance(const Point& point, float* t=null) const { return sqrtf(SquareDistance(point, t)); } 50 | 51 | Point mP0; //!< Start of segment 52 | Point mP1; //!< End of segment 53 | }; 54 | 55 | #endif // __ICESEGMENT_H__ 56 | -------------------------------------------------------------------------------- /opcodemesh/opcode/Ice/IceRay.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /** 3 | * Contains code for rays. 4 | * \file IceRay.cpp 5 | * \author Pierre Terdiman 6 | * \date April, 4, 2000 7 | */ 8 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | /** 12 | * Ray class. 13 | * A ray is a half-line P(t) = mOrig + mDir * t, with 0 <= t <= +infinity 14 | * \class Ray 15 | * \author Pierre Terdiman 16 | * \version 1.0 17 | */ 18 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | /* 21 | O = Origin = impact point 22 | i = normalized vector along the x axis 23 | j = normalized vector along the y axis = actually the normal vector in O 24 | D = Direction vector, norm |D| = 1 25 | N = Projection of D on y axis, norm |N| = normal reaction 26 | T = Projection of D on x axis, norm |T| = tangential reaction 27 | R = Reflexion vector 28 | 29 | ^y 30 | | 31 | | 32 | | 33 | _ _ _| _ _ _ 34 | * * *| 35 | \ | / 36 | \ |N / | 37 | R\ | /D 38 | \ | / | 39 | \ | / 40 | _________\|/______*_______>x 41 | O T 42 | 43 | Let define theta = angle between D and N. Then cos(theta) = |N| / |D| = |N| since D is normalized. 44 | 45 | j|D = |j|*|D|*cos(theta) => |N| = j|D 46 | 47 | Then we simply have: 48 | 49 | D = N + T 50 | 51 | To compute tangential reaction : 52 | 53 | T = D - N 54 | 55 | To compute reflexion vector : 56 | 57 | R = N - T = N - (D-N) = 2*N - D 58 | */ 59 | 60 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 61 | // Precompiled Header 62 | #include "Stdafx.h" 63 | 64 | using namespace IceMaths; 65 | 66 | float Ray::SquareDistance(const Point& point, float* t) const 67 | { 68 | Point Diff = point - mOrig; 69 | float fT = Diff | mDir; 70 | 71 | if(fT<=0.0f) 72 | { 73 | fT = 0.0f; 74 | } 75 | else 76 | { 77 | fT /= mDir.SquareMagnitude(); 78 | Diff -= fT*mDir; 79 | } 80 | 81 | if(t) *t = fT; 82 | 83 | return Diff.SquareMagnitude(); 84 | } 85 | -------------------------------------------------------------------------------- /opcodemesh/opcode/Ice/IceRevisitedRadix.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /** 3 | * Contains source code from the article "Radix Sort Revisited". 4 | * \file IceRevisitedRadix.h 5 | * \author Pierre Terdiman 6 | * \date April, 4, 2000 7 | */ 8 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | // Include Guard 12 | #ifndef __ICERADIXSORT_H__ 13 | #define __ICERADIXSORT_H__ 14 | 15 | //! Allocate histograms & offsets locally 16 | #define RADIX_LOCAL_RAM 17 | 18 | enum RadixHint 19 | { 20 | RADIX_SIGNED, //!< Input values are signed 21 | RADIX_UNSIGNED, //!< Input values are unsigned 22 | 23 | RADIX_FORCE_DWORD = 0x7fffffff 24 | }; 25 | 26 | class ICECORE_API RadixSort 27 | { 28 | public: 29 | // Constructor/Destructor 30 | RadixSort(); 31 | ~RadixSort(); 32 | // Sorting methods 33 | RadixSort& Sort(const udword* input, udword nb, RadixHint hint=RADIX_SIGNED); 34 | RadixSort& Sort(const float* input, udword nb); 35 | 36 | //! Access to results. mRanks is a list of indices in sorted order, i.e. in the order you may further process your data 37 | inline_ const udword* GetRanks() const { return mRanks; } 38 | 39 | //! mIndices2 gets trashed on calling the sort routine, but otherwise you can recycle it the way you want. 40 | inline_ udword* GetRecyclable() const { return mRanks2; } 41 | 42 | // Stats 43 | udword GetUsedRam() const; 44 | //! Returns the total number of calls to the radix sorter. 45 | inline_ udword GetNbTotalCalls() const { return mTotalCalls; } 46 | //! Returns the number of eraly exits due to temporal coherence. 47 | inline_ udword GetNbHits() const { return mNbHits; } 48 | 49 | private: 50 | #ifndef RADIX_LOCAL_RAM 51 | udword* mHistogram; //!< Counters for each byte 52 | udword* mOffset; //!< Offsets (nearly a cumulative distribution function) 53 | #endif 54 | udword mCurrentSize; //!< Current size of the indices list 55 | udword* mRanks; //!< Two lists, swapped each pass 56 | udword* mRanks2; 57 | // Stats 58 | udword mTotalCalls; //!< Total number of calls to the sort routine 59 | udword mNbHits; //!< Number of early exits due to coherence 60 | // Internal methods 61 | void CheckResize(udword nb); 62 | bool Resize(udword nb); 63 | }; 64 | 65 | #endif // __ICERADIXSORT_H__ 66 | -------------------------------------------------------------------------------- /opcodemesh/opcode/OPC_Common.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /* 3 | * OPCODE - Optimized Collision Detection 4 | * Copyright (C) 2001 Pierre Terdiman 5 | * Homepage: http://www.codercorner.com/Opcode.htm 6 | */ 7 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 10 | /** 11 | * Contains common classes & defs used in OPCODE. 12 | * \file OPC_Common.cpp 13 | * \author Pierre Terdiman 14 | * \date March, 20, 2001 15 | */ 16 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | /** 20 | * An AABB dedicated to collision detection. 21 | * We don't use the generic AABB class included in ICE, since it can be a Min/Max or a Center/Extents one (depends 22 | * on compilation flags). Since the Center/Extents model is more efficient in collision detection, it was worth 23 | * using an extra special class. 24 | * 25 | * \class CollisionAABB 26 | * \author Pierre Terdiman 27 | * \version 1.3 28 | * \date March, 20, 2001 29 | */ 30 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 31 | 32 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 33 | /** 34 | * A quantized AABB. 35 | * Center/Extent model, using 16-bits integers. 36 | * 37 | * \class QuantizedAABB 38 | * \author Pierre Terdiman 39 | * \version 1.3 40 | * \date March, 20, 2001 41 | */ 42 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 43 | 44 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 45 | // Precompiled Header 46 | #include "Stdafx.h" 47 | 48 | using namespace Opcode; 49 | -------------------------------------------------------------------------------- /opcodemesh/opcode/OPC_Collider.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /* 3 | * OPCODE - Optimized Collision Detection 4 | * Copyright (C) 2001 Pierre Terdiman 5 | * Homepage: http://www.codercorner.com/Opcode.htm 6 | */ 7 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 10 | /** 11 | * Contains base collider class. 12 | * \file OPC_Collider.cpp 13 | * \author Pierre Terdiman 14 | * \date June, 2, 2001 15 | */ 16 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | /** 20 | * Contains the abstract class for colliders. 21 | * 22 | * \class Collider 23 | * \author Pierre Terdiman 24 | * \version 1.3 25 | * \date June, 2, 2001 26 | */ 27 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 28 | 29 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 30 | // Precompiled Header 31 | #include "Stdafx.h" 32 | 33 | using namespace Opcode; 34 | 35 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 36 | /** 37 | * Constructor. 38 | */ 39 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 40 | Collider::Collider() : 41 | mFlags (0), 42 | mCurrentModel (null), 43 | mIMesh (null) 44 | { 45 | } 46 | 47 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 48 | /** 49 | * Destructor. 50 | */ 51 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 52 | Collider::~Collider() 53 | { 54 | } 55 | -------------------------------------------------------------------------------- /opcodemesh/opcode/Opcode.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /* 3 | * OPCODE - Optimized Collision Detection 4 | * Copyright (C) 2001 Pierre Terdiman 5 | * Homepage: http://www.codercorner.com/Opcode.htm 6 | */ 7 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 10 | /** 11 | * Main file for Opcode.dll. 12 | * \file Opcode.cpp 13 | * \author Pierre Terdiman 14 | * \date March, 20, 2001 15 | */ 16 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | /* 19 | Finding a good name is difficult! 20 | Here's the draft for this lib.... Spooky, uh? 21 | 22 | VOID? Very Optimized Interference Detection 23 | ZOID? Zappy's Optimized Interference Detection 24 | CID? Custom/Clever Interference Detection 25 | AID / ACID! Accurate Interference Detection 26 | QUID? Quick Interference Detection 27 | RIDE? Realtime Interference DEtection 28 | WIDE? Wicked Interference DEtection (....) 29 | GUID! 30 | KID ! k-dop interference detection :) 31 | OPCODE! OPtimized COllision DEtection 32 | */ 33 | 34 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 35 | 36 | // Precompiled Header 37 | #include "Stdafx.h" 38 | #include 39 | #include 40 | std::ofstream gFile; 41 | 42 | #include 43 | 44 | void Opcode_Log (const char* msg, ...) 45 | { 46 | va_list args; 47 | va_start (args, msg); 48 | char mesg[256]; 49 | sprintf(mesg, msg, args); 50 | gFile << mesg; 51 | gFile.flush(); 52 | va_end (args); 53 | } 54 | 55 | bool Opcode_Err (const char* msg, ...) 56 | { 57 | va_list args; 58 | va_start (args, msg); 59 | // Although it's called "..._Err", Opcode also reports less-than-fatal 60 | // messages through it 61 | 62 | char mesg[256]; 63 | sprintf(mesg, msg, args); 64 | gFile << mesg; 65 | gFile.flush(); 66 | va_end (args); 67 | return false; 68 | } 69 | 70 | bool Opcode::InitOpcode() 71 | { 72 | gFile.open("opcode.log"); 73 | Log("// Initializing OPCODE\n\n"); 74 | //LogAPIInfo(); 75 | return true; 76 | } 77 | 78 | void ReleasePruningSorters(); 79 | bool Opcode::CloseOpcode() 80 | { 81 | Log("// Closing OPCODE\n\n"); 82 | 83 | ReleasePruningSorters(); 84 | 85 | return true; 86 | } 87 | 88 | #ifdef ICE_MAIN 89 | 90 | void ModuleAttach(HINSTANCE hinstance) 91 | { 92 | } 93 | 94 | void ModuleDetach() 95 | { 96 | } 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /opcodemesh/opcode/OPC_SphereAABBOverlap.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /** 3 | * Sphere-AABB overlap test, based on Jim Arvo's code. 4 | * \param center_ [in] box center 5 | * \param extents_ [in] box extents 6 | * \return TRUE on overlap 7 | */ 8 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | inline_ BOOL SphereCollider::SphereAABBOverlap(const IceMaths::Point& center_, const IceMaths::Point& extents_) 10 | { 11 | // Stats 12 | mNbVolumeBVTests++; 13 | 14 | // Applies the model's local scale 15 | const IceMaths::Point center = center_ *mLocalScale; 16 | const IceMaths::Point extents = extents_*mLocalScale; 17 | 18 | float d = 0.0f; 19 | 20 | //find the square of the distance 21 | //from the sphere to the box 22 | #ifdef OLDIES 23 | for(udword i=0;i<3;i++) 24 | { 25 | float tmp = mCenter[i] - center[i]; 26 | float s = tmp + extents[i]; 27 | 28 | if(s<0.0f) d += s*s; 29 | else 30 | { 31 | s = tmp - extents[i]; 32 | if(s>0.0f) d += s*s; 33 | } 34 | } 35 | #endif 36 | 37 | //#ifdef NEW_TEST 38 | 39 | // float tmp = mCenter.x - center.x; 40 | // float s = tmp + extents.x; 41 | 42 | float tmp,s; 43 | 44 | tmp = mCenter.x - center.x; 45 | s = tmp + extents.x; 46 | 47 | if(s<0.0f) 48 | { 49 | d += s*s; 50 | if(d>mRadius2) return FALSE; 51 | } 52 | else 53 | { 54 | s = tmp - extents.x; 55 | if(s>0.0f) 56 | { 57 | d += s*s; 58 | if(d>mRadius2) return FALSE; 59 | } 60 | } 61 | 62 | tmp = mCenter.y - center.y; 63 | s = tmp + extents.y; 64 | 65 | if(s<0.0f) 66 | { 67 | d += s*s; 68 | if(d>mRadius2) return FALSE; 69 | } 70 | else 71 | { 72 | s = tmp - extents.y; 73 | if(s>0.0f) 74 | { 75 | d += s*s; 76 | if(d>mRadius2) return FALSE; 77 | } 78 | } 79 | 80 | tmp = mCenter.z - center.z; 81 | s = tmp + extents.z; 82 | 83 | if(s<0.0f) 84 | { 85 | d += s*s; 86 | if(d>mRadius2) return FALSE; 87 | } 88 | else 89 | { 90 | s = tmp - extents.z; 91 | if(s>0.0f) 92 | { 93 | d += s*s; 94 | if(d>mRadius2) return FALSE; 95 | } 96 | } 97 | //#endif 98 | 99 | #ifdef OLDIES 100 | // Point Min = center - extents; 101 | // Point Max = center + extents; 102 | 103 | float d = 0.0f; 104 | 105 | //find the square of the distance 106 | //from the sphere to the box 107 | for(udword i=0;i<3;i++) 108 | { 109 | float Min = center[i] - extents[i]; 110 | 111 | // if(mCenter[i]Max[i]) 123 | if(mCenter[i]>Max) 124 | { 125 | float s = mCenter[i] - Max; 126 | d += s*s; 127 | } 128 | } 129 | } 130 | #endif 131 | return d <= mRadius2; 132 | } 133 | -------------------------------------------------------------------------------- /opcodemesh/opcode/Ice/IceIndexedTriangle.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /** 3 | * Contains a handy indexed triangle class. 4 | * \file IceIndexedTriangle.h 5 | * \author Pierre Terdiman 6 | * \date January, 17, 2000 7 | */ 8 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | // Include Guard 12 | #ifndef __ICEINDEXEDTRIANGLE_H__ 13 | #define __ICEINDEXEDTRIANGLE_H__ 14 | 15 | // Forward declarations 16 | #ifdef _MSC_VER 17 | enum CubeIndex; 18 | #else 19 | typedef int CubeIndex; 20 | #endif 21 | 22 | // An indexed triangle class. 23 | class ICEMATHS_API IndexedTriangle 24 | { 25 | public: 26 | //! Constructor 27 | inline_ IndexedTriangle() {} 28 | //! Constructor 29 | inline_ IndexedTriangle(udword r0, udword r1, udword r2) { mVRef[0]=r0; mVRef[1]=r1; mVRef[2]=r2; } 30 | //! Copy constructor 31 | inline_ IndexedTriangle(const IndexedTriangle& triangle) 32 | { 33 | mVRef[0] = triangle.mVRef[0]; 34 | mVRef[1] = triangle.mVRef[1]; 35 | mVRef[2] = triangle.mVRef[2]; 36 | } 37 | //! Destructor 38 | inline_ ~IndexedTriangle() {} 39 | //! Vertex-references 40 | udword mVRef[3]; 41 | 42 | // Methods 43 | void Flip(); 44 | float Area(const Point* verts) const; 45 | float Perimeter(const Point* verts) const; 46 | float Compacity(const Point* verts) const; 47 | void Normal(const Point* verts, Point& normal) const; 48 | void DenormalizedNormal(const Point* verts, Point& normal) const; 49 | void Center(const Point* verts, Point& center) const; 50 | void CenteredNormal(const Point* verts, Point& normal) const; 51 | void RandomPoint(const Point* verts, Point& random) const; 52 | bool IsVisible(const Point* verts, const Point& source) const; 53 | bool BackfaceCulling(const Point* verts, const Point& source) const; 54 | float ComputeOcclusionPotential(const Point* verts, const Point& view) const; 55 | bool ReplaceVertex(udword oldref, udword newref); 56 | bool IsDegenerate() const; 57 | bool HasVertex(udword ref) const; 58 | bool HasVertex(udword ref, udword* index) const; 59 | ubyte FindEdge(udword vref0, udword vref1) const; 60 | udword OppositeVertex(udword vref0, udword vref1) const; 61 | inline_ udword OppositeVertex(ubyte edgenb) const { return mVRef[2-edgenb]; } 62 | void GetVRefs(ubyte edgenb, udword& vref0, udword& vref1, udword& vref2) const; 63 | float MinEdgeLength(const Point* verts) const; 64 | float MaxEdgeLength(const Point* verts) const; 65 | void ComputePoint(const Point* verts, float u, float v, Point& pt, udword* nearvtx=null) const; 66 | float Angle(const IndexedTriangle& tri, const Point* verts) const; 67 | inline_ Plane PlaneEquation(const Point* verts) const { return Plane(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]); } 68 | bool Equal(const IndexedTriangle& tri) const; 69 | CubeIndex ComputeCubeIndex(const Point* verts) const; 70 | }; 71 | 72 | #endif // __ICEINDEXEDTRIANGLE_H__ 73 | -------------------------------------------------------------------------------- /opcodemesh/opcode/OPC_Settings.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /* 3 | * OPCODE - Optimized Collision Detection 4 | * Copyright (C) 2001 Pierre Terdiman 5 | * Homepage: http://www.codercorner.com/Opcode.htm 6 | * 7 | * OPCODE modifications for scaled model support (and some minor things) 8 | * Copyright (C) 2004-2005 Gilvan Maia (gilvan 'at' vdl.ufc.br) 9 | * Check http://www.vdl.ufc.br/gilvan/coll/opcode/index.htm for news, more information and updates. 10 | * 11 | */ 12 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 13 | 14 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 15 | /** 16 | * Contains compilation flags. 17 | * \file OPC_Settings.h 18 | * \author Pierre Terdiman 19 | * \date May, 12, 2001 20 | */ 21 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 22 | 23 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 24 | // Include Guard 25 | #ifndef __OPC_SETTINGS_H__ 26 | #define __OPC_SETTINGS_H__ 27 | 28 | //! NEW!!! Use double-precision vertices. Remember that this is a "storage-only" option, because 29 | // every test performed in OPCODE for collision is done against a triangle. This means a 30 | // double precision triangle is 'cast' into a single precision one before true collision 31 | // tests are performed, trees built, etc. 32 | // #define OPC_DOUBLE_PRECISION 33 | 34 | //! Use CPU comparisons (comment that line to use standard FPU compares) 35 | #define OPC_CPU_COMPARE 36 | 37 | //! Use FCOMI / FCMOV on Pentium-Pro based processors (comment that line to use plain C++) 38 | #define OPC_USE_FCOMI 39 | 40 | //! Use epsilon value in tri-tri overlap test 41 | #define OPC_TRITRI_EPSILON_TEST 42 | 43 | //! Use tree-coherence or not [not implemented yet] 44 | // #define OPC_USE_TREE_COHERENCE 45 | 46 | //! Use callbacks or direct pointers. Using callbacks might be a bit slower (but probably not much) 47 | // #define OPC_USE_CALLBACKS 48 | 49 | //! Support triangle and vertex strides or not. Using strides might be a bit slower (but probably not much) 50 | //! HINT: Enable strides only if your vertices are NOT "tighly packed", ie, there are other info (not only 51 | //! vertex positions but colors, normals, etc) stored at each vertex. In this case, vertex strides 52 | //! must be set to the 'sizeof' the 'struct' holding your vertex positions in an array - if you used 53 | //! OpenGL vertex arrays, you should understand this fine. 54 | //! Thus, if you always have an array of 'xzy' coordinates and an array for indices, it could be better 55 | //! if you disable strides. 56 | #define OPC_USE_STRIDE 57 | 58 | //! Discard negative pointer in vanilla trees 59 | #define OPC_NO_NEG_VANILLA_TREE 60 | 61 | //! Use a callback in the ray collider 62 | //#define OPC_RAYHIT_CALLBACK 63 | 64 | // NB: no compilation flag to enable/disable stats since they're actually needed in the box/box overlap test. 65 | // Such flag will be added in the 1.3.3 version and will make things faster. Just wait. 66 | 67 | #endif //__OPC_SETTINGS_H__ 68 | -------------------------------------------------------------------------------- /opcodemesh/opcode/OPC_Model.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /* 3 | * OPCODE - Optimized Collision Detection 4 | * Copyright (C) 2001 Pierre Terdiman 5 | * Homepage: http://www.codercorner.com/Opcode.htm 6 | * 7 | * OPCODE modifications for scaled model support (and other things) 8 | * Copyright (C) 2004 Gilvan Maia (gilvan 'at' vdl.ufc.br) 9 | * Check http://www.vdl.ufc.br/gilvan/coll/opcode/index.htm for updates. 10 | */ 11 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 12 | 13 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 14 | /** 15 | * Contains code for OPCODE models. 16 | * \file OPC_Model.h 17 | * \author Pierre Terdiman 18 | * \date March, 20, 2001 19 | */ 20 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 21 | 22 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 23 | // Include Guard 24 | #ifndef __OPC_MODEL_H__ 25 | #define __OPC_MODEL_H__ 26 | 27 | class OPCODE_API Model : public BaseModel 28 | { 29 | public: 30 | // Constructor/Destructor 31 | Model(); 32 | virtual ~Model(); 33 | 34 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 35 | /** 36 | * Builds a collision model. 37 | * \param create [in] model creation structure 38 | * \return true if success 39 | */ 40 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 41 | override(BaseModel) bool Build(const OPCODECREATE& create); 42 | 43 | #ifdef __MESHMERIZER_H__ 44 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 45 | /** 46 | * Gets the collision hull. 47 | * \return the collision hull if it exists 48 | */ 49 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 50 | inline_ const CollisionHull* GetHull() const { return mHull; } 51 | #endif // __MESHMERIZER_H__ 52 | 53 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 54 | /** 55 | * Gets the number of bytes used by the tree. 56 | * \return amount of bytes used 57 | */ 58 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 59 | override(BaseModel) udword GetUsedBytes() const; 60 | 61 | private: 62 | #ifdef __MESHMERIZER_H__ 63 | CollisionHull* mHull; //!< Possible convex hull 64 | #endif // __MESHMERIZER_H__ 65 | // Internal methods 66 | void Release(); 67 | }; 68 | 69 | #endif //__OPC_MODEL_H__ 70 | -------------------------------------------------------------------------------- /opcodemesh/opcode/OPC_SweepAndPrune.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /* 3 | * OPCODE - Optimized Collision Detection 4 | * Copyright (C) 2001 Pierre Terdiman 5 | * Homepage: http://www.codercorner.com/Opcode.htm 6 | */ 7 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 10 | /** 11 | * Contains an implementation of the sweep-and-prune algorithm (moved from Z-Collide) 12 | * \file OPC_SweepAndPrune.h 13 | * \author Pierre Terdiman 14 | * \date January, 29, 2000 15 | */ 16 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | // Include Guard 20 | #ifndef __OPC_SWEEPANDPRUNE_H__ 21 | #define __OPC_SWEEPANDPRUNE_H__ 22 | 23 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 24 | /** 25 | * User-callback, called by OPCODE for each colliding pairs. 26 | * \param id0 [in] id of colliding object 27 | * \param id1 [in] id of colliding object 28 | * \param user_data [in] user-defined data 29 | * \return TRUE to continue enumeration 30 | */ 31 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 32 | typedef BOOL (*PairCallback) (udword id0, udword id1, void* user_data); 33 | 34 | class SAP_Element; 35 | class SAP_EndPoint; 36 | class SAP_Box; 37 | 38 | class OPCODE_API SAP_PairData 39 | { 40 | public: 41 | SAP_PairData(); 42 | ~SAP_PairData(); 43 | 44 | bool Init(udword nb_objects); 45 | 46 | void AddPair(udword id1, udword id2); 47 | void RemovePair(udword id1, udword id2); 48 | 49 | void DumpPairs(Pairs& pairs) const; 50 | void DumpPairs(PairCallback callback, void* user_data) const; 51 | private: 52 | udword mNbElements; //!< Total number of elements in the pool 53 | udword mNbUsedElements; //!< Number of used elements 54 | SAP_Element* mElementPool; //!< Array of mNbElements elements 55 | SAP_Element* mFirstFree; //!< First free element in the pool 56 | 57 | udword mNbObjects; //!< Max number of objects we can handle 58 | SAP_Element** mArray; //!< Pointers to pool 59 | // Internal methods 60 | SAP_Element* GetFreeElem(udword id, SAP_Element* next, udword* remap=null); 61 | inline_ void FreeElem(SAP_Element* elem); 62 | void Release(); 63 | }; 64 | 65 | class OPCODE_API SweepAndPrune 66 | { 67 | public: 68 | SweepAndPrune(); 69 | ~SweepAndPrune(); 70 | 71 | bool Init(udword nb_objects, const IceMaths::AABB** boxes); 72 | bool UpdateObject(udword i, const IceMaths::AABB& box); 73 | 74 | void GetPairs(Pairs& pairs) const; 75 | void GetPairs(PairCallback callback, void* user_data) const; 76 | private: 77 | SAP_PairData mPairs; 78 | 79 | udword mNbObjects; 80 | SAP_Box* mBoxes; 81 | SAP_EndPoint* mList[3]; 82 | // Internal methods 83 | bool CheckListsIntegrity(); 84 | }; 85 | 86 | #endif //__OPC_SWEEPANDPRUNE_H__ 87 | -------------------------------------------------------------------------------- /opcodemesh/opcode/Ice/IceHPoint.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /** 3 | * Contains code for homogeneous points. 4 | * \file IceHPoint.cpp 5 | * \author Pierre Terdiman 6 | * \date April, 4, 2000 7 | */ 8 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | /** 12 | * Homogeneous point. 13 | * 14 | * Use it: 15 | * - for clipping in homogeneous space (standard way) 16 | * - to differentiate between points (w=1) and vectors (w=0). 17 | * - in some cases you can also use it instead of Point for padding reasons. 18 | * 19 | * \class HPoint 20 | * \author Pierre Terdiman 21 | * \version 1.0 22 | * \warning No cross-product in 4D. 23 | * \warning HPoint *= Matrix3x3 doesn't exist, the matrix is first casted to a 4x4 24 | */ 25 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 26 | 27 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 28 | // Precompiled Header 29 | #include "Stdafx.h" 30 | 31 | using namespace IceMaths; 32 | 33 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 34 | // Point Mul = HPoint * Matrix3x3; 35 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 36 | Point HPoint::operator*(const Matrix3x3& mat) const 37 | { 38 | return Point( 39 | x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0], 40 | x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1], 41 | x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] ); 42 | } 43 | 44 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 45 | // HPoint Mul = HPoint * Matrix4x4; 46 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 47 | HPoint HPoint::operator*(const Matrix4x4& mat) const 48 | { 49 | return HPoint( 50 | x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0] + w * mat.m[3][0], 51 | x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1] + w * mat.m[3][1], 52 | x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] + w * mat.m[3][2], 53 | x * mat.m[0][3] + y * mat.m[1][3] + z * mat.m[2][3] + w * mat.m[3][3]); 54 | } 55 | 56 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 57 | // HPoint *= Matrix4x4 58 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 59 | HPoint& HPoint::operator*=(const Matrix4x4& mat) 60 | { 61 | float xp = x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0] + w * mat.m[3][0]; 62 | float yp = x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1] + w * mat.m[3][1]; 63 | float zp = x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] + w * mat.m[3][2]; 64 | float wp = x * mat.m[0][3] + y * mat.m[1][3] + z * mat.m[2][3] + w * mat.m[3][3]; 65 | 66 | x = xp; y = yp; z = zp; w = wp; 67 | 68 | return *this; 69 | } 70 | 71 | -------------------------------------------------------------------------------- /opcodemesh/opcode/Ice/IceLSS.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /** 3 | * Contains code for line-swept spheres. 4 | * \file IceLSS.h 5 | * \author Pierre Terdiman 6 | * \date April, 4, 2000 7 | */ 8 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | // Include Guard 12 | #ifndef __ICELSS_H__ 13 | #define __ICELSS_H__ 14 | 15 | class ICEMATHS_API LSS : public Segment 16 | { 17 | public: 18 | //! Constructor 19 | inline_ LSS() {} 20 | //! Constructor 21 | inline_ LSS(const Segment& seg, float radius) : Segment(seg), mRadius(radius) {} 22 | //! Destructor 23 | inline_ ~LSS() {} 24 | 25 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 26 | /** 27 | * Computes an OBB surrounding the LSS. 28 | * \param box [out] the OBB 29 | */ 30 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 31 | void ComputeOBB(OBB& box); 32 | 33 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 34 | /** 35 | * Tests if a point is contained within the LSS. 36 | * \param pt [in] the point to test 37 | * \return true if inside the LSS 38 | * \warning point and LSS must be in same space 39 | */ 40 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 41 | inline_ bool Contains(const Point& pt) const { return SquareDistance(pt) <= mRadius*mRadius; } 42 | 43 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 44 | /** 45 | * Tests if a sphere is contained within the LSS. 46 | * \param sphere [in] the sphere to test 47 | * \return true if inside the LSS 48 | * \warning sphere and LSS must be in same space 49 | */ 50 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 51 | inline_ bool Contains(const Sphere& sphere) 52 | { 53 | float d = mRadius - sphere.mRadius; 54 | if(d>=0.0f) return SquareDistance(sphere.mCenter) <= d*d; 55 | else return false; 56 | } 57 | 58 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 59 | /** 60 | * Tests if an LSS is contained within the LSS. 61 | * \param lss [in] the LSS to test 62 | * \return true if inside the LSS 63 | * \warning both LSS must be in same space 64 | */ 65 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 66 | inline_ bool Contains(const LSS& lss) 67 | { 68 | // We check the LSS contains the two spheres at the start and end of the sweep 69 | return Contains(Sphere(lss.mP0, lss.mRadius)) && Contains(Sphere(lss.mP0, lss.mRadius)); 70 | } 71 | 72 | float mRadius; //!< Sphere radius 73 | }; 74 | 75 | #endif // __ICELSS_H__ 76 | -------------------------------------------------------------------------------- /demo_KinectSimulator.m: -------------------------------------------------------------------------------- 1 | clear all 2 | close all 3 | 4 | % Add opcodemesh folders 5 | folder_path = pwd; 6 | path_opcodemesh = [folder_path '\opcodemesh']; 7 | if isempty(strfind(path,path_opcodemesh)) 8 | disp('Adding opcodemesh path...\n') 9 | addpath(genpath(path_opcodemesh)) 10 | end 11 | 12 | %% DEMO FLAT WALLS BETWEEN DEFAULT MIN AND MAX DEPTHS ===================== 13 | testMinDepth = 1000; % mm 14 | testMaxDepth = 3000; % mm 15 | 16 | % Set parameters of wall CAD model 17 | vertex_wall = [2e4 2e4 -2e4 -2e4;... 18 | 7e3 -7e3 7e3 -7e3;... 19 | 0 0 0 0]; 20 | face_wall = [1 1;... 21 | 2 3;... 22 | 4 4]; 23 | norm_wall = [0 0;... 24 | 0 0;... 25 | -1 -1]; 26 | 27 | vertex_wall(3,:) = testMinDepth*ones(1,4); 28 | [~,~,~] = KinectSimulator_IR(vertex_wall,face_wall,norm_wall); 29 | DpthImg = KinectSimulator_Depth(vertex_wall,face_wall,norm_wall); 30 | figure, imshow(DpthImg,[min(DpthImg(:)) max(DpthImg(:))]) 31 | title('Noisy depth image of flat wall at 1000 mm') 32 | 33 | vertex_wall(3,:) = testMaxDepth*ones(1,4); 34 | [~,~,~] = KinectSimulator_IR(vertex_wall,face_wall,norm_wall); 35 | DpthImg = KinectSimulator_Depth(vertex_wall,face_wall,norm_wall); 36 | figure, imshow(DpthImg,[min(DpthImg(:)) max(DpthImg(:))]) 37 | title('Noisy depth image of flat wall at 3000 mm') 38 | 39 | %% DEMO TILTED WALL ======================================================= 40 | tilt_Angle = 60; % deg 41 | tilt_Center = 1000; % mm 42 | tilt_X = -tilt_Center/tand(tilt_Angle); 43 | tilt_Z = tilt_Center + 1e5*tand(tilt_Angle); 44 | vertex_tilt = [1e5 1e5 tilt_X tilt_X;... 45 | 1e5 -1e5 1e5 -1e5;... 46 | tilt_Z tilt_Z 0 0]; 47 | face_tilt = [1 1;... 48 | 2 3;... 49 | 4 4]; 50 | norm_tilt = [sind(tilt_Angle) sind(tilt_Angle);... 51 | 0 0;... 52 | -cosd(tilt_Angle) -cosd(tilt_Angle)]; 53 | 54 | DpthImg = KinectSimulator_Depth(vertex_tilt,face_tilt,norm_tilt,... 55 | 'default','default','max','imgrng',[400 4000],'displayIR','on'); 56 | figure, imshow(DpthImg,[min(DpthImg(:)) max(DpthImg(:))]) 57 | title('Noisy depth image of 60 degree tilted wall, center depth at 1000 mm') 58 | 59 | %% DEMO BOX GRID ========================================================== 60 | load('example_CAD\BoxGrid.mat') 61 | 62 | box_width = 96; % mm 63 | box_depth = 54; % mm 64 | wallDist = 854; % mm 65 | 66 | % Scale size of box and shift grid to further depth 67 | vertex_grid = vertex; 68 | vertex_grid(1:2,:) = vertex_grid(1:2,:).*box_width; 69 | vertex_grid(3,:) = vertex_grid(3,:).*box_depth + wallDist-box_depth; 70 | face_grid = face; 71 | norm_grid = normalf; 72 | GridRng = [min(vertex_grid(3,:)) max(vertex_grid(3,:))]; 73 | 74 | DpthImg = KinectSimulator_Depth(vertex_grid,face_grid,norm_grid,... 75 | 'simple','default',wallDist,'imgrng',GridRng,'quant11','off',... 76 | 'quant10','off','displayIR','on'); 77 | figure, imshow(DpthImg,[min(DpthImg(:)) max(DpthImg(:))]) 78 | title('Noisy depth image of box grid in front of flat wall') 79 | 80 | %% DEMO TEAPOT ============================================================ 81 | load('example_CAD\Teapot.mat') 82 | 83 | % Shift CAD model to further depth 84 | vertex_teapot = vertex; 85 | vertex_teapot(3,:) = vertex_teapot(3,:) + 600; 86 | face_teapot = face; 87 | norm_teapot = normalf; 88 | 89 | DpthImg = KinectSimulator_Depth(vertex_teapot,face_teapot,norm_teapot,... 90 | 'default','default','max','imgrng',[400 4000],... 91 | 'window',[7 9],'displayIR','on'); 92 | figure, imshow(DpthImg,[0 1500]) 93 | title('Noisy depth image of teapot in front of flat wall') 94 | 95 | %% DEMO XBOX CONTROLLER =================================================== 96 | load('example_CAD\XboxController.mat') 97 | 98 | % Shift CAD model to further depth 99 | vertex_xbox = vertex; 100 | vertex_xbox(3,:) = vertex_xbox(3,:) + 300; 101 | face_xbox = face; 102 | norm_xbox = normalf; 103 | 104 | DpthImg = KinectSimulator_Depth(vertex_xbox,face_xbox,norm_xbox,... 105 | 'simple','default',[],'imgrng',[204 4000],'subray',[5 9]); 106 | figure, imshow(DpthImg,[170 320]) 107 | title('Noisy depth image of xbox controller in front of nothing') -------------------------------------------------------------------------------- /opcodemesh/opcode/Ice/IcePreprocessor.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /** 3 | * Contains preprocessor stuff. This should be the first included header. 4 | * \file IcePreprocessor.h 5 | * \author Pierre Terdiman 6 | * \date April, 4, 2000 7 | */ 8 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | // Include Guard 12 | #ifndef __ICEPREPROCESSOR_H__ 13 | #define __ICEPREPROCESSOR_H__ 14 | 15 | // Check platform 16 | #if defined( _WIN32 ) || defined( WIN32 ) 17 | // #pragma message("Compiling on Windows...") 18 | #define PLATFORM_WINDOWS 19 | #else 20 | // don't issue pragmas on unknown platforms 21 | // #pragma message("Compiling on unknown platform...") 22 | #endif 23 | 24 | // Check compiler 25 | #if defined(_MSC_VER) 26 | // #pragma message("Compiling with VC++...") 27 | #define COMPILER_VISUAL_CPP 28 | 29 | // disable annoying warnings 30 | #pragma warning (disable : 4267) // data type conversion: size_t to BOOL, size_t to udword, etc) 31 | 32 | #else 33 | // don't issue pragmas on unknown platforms 34 | // #pragma message("Compiling with unknown compiler...") 35 | #endif 36 | 37 | // Check compiler options. If this file is included in user-apps, this 38 | // shouldn't be needed, so that they can use what they like best. 39 | #ifndef ICE_DONT_CHECK_COMPILER_OPTIONS 40 | #ifdef COMPILER_VISUAL_CPP 41 | #if defined(_CHAR_UNSIGNED) 42 | #endif 43 | 44 | #if defined(_CPPRTTI) 45 | #error Please disable RTTI... 46 | #endif 47 | 48 | #if defined(_CPPUNWIND) 49 | #error Please disable exceptions... 50 | #endif 51 | 52 | #if defined(_MT) 53 | // Multithreading 54 | #endif 55 | #endif 56 | #endif 57 | 58 | // Check debug mode 59 | #ifdef DEBUG // May be defined instead of _DEBUG. Let's fix it. 60 | #ifndef _DEBUG 61 | #define _DEBUG 62 | #endif 63 | #endif 64 | 65 | #ifdef _DEBUG 66 | // Here you may define items for debug builds 67 | #endif 68 | 69 | #ifndef THIS_FILE 70 | #define THIS_FILE __FILE__ 71 | #endif 72 | 73 | // #ifndef ICE_NO_DLL 74 | // #ifdef ICECORE_EXPORTS 75 | // #define ICECORE_API __declspec(dllexport) 76 | // #else 77 | // #define ICECORE_API __declspec(dllimport) 78 | // #endif 79 | // #else 80 | // #define ICECORE_API 81 | // #endif 82 | #define ICECORE_API 83 | 84 | // Don't override new/delete 85 | // #define DEFAULT_NEWDELETE 86 | #define DONT_TRACK_MEMORY_LEAKS 87 | 88 | #define FUNCTION extern "C" 89 | 90 | // Cosmetic stuff [mainly useful with multiple inheritance] 91 | #define override(base_class) virtual 92 | 93 | // Our own inline keyword, so that: 94 | // - we can switch to __forceinline to check it's really better or not 95 | // - we can remove __forceinline if the compiler doesn't support it 96 | // #define inline_ __forceinline 97 | // #define inline_ inline 98 | 99 | // Contributed by Bruce Mitchener 100 | #if defined(COMPILER_VISUAL_CPP) 101 | #define inline_ __forceinline 102 | // #define inline_ inline 103 | #elif defined(__GNUC__) && __GNUC__ < 3 104 | #define inline_ inline 105 | #elif defined(__GNUC__) 106 | #define inline_ inline __attribute__ ((always_inline)) 107 | #else 108 | #define inline_ inline 109 | #endif 110 | 111 | // Down the hatch 112 | #ifdef _MSC_VER 113 | #pragma inline_depth( 255 ) 114 | #endif 115 | 116 | #ifdef COMPILER_VISUAL_CPP 117 | #pragma intrinsic(memcmp) 118 | #pragma intrinsic(memcpy) 119 | #pragma intrinsic(memset) 120 | #pragma intrinsic(strcat) 121 | #pragma intrinsic(strcmp) 122 | #pragma intrinsic(strcpy) 123 | #pragma intrinsic(strlen) 124 | #pragma intrinsic(abs) 125 | #pragma intrinsic(labs) 126 | #endif 127 | 128 | // ANSI compliance 129 | #ifdef _DEBUG 130 | // Remove painful warning in debug 131 | inline_ bool __False__(){ return false; } 132 | #define for if(__False__()){} else for 133 | #else 134 | #define for if(0){} else for 135 | #endif 136 | 137 | #endif // __ICEPREPROCESSOR_H__ 138 | -------------------------------------------------------------------------------- /opcodemesh/opcode/Ice/IceMemoryMacros.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /** 3 | * Contains all memory macros. 4 | * \file IceMemoryMacros.h 5 | * \author Pierre Terdiman 6 | * \date April, 4, 2000 7 | */ 8 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | // Include Guard 12 | #ifndef __ICEMEMORYMACROS_H__ 13 | #define __ICEMEMORYMACROS_H__ 14 | 15 | #undef ZeroMemory 16 | #undef CopyMemory 17 | #undef MoveMemory 18 | #undef FillMemory 19 | 20 | //! Clears a buffer. 21 | //! \param addr [in] buffer address 22 | //! \param size [in] buffer length 23 | //! \see FillMemory 24 | //! \see StoreDwords 25 | //! \see CopyMemory 26 | //! \see MoveMemory 27 | inline_ void ZeroMemory(void* addr, udword size) { memset(addr, 0, size); } 28 | 29 | //! Fills a buffer with a given byte. 30 | //! \param addr [in] buffer address 31 | //! \param size [in] buffer length 32 | //! \param val [in] the byte value 33 | //! \see StoreDwords 34 | //! \see ZeroMemory 35 | //! \see CopyMemory 36 | //! \see MoveMemory 37 | inline_ void FillMemory(void* dest, udword size, ubyte val) { memset(dest, val, size); } 38 | 39 | //! Fills a buffer with a given dword. 40 | //! \param addr [in] buffer address 41 | //! \param nb [in] number of dwords to write 42 | //! \param value [in] the dword value 43 | //! \see FillMemory 44 | //! \see ZeroMemory 45 | //! \see CopyMemory 46 | //! \see MoveMemory 47 | //! \warning writes nb*4 bytes ! 48 | inline_ void StoreDwords(udword* dest, udword nb, udword value) 49 | { 50 | // The asm code below **SHOULD** be equivalent to one of those C versions 51 | // or the other if your compiled is good: (checked on VC++ 6.0) 52 | // 53 | // 1) while(nb--) *dest++ = value; 54 | // 55 | // 2) for(udword i=0;iRelease(); (x) = null; } //!< Safe D3D-style release 98 | #define SAFE_DESTRUCT(x) if (x) { (x)->SelfDestruct(); (x) = null; } //!< Safe ICE-style release 99 | 100 | #ifdef __ICEERROR_H__ 101 | #define CHECKALLOC(x) if(!x) return SetIceError("Out of memory.", EC_OUT_OF_MEMORY); //!< Standard alloc checking. HANDLE WITH CARE. 102 | #else 103 | #define CHECKALLOC(x) if(!x) return false; 104 | #endif 105 | 106 | //! Standard allocation cycle 107 | #define SAFE_ALLOC(ptr, type, count) DELETEARRAY(ptr); ptr = new type[count]; CHECKALLOC(ptr); 108 | 109 | #endif // __ICEMEMORYMACROS_H__ 110 | -------------------------------------------------------------------------------- /opcodemesh/opcode/OPC_AABBCollider.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /* 3 | * OPCODE - Optimized Collision Detection 4 | * Copyright (C) 2001 Pierre Terdiman 5 | * Homepage: http://www.codercorner.com/Opcode.htm 6 | */ 7 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 10 | /** 11 | * Contains code for an AABB collider. 12 | * \file OPC_AABBCollider.h 13 | * \author Pierre Terdiman 14 | * \date January, 1st, 2002 15 | */ 16 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | // Include Guard 20 | #ifndef __OPC_AABBCOLLIDER_H__ 21 | #define __OPC_AABBCOLLIDER_H__ 22 | 23 | struct OPCODE_API AABBCache : VolumeCache 24 | { 25 | AABBCache() : FatCoeff(1.1f) 26 | { 27 | FatBox.mCenter.Zero(); 28 | FatBox.mExtents.Zero(); 29 | } 30 | 31 | // Cached faces signature 32 | CollisionAABB FatBox; //!< Box used when performing the query resulting in cached faces 33 | // User settings 34 | float FatCoeff; //!< mRadius2 multiplier used to create a fat sphere 35 | }; 36 | 37 | class OPCODE_API AABBCollider : public VolumeCollider 38 | { 39 | public: 40 | // Constructor / Destructor 41 | AABBCollider(); 42 | virtual ~AABBCollider(); 43 | 44 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 45 | /** 46 | * Generic collision query for generic OPCODE models. After the call, access the results: 47 | * - with GetContactStatus() 48 | * - with GetNbTouchedPrimitives() 49 | * - with GetTouchedPrimitives() 50 | * 51 | * \param cache [in/out] a box cache 52 | * \param box [in] collision AABB in world space 53 | * \param model [in] Opcode model to collide with 54 | * \return true if success 55 | */ 56 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 57 | bool Collide(AABBCache& cache, const CollisionAABB& box, const Model& model); 58 | // 59 | bool Collide(AABBCache& cache, const CollisionAABB& box, const AABBTree* tree); 60 | protected: 61 | CollisionAABB mBox; //!< Query box in (center, extents) form 62 | IceMaths::Point mMin; //!< Query box min point 63 | IceMaths::Point mMax; //!< Query box max point 64 | // Leaf description 65 | IceMaths::Point mLeafVerts[3]; //!< Triangle vertices 66 | // Internal methods 67 | void _Collide(const AABBCollisionNode* node); 68 | void _Collide(const AABBNoLeafNode* node); 69 | void _Collide(const AABBQuantizedNode* node); 70 | void _Collide(const AABBQuantizedNoLeafNode* node); 71 | void _Collide(const AABBTreeNode* node); 72 | void _CollideNoPrimitiveTest(const AABBCollisionNode* node); 73 | void _CollideNoPrimitiveTest(const AABBNoLeafNode* node); 74 | void _CollideNoPrimitiveTest(const AABBQuantizedNode* node); 75 | void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node); 76 | // Overlap tests 77 | inline_ BOOL AABBContainsBox(const IceMaths::Point& bc, const IceMaths::Point& be); 78 | inline_ BOOL AABBAABBOverlap(const IceMaths::Point& b, const IceMaths::Point& Pb); 79 | inline_ BOOL TriBoxOverlap(); 80 | // Init methods 81 | BOOL InitQuery(AABBCache& cache, const CollisionAABB& box); 82 | }; 83 | 84 | class OPCODE_API HybridAABBCollider : public AABBCollider 85 | { 86 | public: 87 | // Constructor / Destructor 88 | HybridAABBCollider(); 89 | virtual ~HybridAABBCollider(); 90 | 91 | bool Collide(AABBCache& cache, const CollisionAABB& box, const HybridModel& model); 92 | protected: 93 | Container mTouchedBoxes; 94 | }; 95 | 96 | #endif // __OPC_AABBCOLLIDER_H__ 97 | -------------------------------------------------------------------------------- /opcodemesh/opcode/Opcode.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /* 3 | * OPCODE - Optimized Collision Detection 4 | * Copyright (C) 2001 Pierre Terdiman 5 | * Homepage: http://www.codercorner.com/Opcode.htm 6 | */ 7 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 10 | /** 11 | * Main file for Opcode.dll. 12 | * \file Opcode.h 13 | * \author Pierre Terdiman 14 | * \date March, 20, 2001 15 | */ 16 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | // Include Guard 20 | #ifndef __OPCODE_H__ 21 | #define __OPCODE_H__ 22 | 23 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 24 | // Things to help us compile on non-windows platforms 25 | 26 | #if defined(__APPLE__) || defined(__MACOSX__) 27 | #if __APPLE_CC__ < 1495 28 | #define sqrtf sqrt 29 | #define sinf sin 30 | #define cosf cos 31 | #define acosf acos 32 | #define asinf sinf 33 | #endif 34 | #endif 35 | 36 | #ifndef _MSC_VER 37 | 38 | #define __int64 long long int 39 | #define __stdcall /* */ 40 | 41 | #endif 42 | 43 | 44 | // /* No stupid autolinking */ 45 | // #define BAN_OPCODE_AUTOLINK 46 | // 47 | // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 48 | // // Compilation messages 49 | // #ifdef _MSC_VER 50 | // #if defined(OPCODE_EXPORTS) 51 | // #pragma message("Compiling OPCODE") 52 | // #elif !defined(OPCODE_EXPORTS) 53 | // #pragma message("Using OPCODE") 54 | // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 55 | // // Automatic linking 56 | // #ifndef BAN_OPCODE_AUTOLINK 57 | // #ifdef _DEBUG 58 | // #pragma comment(lib, "Opcode_D.lib") 59 | // #else 60 | // #pragma comment(lib, "Opcode.lib") 61 | // #endif 62 | // #endif 63 | // #endif 64 | // #endif 65 | 66 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 67 | 68 | // // Preprocessor 69 | // #ifdef _MSC_VER 70 | // #ifndef ICE_NO_DLL 71 | // #ifdef OPCODE_EXPORTS 72 | // #define OPCODE_API __declspec(dllexport) 73 | // #else 74 | // #define OPCODE_API __declspec(dllimport) 75 | // #endif 76 | // #else 77 | // #define OPCODE_API 78 | // #endif 79 | // #else 80 | // #define OPCODE_API 81 | // #endif 82 | #define OPCODE_API 83 | //#define OPCODE_API __declspec(dllimport) 84 | 85 | #include "OPC_IceHook.h" 86 | 87 | namespace Opcode 88 | { 89 | // Bulk-of-the-work 90 | #include "OPC_Settings.h" 91 | #include "OPC_Common.h" 92 | #include "OPC_MeshInterface.h" 93 | // Builders 94 | #include "OPC_TreeBuilders.h" 95 | // Trees 96 | #include "OPC_AABBTree.h" 97 | #include "OPC_OptimizedTree.h" 98 | // Models 99 | #include "OPC_BaseModel.h" 100 | #include "OPC_Model.h" 101 | #include "OPC_HybridModel.h" 102 | // Colliders 103 | #include "OPC_Collider.h" 104 | #include "OPC_VolumeCollider.h" 105 | #include "OPC_TreeCollider.h" 106 | #include "OPC_RayCollider.h" 107 | #include "OPC_SphereCollider.h" 108 | #include "OPC_OBBCollider.h" 109 | #include "OPC_AABBCollider.h" 110 | #include "OPC_LSSCollider.h" 111 | #include "OPC_PlanesCollider.h" 112 | // Usages 113 | #include "OPC_Picking.h" 114 | // Sweep-and-prune 115 | #include "OPC_BoxPruning.h" 116 | #include "OPC_SweepAndPrune.h" 117 | 118 | FUNCTION OPCODE_API bool InitOpcode(); 119 | FUNCTION OPCODE_API bool CloseOpcode(); 120 | } 121 | 122 | #endif // __OPCODE_H__ 123 | -------------------------------------------------------------------------------- /opcodemesh/opcode/OPC_RayAABBOverlap.h: -------------------------------------------------------------------------------- 1 | // Opcode 1.1: ray-AABB overlap tests based on Woo's code 2 | // Opcode 1.2: ray-AABB overlap tests based on the separating axis theorem 3 | // Opcode 1.3.2: configuration. Apply or do not apply the model's scale?? 4 | // 5 | // The point of intersection is not computed anymore. The distance to impact is not needed anymore 6 | // since we now have two different queries for segments or rays. 7 | 8 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | /** 10 | * Computes a segment-AABB overlap test using the separating axis theorem. Segment is cached within the class. 11 | * \param center [in] AABB center 12 | * \param extents [in] AABB extents 13 | * \return true on overlap 14 | */ 15 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 16 | 17 | /// What we do here is just a simple hack over the method declaration in order do keep the 18 | /// intersection code easier to maintain. This code will be moved to RayCollider macros sooner or later 19 | 20 | #if defined(OPC_RAYCOLLIDER_SCALE_BEFORE_OVERLAP) 21 | inline_ BOOL RayCollider::SegmentAABBOverlap(const Point& center_, const Point& extents_) 22 | { 23 | // Applies model's local scale 24 | const IceMaths::Point center = center_ * mLocalScale; 25 | const IceMaths::Point extents = extents_* mLocalScale; 26 | 27 | #else 28 | inline_ BOOL RayCollider::SegmentAABBOverlap(const Point& center, const Point& extents) 29 | { 30 | #endif 31 | // Stats 32 | mNbRayBVTests++; 33 | 34 | // Pierre's code: looks like an AABB-AABB test 35 | float Dx = mData2.x - center.x; if(fabsf(Dx) > extents.x + mFDir.x) return FALSE; 36 | float Dy = mData2.y - center.y; if(fabsf(Dy) > extents.y + mFDir.y) return FALSE; 37 | float Dz = mData2.z - center.z; if(fabsf(Dz) > extents.z + mFDir.z) return FALSE; 38 | 39 | //float f; 40 | register float f = mData.y * Dz - mData.z * Dy; if(fabsf(f) > extents.y*mFDir.z + extents.z*mFDir.y) return FALSE; 41 | f = mData.z * Dx - mData.x * Dz; if(fabsf(f) > extents.x*mFDir.z + extents.z*mFDir.x) return FALSE; 42 | f = mData.x * Dy - mData.y * Dx; if(fabsf(f) > extents.x*mFDir.y + extents.y*mFDir.x) return FALSE; 43 | 44 | return TRUE; 45 | } 46 | 47 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 48 | /** 49 | * Computes a ray-AABB overlap test using the separating axis theorem. Ray is cached within the class. 50 | * \param center [in] AABB center 51 | * \param extents [in] AABB extents 52 | * \return true on overlap 53 | */ 54 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 55 | 56 | #if defined(OPC_RAYCOLLIDER_SCALE_BEFORE_OVERLAP) 57 | inline_ BOOL RayCollider::RayAABBOverlap(const Point& center_, const Point& extents_) 58 | { 59 | const Point center = center_*mLocalScale; 60 | const Point extents = extents_*mLocalScale; 61 | #else 62 | inline_ BOOL RayCollider::RayAABBOverlap(const Point& center, const Point& extents) 63 | { 64 | #endif 65 | 66 | // Stats 67 | mNbRayBVTests++; 68 | 69 | // PIERRE'S CODE: 70 | // float Dx = mOrigin.x - center.x; if(fabsf(Dx) > extents.x && Dx*mDir.x>=0.0f) return FALSE; 71 | // float Dy = mOrigin.y - center.y; if(fabsf(Dy) > extents.y && Dy*mDir.y>=0.0f) return FALSE; 72 | // float Dz = mOrigin.z - center.z; if(fabsf(Dz) > extents.z && Dz*mDir.z>=0.0f) return FALSE; 73 | 74 | float Dx = mOrigin.x - center.x; if(GREATER(Dx, extents.x) && Dx*mDir.x>=0.0f) return FALSE; 75 | float Dy = mOrigin.y - center.y; if(GREATER(Dy, extents.y) && Dy*mDir.y>=0.0f) return FALSE; 76 | float Dz = mOrigin.z - center.z; if(GREATER(Dz, extents.z) && Dz*mDir.z>=0.0f) return FALSE; 77 | 78 | // float Dx = mOrigin.x - center.x; if(GREATER(Dx, extents.x) && ((SIR(Dx)-1)^SIR(mDir.x))>=0.0f) return FALSE; 79 | // float Dy = mOrigin.y - center.y; if(GREATER(Dy, extents.y) && ((SIR(Dy)-1)^SIR(mDir.y))>=0.0f) return FALSE; 80 | // float Dz = mOrigin.z - center.z; if(GREATER(Dz, extents.z) && ((SIR(Dz)-1)^SIR(mDir.z))>=0.0f) return FALSE; 81 | 82 | //float f; 83 | register float f = mDir.y * Dz - mDir.z * Dy; if(fabsf(f) > extents.y*mFDir.z + extents.z*mFDir.y) return FALSE; 84 | f = mDir.z * Dx - mDir.x * Dz; if(fabsf(f) > extents.x*mFDir.z + extents.z*mFDir.x) return FALSE; 85 | f = mDir.x * Dy - mDir.y * Dx; if(fabsf(f) > extents.x*mFDir.y + extents.y*mFDir.x) return FALSE; 86 | 87 | return TRUE; 88 | } 89 | -------------------------------------------------------------------------------- /opcodemesh/opcode/Ice/IceRay.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /** 3 | * Contains code for rays. 4 | * \file IceRay.h 5 | * \author Pierre Terdiman 6 | * \date April, 4, 2000 7 | */ 8 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | // Include Guard 12 | #ifndef __ICERAY_H__ 13 | #define __ICERAY_H__ 14 | 15 | class ICEMATHS_API Ray 16 | { 17 | public: 18 | //! Constructor 19 | inline_ Ray() {} 20 | //! Constructor 21 | inline_ Ray(const Point& orig, const Point& dir) : mOrig(orig), mDir(dir) {} 22 | //! Copy constructor 23 | inline_ Ray(const Ray& ray) : mOrig(ray.mOrig), mDir(ray.mDir) {} 24 | //! Destructor 25 | inline_ ~Ray() {} 26 | 27 | float SquareDistance(const Point& point, float* t=null) const; 28 | inline_ float Distance(const Point& point, float* t=null) const { return sqrtf(SquareDistance(point, t)); } 29 | 30 | Point mOrig; //!< Ray origin 31 | Point mDir; //!< Normalized direction 32 | }; 33 | 34 | inline_ void ComputeReflexionVector(Point& reflected, const Point& incoming_dir, const Point& outward_normal) 35 | { 36 | reflected = incoming_dir - outward_normal * 2.0f * (incoming_dir|outward_normal); 37 | } 38 | 39 | inline_ void ComputeReflexionVector(Point& reflected, const Point& source, const Point& impact, const Point& normal) 40 | { 41 | Point V = impact - source; 42 | reflected = V - normal * 2.0f * (V|normal); 43 | } 44 | 45 | inline_ void DecomposeVector(Point& normal_compo, Point& tangent_compo, const Point& outward_dir, const Point& outward_normal) 46 | { 47 | normal_compo = outward_normal * (outward_dir|outward_normal); 48 | tangent_compo = outward_dir - normal_compo; 49 | } 50 | 51 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 52 | /** 53 | * Transforms a direction vector from world space to local space 54 | * \param local_dir [out] direction vector in local space 55 | * \param world_dir [in] direction vector in world space 56 | * \param world [in] world transform 57 | */ 58 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 59 | inline_ void ComputeLocalDirection(Point& local_dir, const Point& world_dir, const Matrix4x4& world) 60 | { 61 | // Get world direction back in local space 62 | // Matrix3x3 InvWorld = world; 63 | // local_dir = InvWorld * world_dir; 64 | local_dir = Matrix3x3(world) * world_dir; 65 | } 66 | 67 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 68 | /** 69 | * Transforms a position vector from world space to local space 70 | * \param local_pt [out] position vector in local space 71 | * \param world_pt [in] position vector in world space 72 | * \param world [in] world transform 73 | */ 74 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 75 | inline_ void ComputeLocalPoint(Point& local_pt, const Point& world_pt, const Matrix4x4& world) 76 | { 77 | // Get world vertex back in local space 78 | Matrix4x4 InvWorld = world; 79 | InvWorld.Invert(); 80 | local_pt = world_pt * InvWorld; 81 | } 82 | 83 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 84 | /** 85 | * Transforms a ray from world space to local space 86 | * \param local_ray [out] ray in local space 87 | * \param world_ray [in] ray in world space 88 | * \param world [in] world transform 89 | */ 90 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 91 | inline_ void ComputeLocalRay(Ray& local_ray, const Ray& world_ray, const Matrix4x4& world) 92 | { 93 | // Get world ray back in local space 94 | ComputeLocalDirection(local_ray.mDir, world_ray.mDir, world); 95 | ComputeLocalPoint(local_ray.mOrig, world_ray.mOrig, world); 96 | } 97 | 98 | #endif // __ICERAY_H__ 99 | -------------------------------------------------------------------------------- /opcodemesh/opcode/OPC_VolumeCollider.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /* 3 | * OPCODE - Optimized Collision Detection 4 | * Copyright (C) 2001 Pierre Terdiman 5 | * Homepage: http://www.codercorner.com/Opcode.htm 6 | */ 7 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 10 | /** 11 | * Contains base volume collider class. 12 | * \file OPC_VolumeCollider.cpp 13 | * \author Pierre Terdiman 14 | * \date June, 2, 2001 15 | */ 16 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | /** 20 | * Contains the abstract class for volume colliders. 21 | * 22 | * \class VolumeCollider 23 | * \author Pierre Terdiman 24 | * \version 1.3 25 | * \date June, 2, 2001 26 | */ 27 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 28 | 29 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 30 | // Precompiled Header 31 | #include "Stdafx.h" 32 | 33 | using namespace Opcode; 34 | 35 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 36 | /** 37 | * Constructor. 38 | */ 39 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 40 | VolumeCollider::VolumeCollider() : 41 | mTouchedPrimitives (null), 42 | mLocalScale (1.0,1.0,1.0), 43 | mNbVolumeBVTests (0), 44 | mNbVolumePrimTests (0) 45 | { 46 | } 47 | 48 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 49 | /** 50 | * Destructor. 51 | */ 52 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 53 | VolumeCollider::~VolumeCollider() 54 | { 55 | mTouchedPrimitives = null; 56 | } 57 | 58 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 59 | /** 60 | * Validates current settings. You should call this method after all the settings / callbacks have been defined for a collider. 61 | * \return null if everything is ok, else a string describing the problem 62 | */ 63 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 64 | const char* VolumeCollider::ValidateSettings() 65 | { 66 | return null; 67 | } 68 | 69 | // Pretty dumb way to dump - to do better - one day... 70 | 71 | #define IMPLEMENT_NOLEAFDUMP(type) \ 72 | void VolumeCollider::_Dump(const type* node) \ 73 | { \ 74 | if(node->HasPosLeaf()) mTouchedPrimitives->Add(node->GetPosPrimitive()); \ 75 | else _Dump(node->GetPos()); \ 76 | \ 77 | if(ContactFound()) return; \ 78 | \ 79 | if(node->HasNegLeaf()) mTouchedPrimitives->Add(node->GetNegPrimitive()); \ 80 | else _Dump(node->GetNeg()); \ 81 | } 82 | 83 | #define IMPLEMENT_LEAFDUMP(type) \ 84 | void VolumeCollider::_Dump(const type* node) \ 85 | { \ 86 | if(node->IsLeaf()) \ 87 | { \ 88 | mTouchedPrimitives->Add(node->GetPrimitive()); \ 89 | } \ 90 | else \ 91 | { \ 92 | _Dump(node->GetPos()); \ 93 | \ 94 | if(ContactFound()) return; \ 95 | \ 96 | _Dump(node->GetNeg()); \ 97 | } \ 98 | } 99 | 100 | IMPLEMENT_NOLEAFDUMP(AABBNoLeafNode) 101 | IMPLEMENT_NOLEAFDUMP(AABBQuantizedNoLeafNode) 102 | 103 | IMPLEMENT_LEAFDUMP(AABBCollisionNode) 104 | IMPLEMENT_LEAFDUMP(AABBQuantizedNode) 105 | -------------------------------------------------------------------------------- /opcodemesh/opcode/OPC_Common.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /* 3 | * OPCODE - Optimized Collision Detection 4 | * Copyright (C) 2001 Pierre Terdiman 5 | * Homepage: http://www.codercorner.com/Opcode.htm 6 | */ 7 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 10 | /** 11 | * Contains common classes & defs used in OPCODE. 12 | * \file OPC_Common.h 13 | * \author Pierre Terdiman 14 | * \date March, 20, 2001 15 | */ 16 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | // Include Guard 20 | #ifndef __OPC_COMMON_H__ 21 | #define __OPC_COMMON_H__ 22 | 23 | // [GOTTFRIED]: Just a small change for readability. 24 | #ifdef OPC_CPU_COMPARE 25 | #define GREATER(x, y) AIR(x) > IR(y) 26 | #else 27 | #define GREATER(x, y) fabsf(x) > (y) 28 | #endif 29 | 30 | class OPCODE_API CollisionAABB 31 | { 32 | public: 33 | //! Constructor 34 | inline_ CollisionAABB() {} 35 | //! Constructor 36 | inline_ CollisionAABB(const IceMaths::AABB& b) { b.GetCenter(mCenter); b.GetExtents(mExtents); } 37 | //! Destructor 38 | inline_ ~CollisionAABB() {} 39 | 40 | //! Get min point of the box 41 | inline_ void GetMin(IceMaths::Point& min) const { min = mCenter - mExtents; } 42 | //! Get max point of the box 43 | inline_ void GetMax(IceMaths::Point& max) const { max = mCenter + mExtents; } 44 | 45 | //! Get component of the box's min point along a given axis 46 | inline_ float GetMin(udword axis) const { return mCenter[axis] - mExtents[axis]; } 47 | //! Get component of the box's max point along a given axis 48 | inline_ float GetMax(udword axis) const { return mCenter[axis] + mExtents[axis]; } 49 | 50 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 51 | /** 52 | * Setups an AABB from min & max vectors. 53 | * \param min [in] the min point 54 | * \param max [in] the max point 55 | */ 56 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 57 | inline_ void SetMinMax(const IceMaths::Point& min, const IceMaths::Point& max) { mCenter = (max + min)*0.5f; mExtents = (max - min)*0.5f; } 58 | 59 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 60 | /** 61 | * Checks a box is inside another box. 62 | * \param box [in] the other box 63 | * \return true if current box is inside input box 64 | */ 65 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 66 | inline_ BOOL IsInside(const CollisionAABB& box) const 67 | { 68 | if(box.GetMin(0)>GetMin(0)) return FALSE; 69 | if(box.GetMin(1)>GetMin(1)) return FALSE; 70 | if(box.GetMin(2)>GetMin(2)) return FALSE; 71 | if(box.GetMax(0)=fA00) { /*u = 1.0f;*/ SqrDist = fA00+2.0f*fB0+fC; } 58 | else { u = -fB0/fA00; SqrDist = fB0*u+fC; } 59 | } 60 | else 61 | { 62 | // u = 0.0f; 63 | if(fB1>=0.0f) { /*v = 0.0f;*/ SqrDist = fC; } 64 | else if(-fB1>=fA11) { /*v = 1.0f;*/ SqrDist = fA11+2.0f*fB1+fC; } 65 | else { v = -fB1/fA11; SqrDist = fB1*v+fC; } 66 | } 67 | } 68 | else // region 3 69 | { 70 | // u = 0.0f; 71 | if(fB1>=0.0f) { /*v = 0.0f;*/ SqrDist = fC; } 72 | else if(-fB1>=fA11) { /*v = 1.0f;*/ SqrDist = fA11+2.0f*fB1+fC; } 73 | else { v = -fB1/fA11; SqrDist = fB1*v+fC; } 74 | } 75 | } 76 | else if(v < 0.0f) // region 5 77 | { 78 | // v = 0.0f; 79 | if(fB0>=0.0f) { /*u = 0.0f;*/ SqrDist = fC; } 80 | else if(-fB0>=fA00) { /*u = 1.0f;*/ SqrDist = fA00+2.0f*fB0+fC; } 81 | else { u = -fB0/fA00; SqrDist = fB0*u+fC; } 82 | } 83 | else // region 0 84 | { 85 | // minimum at interior point 86 | if(fDet==0.0f) 87 | { 88 | // u = 0.0f; 89 | // v = 0.0f; 90 | SqrDist = MAX_FLOAT; 91 | } 92 | else 93 | { 94 | float fInvDet = 1.0f/fDet; 95 | u *= fInvDet; 96 | v *= fInvDet; 97 | SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; 98 | } 99 | } 100 | } 101 | else 102 | { 103 | float fTmp0, fTmp1, fNumer, fDenom; 104 | 105 | if(u < 0.0f) // region 2 106 | { 107 | fTmp0 = fA01 + fB0; 108 | fTmp1 = fA11 + fB1; 109 | if(fTmp1 > fTmp0) 110 | { 111 | fNumer = fTmp1 - fTmp0; 112 | fDenom = fA00-2.0f*fA01+fA11; 113 | if(fNumer >= fDenom) 114 | { 115 | // u = 1.0f; 116 | // v = 0.0f; 117 | SqrDist = fA00+2.0f*fB0+fC; 118 | } 119 | else 120 | { 121 | u = fNumer/fDenom; 122 | v = 1.0f - u; 123 | SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; 124 | } 125 | } 126 | else 127 | { 128 | // u = 0.0f; 129 | if(fTmp1 <= 0.0f) { /*v = 1.0f;*/ SqrDist = fA11+2.0f*fB1+fC; } 130 | else if(fB1 >= 0.0f) { /*v = 0.0f;*/ SqrDist = fC; } 131 | else { v = -fB1/fA11; SqrDist = fB1*v+fC; } 132 | } 133 | } 134 | else if(v < 0.0f) // region 6 135 | { 136 | fTmp0 = fA01 + fB1; 137 | fTmp1 = fA00 + fB0; 138 | if(fTmp1 > fTmp0) 139 | { 140 | fNumer = fTmp1 - fTmp0; 141 | fDenom = fA00-2.0f*fA01+fA11; 142 | if(fNumer >= fDenom) 143 | { 144 | // v = 1.0f; 145 | // u = 0.0f; 146 | SqrDist = fA11+2.0f*fB1+fC; 147 | } 148 | else 149 | { 150 | v = fNumer/fDenom; 151 | u = 1.0f - v; 152 | SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; 153 | } 154 | } 155 | else 156 | { 157 | // v = 0.0f; 158 | if(fTmp1 <= 0.0f) { /*u = 1.0f;*/ SqrDist = fA00+2.0f*fB0+fC; } 159 | else if(fB0 >= 0.0f) { /*u = 0.0f;*/ SqrDist = fC; } 160 | else { u = -fB0/fA00; SqrDist = fB0*u+fC; } 161 | } 162 | } 163 | else // region 1 164 | { 165 | fNumer = fA11 + fB1 - fA01 - fB0; 166 | if(fNumer <= 0.0f) 167 | { 168 | // u = 0.0f; 169 | // v = 1.0f; 170 | SqrDist = fA11+2.0f*fB1+fC; 171 | } 172 | else 173 | { 174 | fDenom = fA00-2.0f*fA01+fA11; 175 | if(fNumer >= fDenom) 176 | { 177 | // u = 1.0f; 178 | // v = 0.0f; 179 | SqrDist = fA00+2.0f*fB0+fC; 180 | } 181 | else 182 | { 183 | u = fNumer/fDenom; 184 | v = 1.0f - u; 185 | SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; 186 | } 187 | } 188 | } 189 | } 190 | 191 | return fabsf(SqrDist) < mRadius2; 192 | } 193 | -------------------------------------------------------------------------------- /opcodemesh/opcode/OPC_Picking.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /* 3 | * OPCODE - Optimized Collision Detection 4 | * Copyright (C) 2001 Pierre Terdiman 5 | * Homepage: http://www.codercorner.com/Opcode.htm 6 | */ 7 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 10 | /** 11 | * Contains code to perform "picking". 12 | * \file OPC_Picking.cpp 13 | * \author Pierre Terdiman 14 | * \date March, 20, 2001 15 | */ 16 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | // Precompiled Header 20 | #include "Stdafx.h" 21 | 22 | using namespace Opcode; 23 | 24 | #ifdef OPC_RAYHIT_CALLBACK 25 | 26 | /* 27 | Possible RayCollider usages: 28 | - boolean query (shadow feeler) 29 | - closest hit 30 | - all hits 31 | - number of intersection (boolean) 32 | 33 | */ 34 | 35 | bool Opcode::SetupAllHits(RayCollider& collider, CollisionFaces& contacts) 36 | { 37 | struct Local 38 | { 39 | static void AllContacts(const CollisionFace& hit, void* user_data) 40 | { 41 | CollisionFaces* CF = (CollisionFaces*)user_data; 42 | CF->AddFace(hit); 43 | } 44 | }; 45 | 46 | collider.SetFirstContact(false); 47 | collider.SetHitCallback(Local::AllContacts); 48 | collider.SetUserData(&contacts); 49 | return true; 50 | } 51 | 52 | bool Opcode::SetupClosestHit(RayCollider& collider, CollisionFace& closest_contact) 53 | { 54 | struct Local 55 | { 56 | static void ClosestContact(const CollisionFace& hit, void* user_data) 57 | { 58 | CollisionFace* CF = (CollisionFace*)user_data; 59 | if(hit.mDistancemDistance) *CF = hit; 60 | } 61 | }; 62 | 63 | collider.SetFirstContact(false); 64 | collider.SetHitCallback(Local::ClosestContact); 65 | collider.SetUserData(&closest_contact); 66 | closest_contact.mDistance = MAX_FLOAT; 67 | return true; 68 | } 69 | 70 | bool Opcode::SetupShadowFeeler(RayCollider& collider) 71 | { 72 | collider.SetFirstContact(true); 73 | collider.SetHitCallback(null); 74 | return true; 75 | } 76 | 77 | bool Opcode::SetupInOutTest(RayCollider& collider) 78 | { 79 | collider.SetFirstContact(false); 80 | collider.SetHitCallback(null); 81 | // Results with collider.GetNbIntersections() 82 | return true; 83 | } 84 | 85 | bool Opcode::Picking( 86 | CollisionFace& picked_face, 87 | const Ray& world_ray, const Model& model, const Matrix4x4* world, 88 | float min_dist, float max_dist, const Point& view_point, CullModeCallback callback, void* user_data) 89 | { 90 | struct Local 91 | { 92 | struct CullData 93 | { 94 | CollisionFace* Closest; 95 | float MinLimit; 96 | CullModeCallback Callback; 97 | void* UserData; 98 | Point ViewPoint; 99 | const MeshInterface* IMesh; 100 | }; 101 | 102 | // Called for each stabbed face 103 | static void RenderCullingCallback(const CollisionFace& hit, void* user_data) 104 | { 105 | CullData* Data = (CullData*)user_data; 106 | 107 | // Discard face if we already have a closer hit 108 | if(hit.mDistance>=Data->Closest->mDistance) return; 109 | 110 | // Discard face if hit point is smaller than min limit. This mainly happens when the face is in front 111 | // of the near clip plane (or straddles it). If we keep the face nonetheless, the user can select an 112 | // object that he may not even be able to see, which is very annoying. 113 | if(hit.mDistance<=Data->MinLimit) return; 114 | 115 | // This is the index of currently stabbed triangle. 116 | udword StabbedFaceIndex = hit.mFaceID; 117 | 118 | // We may keep it or not, depending on backface culling 119 | bool KeepIt = true; 120 | 121 | // Catch *render* cull mode for this face 122 | CullMode CM = (Data->Callback)(StabbedFaceIndex, Data->UserData); 123 | 124 | if(CM!=CULLMODE_NONE) // Don't even compute culling for double-sided triangles 125 | { 126 | // Compute backface culling for current face 127 | 128 | VertexPointers VP; 129 | Data->IMesh->GetTriangle(VP, StabbedFaceIndex); 130 | if(VP.BackfaceCulling(Data->ViewPoint)) 131 | { 132 | if(CM==CULLMODE_CW) KeepIt = false; 133 | } 134 | else 135 | { 136 | if(CM==CULLMODE_CCW) KeepIt = false; 137 | } 138 | } 139 | 140 | if(KeepIt) *Data->Closest = hit; 141 | } 142 | }; 143 | 144 | RayCollider RC; 145 | RC.SetMaxDist(max_dist); 146 | RC.SetTemporalCoherence(false); 147 | RC.SetCulling(false); // We need all faces since some of them can be double-sided 148 | RC.SetFirstContact(false); 149 | RC.SetHitCallback(Local::RenderCullingCallback); 150 | 151 | picked_face.mFaceID = INVALID_ID; 152 | picked_face.mDistance = MAX_FLOAT; 153 | picked_face.mU = 0.0f; 154 | picked_face.mV = 0.0f; 155 | 156 | Local::CullData Data; 157 | Data.Closest = &picked_face; 158 | Data.MinLimit = min_dist; 159 | Data.Callback = callback; 160 | Data.UserData = user_data; 161 | Data.ViewPoint = view_point; 162 | Data.IMesh = model.GetMeshInterface(); 163 | 164 | if(world) 165 | { 166 | // Get matrices 167 | Matrix4x4 InvWorld; 168 | InvertPRMatrix(InvWorld, *world); 169 | 170 | // Compute camera position in mesh space 171 | Data.ViewPoint *= InvWorld; 172 | } 173 | 174 | RC.SetUserData(&Data); 175 | if(RC.Collide(world_ray, model, world)) 176 | { 177 | return picked_face.mFaceID!=INVALID_ID; 178 | } 179 | return false; 180 | } 181 | 182 | #endif 183 | -------------------------------------------------------------------------------- /opcodemesh/opcode/OPC_PlanesCollider.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /* 3 | * OPCODE - Optimized Collision Detection 4 | * Copyright (C) 2001 Pierre Terdiman 5 | * Homepage: http://www.codercorner.com/Opcode.htm 6 | * 7 | * OPCODE modifications for scaled model support (and other things) 8 | * Copyright (C) 2004 Gilvan Maia (gilvan 'at' vdl.ufc.br) 9 | * Check http://www.vdl.ufc.br/gilvan/coll/opcode/index.htm for updates. 10 | * 11 | */ 12 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 13 | 14 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 15 | /** 16 | * Contains code for a planes collider. 17 | * \file OPC_PlanesCollider.h 18 | * \author Pierre Terdiman 19 | * \date January, 1st, 2002 20 | */ 21 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 22 | 23 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 24 | // Include Guard 25 | #ifndef __OPC_PLANESCOLLIDER_H__ 26 | #define __OPC_PLANESCOLLIDER_H__ 27 | 28 | struct OPCODE_API PlanesCache : VolumeCache 29 | { 30 | PlanesCache() 31 | { 32 | } 33 | }; 34 | 35 | class OPCODE_API PlanesCollider : public VolumeCollider 36 | { 37 | public: 38 | // Constructor / Destructor 39 | PlanesCollider(); 40 | virtual ~PlanesCollider(); 41 | 42 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 43 | /** 44 | * Generic collision query for generic OPCODE models. After the call, access the results: 45 | * - with GetContactStatus() 46 | * - with GetNbTouchedPrimitives() 47 | * - with GetTouchedPrimitives() 48 | * 49 | * \param cache [in/out] a planes cache 50 | * \param planes [in] list of planes in world space 51 | * \param nb_planes [in] number of planes 52 | * \param model [in] Opcode model to collide with 53 | * \param worldm [in] model's world matrix, or null 54 | * \return true if success 55 | */ 56 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 57 | bool Collide(PlanesCache& cache, const IceMaths::Plane* planes, udword nb_planes, const Model& model, const IceMaths::Matrix4x4* worldm=null); 58 | 59 | // Mutant box-with-planes collision queries 60 | inline_ bool Collide(PlanesCache& cache, const IceMaths::OBB& box, const Model& model, const IceMaths::Matrix4x4* worldb=null, const IceMaths::Matrix4x4* worldm=null) 61 | { 62 | IceMaths::Plane PL[6]; 63 | 64 | if(worldb) 65 | { 66 | // Create a new OBB in world space 67 | IceMaths::OBB WorldBox; 68 | box.Rotate(*worldb, WorldBox); 69 | // Compute planes from the sides of the box 70 | WorldBox.ComputePlanes(PL); 71 | } 72 | else 73 | { 74 | // Compute planes from the sides of the box 75 | box.ComputePlanes(PL); 76 | } 77 | 78 | // Collide with box planes 79 | return Collide(cache, PL, 6, model, worldm); 80 | } 81 | // Settings 82 | 83 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 84 | /** 85 | * Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider. 86 | * \return null if everything is ok, else a string describing the problem 87 | */ 88 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 89 | override(Collider) const char* ValidateSettings(); 90 | 91 | protected: 92 | // Planes in model space 93 | udword mNbPlanes; 94 | IceMaths::Plane* mPlanes; 95 | // Leaf description 96 | VertexPointers mVP; 97 | // Internal methods 98 | void _Collide(const AABBCollisionNode* node, udword clip_mask); 99 | void _Collide(const AABBNoLeafNode* node, udword clip_mask); 100 | void _Collide(const AABBQuantizedNode* node, udword clip_mask); 101 | void _Collide(const AABBQuantizedNoLeafNode* node, udword clip_mask); 102 | void _CollideNoPrimitiveTest(const AABBCollisionNode* node, udword clip_mask); 103 | void _CollideNoPrimitiveTest(const AABBNoLeafNode* node, udword clip_mask); 104 | void _CollideNoPrimitiveTest(const AABBQuantizedNode* node, udword clip_mask); 105 | void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node, udword clip_mask); 106 | // Overlap tests 107 | inline_ BOOL PlanesAABBOverlap(const IceMaths::Point& center, const IceMaths::Point& extents, udword& out_clip_mask, udword in_clip_mask); 108 | inline_ BOOL PlanesTriOverlap(udword in_clip_mask); 109 | // Init methods 110 | BOOL InitQuery(PlanesCache& cache, const IceMaths::Plane* planes, udword nb_planes, const IceMaths::Matrix4x4* worldm=null); 111 | }; 112 | 113 | class OPCODE_API HybridPlanesCollider : public PlanesCollider 114 | { 115 | public: 116 | // Constructor / Destructor 117 | HybridPlanesCollider(); 118 | virtual ~HybridPlanesCollider(); 119 | 120 | bool Collide(PlanesCache& cache, const IceMaths::Plane* planes, udword nb_planes, const HybridModel& model, const IceMaths::Matrix4x4* worldm=null); 121 | protected: 122 | Container mTouchedBoxes; 123 | }; 124 | 125 | #endif // __OPC_PLANESCOLLIDER_H__ 126 | -------------------------------------------------------------------------------- /opcodemesh/opcode/OPC_HybridModel.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /* 3 | * OPCODE - Optimized Collision Detection 4 | * Copyright (C) 2001 Pierre Terdiman 5 | * Homepage: http://www.codercorner.com/Opcode.htm 6 | */ 7 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 10 | /** 11 | * Contains code for hybrid models. 12 | * \file OPC_HybridModel.h 13 | * \author Pierre Terdiman 14 | * \date May, 18, 2003 15 | */ 16 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | // Include Guard 20 | #ifndef __OPC_HYBRIDMODEL_H__ 21 | #define __OPC_HYBRIDMODEL_H__ 22 | 23 | //! Leaf descriptor 24 | struct LeafTriangles 25 | { 26 | udword Data; //!< Packed data 27 | 28 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 29 | /** 30 | * Gets number of triangles in the leaf. 31 | * \return number of triangles N, with 0 < N <= 16 32 | */ 33 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 34 | inline_ udword GetNbTriangles() const { return (Data & 15)+1; } 35 | 36 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 37 | /** 38 | * Gets triangle index for this leaf. Indexed model's array of indices retrieved with HybridModel::GetIndices() 39 | * \return triangle index 40 | */ 41 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 42 | inline_ udword GetTriangleIndex() const { return Data>>4; } 43 | inline_ void SetData(udword nb, udword index) { ASSERT(nb>0 && nb<=16); nb--; Data = (index<<4)|(nb&15); } 44 | }; 45 | 46 | class OPCODE_API HybridModel : public BaseModel 47 | { 48 | public: 49 | // Constructor/Destructor 50 | HybridModel(); 51 | virtual ~HybridModel(); 52 | 53 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 54 | /** 55 | * Builds a collision model. 56 | * \param create [in] model creation structure 57 | * \return true if success 58 | */ 59 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 60 | override(BaseModel) bool Build(const OPCODECREATE& create); 61 | 62 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 63 | /** 64 | * Gets the number of bytes used by the tree. 65 | * \return amount of bytes used 66 | */ 67 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 68 | override(BaseModel) udword GetUsedBytes() const; 69 | 70 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 71 | /** 72 | * Refits the collision model. This can be used to handle dynamic meshes. Usage is: 73 | * 1. modify your mesh vertices (keep the topology constant!) 74 | * 2. refit the tree (call this method) 75 | * \return true if success 76 | */ 77 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 78 | override(BaseModel) bool Refit(); 79 | 80 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 81 | /** 82 | * Gets array of triangles. 83 | * \return array of triangles 84 | */ 85 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 86 | inline_ const LeafTriangles* GetLeafTriangles() const { return mTriangles; } 87 | 88 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 89 | /** 90 | * Gets array of indices. 91 | * \return array of indices 92 | */ 93 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 94 | inline_ const udword* GetIndices() const { return mIndices; } 95 | 96 | private: 97 | udword mNbLeaves; //!< Number of leaf nodes in the model 98 | LeafTriangles* mTriangles; //!< Array of mNbLeaves leaf descriptors 99 | udword mNbPrimitives; //!< Number of primitives in the model 100 | udword* mIndices; //!< Array of primitive indices 101 | 102 | // Internal methods 103 | void Release(); 104 | }; 105 | 106 | #endif // __OPC_HYBRIDMODEL_H__ 107 | -------------------------------------------------------------------------------- /opcodemesh/opcode/OPC_TriTriOverlapGilvan.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // This is an optional header that implements a custom triangle-versus triangle intersection test. 4 | // This test can be used . 5 | // 6 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 7 | 8 | #define FindMinAndMax(m,M) \ 9 | if ( dp1 < m ) \ 10 | m = dp1; \ 11 | else \ 12 | if ( dp1 > M ) \ 13 | M = dp1; \ 14 | \ 15 | if ( dp2 < m ) \ 16 | m = dp2; \ 17 | else \ 18 | if ( dp2 > M ) \ 19 | M = dp2; 20 | 21 | #define TriProjection( rkD, a0,a1,a2, mi, ma ) \ 22 | { \ 23 | mi = ma= rkD|a0; \ 24 | const float dp1 = rkD|a1; \ 25 | const float dp2 = rkD|a2; \ 26 | \ 27 | FindMinAndMax(mi,ma) \ 28 | } 29 | 30 | #define TriProjection2D( a0,a1,a2, mi, ma ) \ 31 | { \ 32 | mi = ma = (ni0*a0[i0] + ni1*a0[i1]); \ 33 | const float dp1 = ni0*a1[i0] + ni1*a1[i1]; \ 34 | const float dp2 = ni0*a2[i0] + ni1*a2[i1]; \ 35 | \ 36 | FindMinAndMax(mi,ma) \ 37 | } 38 | 39 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 40 | /** 41 | * Triangle/triangle intersection test routine, by Gilvan Maia, 2004. 42 | * Some little optimizations were done and added a 2D SAT test for coplanar triangles. 43 | * This test is based on the tri-tri test from http://www.magik-software.com 44 | * 45 | * \param V0 [in] triangle 0, vertex 0 46 | * \param V1 [in] triangle 0, vertex 1 47 | * \param V2 [in] triangle 0, vertex 2 48 | * \param U0 [in] triangle 1, vertex 0 49 | * \param U1 [in] triangle 1, vertex 1 50 | * \param U2 [in] triangle 1, vertex 2 51 | * \return true if triangles overlap 52 | */ 53 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 54 | inline_ BOOL AABBTreeCollider::TriTriOverlap(const Point& u0, const Point& u1, const Point& u2, const Point& v0, const Point& v1, const Point& v2) 55 | { 56 | // Stats 57 | mNbPrimPrimTests++; 58 | 59 | float fVMin, fVMax; 60 | 61 | // direction N 62 | const Point e0 = u1-u0; 63 | const Point e1 = u2-u1; 64 | const Point kN = e0 ^ e1; 65 | const float fNdU0 = kN | u0;//u0u1u02 origin 66 | TriProjection(kN,v0,v1,v2,fVMin,fVMax); 67 | 68 | if ( fVMin > fNdU0 || fNdU0 > fVMax ) 69 | return FALSE; 70 | 71 | // direction M 72 | const Point f0 = v1-v0; 73 | const Point f1 = v2-v1; 74 | const Point kM = f0 ^ f1; 75 | 76 | if ( (kN ^ kM).SquareMagnitude() >= 1.0e-6f ) 77 | { 78 | // triangles are NOT coplanar... is this numerically stable/precise? 79 | const float fMdV0 = kM | v0; 80 | TriProjection(kM,u0,u1,u2,fVMin,fVMax); 81 | if ( fMdV0 < fVMin || fMdV0 > fVMax ) 82 | return FALSE; 83 | 84 | // Sweet macro that makes code shorter and understandable 85 | #define TEST_AXES( E, F ) \ 86 | { \ 87 | const Point kDir = E ^ F; \ 88 | float fUMin, fUMax; \ 89 | TriProjection(kDir,u0,u1,u2,fUMin,fUMax); \ 90 | TriProjection(kDir,v0,v1,v2,fVMin,fVMax); \ 91 | if ( fUMax < fVMin || fVMax < fUMin ) \ 92 | return FALSE; \ 93 | } 94 | 95 | // computes remaining edges 96 | // directions E[i0]xF[i1] 97 | //float fUMin, fUMax; 98 | 99 | TEST_AXES( e0, f0 ) 100 | TEST_AXES( e0, f1 ) 101 | TEST_AXES( e1, f1 ) 102 | TEST_AXES( e1, f0 ) 103 | 104 | const Point e2 = u0-u2; 105 | TEST_AXES( e2, f0 ) 106 | TEST_AXES( e2, f1 ) 107 | 108 | const Point f2 = v0-v2; 109 | TEST_AXES( e2, f2 ) 110 | TEST_AXES( e1, f2 ) 111 | TEST_AXES( e0, f2 ) 112 | 113 | 114 | return TRUE; 115 | } 116 | else 117 | { 118 | // NOTE: If they're coplanar, then their normals are the same?? 119 | #define SATUSE_3D_AXES 120 | #ifdef SATUSE_3D_AXES 121 | 122 | // this code looks like the original one, but with few changes 123 | float fUMin, fUMax; 124 | TEST_AXES( kN, e0 ) 125 | TEST_AXES( kN, e1 ) 126 | TEST_AXES( kM, f0 ) 127 | TEST_AXES( kM, f1 ) 128 | 129 | const Point e2 = u0-u2; 130 | TEST_AXES( kN, e2 ) 131 | const Point f2 = u0-u2; 132 | TEST_AXES( kM, f2 ) 133 | #else 134 | // brand new code 135 | const Point e2 = u0-u2; 136 | const Point f2 = v0-v2; 137 | const float A[3] = { fabsf(kN[0]), fabsf(kN[1]), fabsf(kN[2])}; 138 | float ni0, ni1; 139 | short i0,i1; 140 | 141 | // project onto an axis-aligned plane, that maximizes the area 142 | if(A[0]>A[1]) 143 | { 144 | if(A[0]>A[2]) 145 | { 146 | i0=1; /// A[0] is greatest 147 | i1=2; 148 | } 149 | else 150 | { 151 | i0=0; // A[2] is greatest 152 | i1=1; 153 | } 154 | } 155 | else // A[0]<=A[1] 156 | { 157 | if(A[2]>A[1]) 158 | { 159 | i0=0; // A[2] is greatest 160 | i1=1; 161 | } 162 | else 163 | { 164 | i0=0; // A[1] is greatest 165 | i1=2; 166 | } 167 | } 168 | 169 | #define TEST_AXES2D(edge) \ 170 | ni0 = edge[i0]; \ 171 | ni1 = -edge[i1]; \ 172 | TriProjection2D(u0,u1,u2,fUMin,fUMax); \ 173 | TriProjection2D(v0,v1,v2,fVMin,fVMax); \ 174 | if ( fUMax < fVMin || fVMax < fUMin ) \ 175 | return false; 176 | 177 | 178 | float fUMin, fUMax; 179 | TEST_AXES2D( e0 ) 180 | TEST_AXES2D( e1 ) 181 | TEST_AXES2D( e2 ) 182 | 183 | TEST_AXES2D( f0 ) 184 | TEST_AXES2D( f1 ) 185 | TEST_AXES2D( f2 ) 186 | #endif 187 | 188 | return TRUE; 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /opcodemesh/opcode/OPC_BaseModel.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /* 3 | * OPCODE - Optimized Collision Detection 4 | * Copyright (C) 2001 Pierre Terdiman 5 | * Homepage: http://www.codercorner.com/Opcode.htm 6 | */ 7 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 10 | /** 11 | * Contains base model interface. 12 | * \file OPC_BaseModel.cpp 13 | * \author Pierre Terdiman 14 | * \date May, 18, 2003 15 | */ 16 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | /** 20 | * The base class for collision models. 21 | * 22 | * \class BaseModel 23 | * \author Pierre Terdiman 24 | * \version 1.3 25 | * \date May, 18, 2003 26 | */ 27 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 28 | 29 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 30 | // Precompiled Header 31 | #include "Stdafx.h" 32 | 33 | using namespace Opcode; 34 | 35 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 36 | /** 37 | * Constructor. 38 | */ 39 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 40 | OPCODECREATE::OPCODECREATE() 41 | { 42 | mIMesh = null; 43 | mSettings.mRules = SPLIT_SPLATTER_POINTS | SPLIT_GEOM_CENTER; 44 | mSettings.mLimit = 1; // Mandatory for complete trees 45 | mNoLeaf = true; 46 | mQuantized = true; 47 | #ifdef __MESHMERIZER_H__ 48 | mCollisionHull = false; 49 | #endif // __MESHMERIZER_H__ 50 | mKeepOriginal = false; 51 | mCanRemap = false; 52 | } 53 | 54 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 55 | /** 56 | * Constructor. 57 | */ 58 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 59 | BaseModel::BaseModel() : mIMesh(null), mModelCode(0), mSource(null), mTree(null) 60 | { 61 | } 62 | 63 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 64 | /** 65 | * Destructor. 66 | */ 67 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 68 | BaseModel::~BaseModel() 69 | { 70 | ReleaseBase(); 71 | } 72 | 73 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 74 | /** 75 | * Releases everything. 76 | */ 77 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 78 | void BaseModel::ReleaseBase() 79 | { 80 | DELETESINGLE(mSource); 81 | DELETESINGLE(mTree); 82 | } 83 | 84 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 85 | /** 86 | * Creates an optimized tree according to user-settings, and setups mModelCode. 87 | * \param no_leaf [in] true for "no leaf" tree 88 | * \param quantized [in] true for quantized tree 89 | * \return true if success 90 | */ 91 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 92 | bool BaseModel::CreateTree(bool no_leaf, bool quantized) 93 | { 94 | DELETESINGLE(mTree); 95 | 96 | // Setup model code 97 | if(no_leaf) mModelCode |= OPC_NO_LEAF; 98 | else mModelCode &= ~OPC_NO_LEAF; 99 | 100 | if(quantized) mModelCode |= OPC_QUANTIZED; 101 | else mModelCode &= ~OPC_QUANTIZED; 102 | 103 | // Create the correct class 104 | if(mModelCode & OPC_NO_LEAF) 105 | { 106 | if(mModelCode & OPC_QUANTIZED) mTree = new AABBQuantizedNoLeafTree; 107 | else mTree = new AABBNoLeafTree; 108 | } 109 | else 110 | { 111 | if(mModelCode & OPC_QUANTIZED) mTree = new AABBQuantizedTree; 112 | else mTree = new AABBCollisionTree; 113 | } 114 | CHECKALLOC(mTree); 115 | 116 | return true; 117 | } 118 | 119 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 120 | /** 121 | * Refits the collision model. This can be used to handle dynamic meshes. Usage is: 122 | * 1. modify your mesh vertices (keep the topology constant!) 123 | * 2. refit the tree (call this method) 124 | * \return true if success 125 | */ 126 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 127 | bool BaseModel::Refit() 128 | { 129 | // Refit the optimized tree 130 | return mTree->Refit(mIMesh); 131 | 132 | // Old code kept for reference : refit the source tree then rebuild ! 133 | // if(!mSource) return false; 134 | // // Ouch... 135 | // mSource->Refit(&mTB); 136 | // // Ouch... 137 | // return mTree->Build(mSource); 138 | } 139 | -------------------------------------------------------------------------------- /opcodemesh/opcode/Ice/IceBoundingSphere.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /** 3 | * Contains code to compute the minimal bounding sphere. 4 | * \file IceBoundingSphere.h 5 | * \author Pierre Terdiman 6 | * \date January, 29, 2000 7 | */ 8 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | // Include Guard 12 | #ifndef __ICEBOUNDINGSPHERE_H__ 13 | #define __ICEBOUNDINGSPHERE_H__ 14 | 15 | enum BSphereMethod 16 | { 17 | BS_NONE, 18 | BS_GEMS, 19 | BS_MINIBALL, 20 | 21 | BS_FORCE_DWORD = 0x7fffffff 22 | }; 23 | 24 | class ICEMATHS_API Sphere 25 | { 26 | public: 27 | //! Constructor 28 | inline_ Sphere() {} 29 | //! Constructor 30 | inline_ Sphere(const Point& center, float radius) : mCenter(center), mRadius(radius) {} 31 | //! Constructor 32 | Sphere(udword nb_verts, const Point* verts); 33 | //! Copy constructor 34 | inline_ Sphere(const Sphere& sphere) : mCenter(sphere.mCenter), mRadius(sphere.mRadius) {} 35 | //! Destructor 36 | inline_ ~Sphere() {} 37 | 38 | BSphereMethod Compute(udword nb_verts, const Point* verts); 39 | bool FastCompute(udword nb_verts, const Point* verts); 40 | 41 | // Access methods 42 | inline_ const Point& GetCenter() const { return mCenter; } 43 | inline_ float GetRadius() const { return mRadius; } 44 | 45 | inline_ const Point& Center() const { return mCenter; } 46 | inline_ float Radius() const { return mRadius; } 47 | 48 | inline_ Sphere& Set(const Point& center, float radius) { mCenter = center; mRadius = radius; return *this; } 49 | inline_ Sphere& SetCenter(const Point& center) { mCenter = center; return *this; } 50 | inline_ Sphere& SetRadius(float radius) { mRadius = radius; return *this; } 51 | 52 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 53 | /** 54 | * Tests if a point is contained within the sphere. 55 | * \param p [in] the point to test 56 | * \return true if inside the sphere 57 | */ 58 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 59 | inline_ bool Contains(const Point& p) const 60 | { 61 | return mCenter.SquareDistance(p) <= mRadius*mRadius; 62 | } 63 | 64 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 65 | /** 66 | * Tests if a sphere is contained within the sphere. 67 | * \param sphere [in] the sphere to test 68 | * \return true if inside the sphere 69 | */ 70 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 71 | inline_ bool Contains(const Sphere& sphere) const 72 | { 73 | // If our radius is the smallest, we can't possibly contain the other sphere 74 | if(mRadius < sphere.mRadius) return false; 75 | // So r is always positive or null now 76 | float r = mRadius - sphere.mRadius; 77 | return mCenter.SquareDistance(sphere.mCenter) <= r*r; 78 | } 79 | 80 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 81 | /** 82 | * Tests if a box is contained within the sphere. 83 | * \param aabb [in] the box to test 84 | * \return true if inside the sphere 85 | */ 86 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 87 | inline_ BOOL Contains(const AABB& aabb) const 88 | { 89 | // I assume if all 8 box vertices are inside the sphere, so does the whole box. 90 | // Sounds ok but maybe there's a better way? 91 | float R2 = mRadius * mRadius; 92 | #ifdef USE_MIN_MAX 93 | const Point& Max = ((ShadowAABB&)&aabb).mMax; 94 | const Point& Min = ((ShadowAABB&)&aabb).mMin; 95 | #else 96 | Point Max; aabb.GetMax(Max); 97 | Point Min; aabb.GetMin(Min); 98 | #endif 99 | Point p; 100 | p.x=Max.x; p.y=Max.y; p.z=Max.z; if(mCenter.SquareDistance(p)>=R2) return FALSE; 101 | p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE; 102 | p.x=Max.x; p.y=Min.y; if(mCenter.SquareDistance(p)>=R2) return FALSE; 103 | p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE; 104 | p.x=Max.x; p.y=Max.y; p.z=Min.z; if(mCenter.SquareDistance(p)>=R2) return FALSE; 105 | p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE; 106 | p.x=Max.x; p.y=Min.y; if(mCenter.SquareDistance(p)>=R2) return FALSE; 107 | p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE; 108 | 109 | return TRUE; 110 | } 111 | 112 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 113 | /** 114 | * Tests if the sphere intersects another sphere 115 | * \param sphere [in] the other sphere 116 | * \return true if spheres overlap 117 | */ 118 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 119 | inline_ bool Intersect(const Sphere& sphere) const 120 | { 121 | float r = mRadius + sphere.mRadius; 122 | return mCenter.SquareDistance(sphere.mCenter) <= r*r; 123 | } 124 | 125 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 126 | /** 127 | * Checks the sphere is valid. 128 | * \return true if the box is valid 129 | */ 130 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 131 | inline_ BOOL IsValid() const 132 | { 133 | // Consistency condition for spheres: Radius >= 0.0f 134 | if(mRadius < 0.0f) return FALSE; 135 | return TRUE; 136 | } 137 | public: 138 | Point mCenter; //!< Sphere center 139 | float mRadius; //!< Sphere radius 140 | }; 141 | 142 | #endif // __ICEBOUNDINGSPHERE_H__ 143 | -------------------------------------------------------------------------------- /opcodemesh/opcode/OPC_OBBCollider.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /* 3 | * OPCODE - Optimized Collision Detection 4 | * Copyright (C) 2001 Pierre Terdiman 5 | * Homepage: http://www.codercorner.com/Opcode.htm 6 | */ 7 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 10 | /** 11 | * Contains code for an OBB collider. 12 | * \file OPC_OBBCollider.h 13 | * \author Pierre Terdiman 14 | * \date January, 1st, 2002 15 | */ 16 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | // Include Guard 20 | #ifndef __OPC_OBBCOLLIDER_H__ 21 | #define __OPC_OBBCOLLIDER_H__ 22 | 23 | struct OPCODE_API OBBCache : VolumeCache 24 | { 25 | OBBCache() : FatCoeff(1.1f) 26 | { 27 | FatBox.mCenter.Zero(); 28 | FatBox.mExtents.Zero(); 29 | FatBox.mRot.Identity(); 30 | } 31 | 32 | // Cached faces signature 33 | IceMaths::OBB FatBox; //!< Box used when performing the query resulting in cached faces 34 | // User settings 35 | float FatCoeff; //!< extents multiplier used to create a fat box 36 | }; 37 | 38 | class OPCODE_API OBBCollider : public VolumeCollider 39 | { 40 | public: 41 | // Constructor / Destructor 42 | OBBCollider(); 43 | virtual ~OBBCollider(); 44 | 45 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 46 | /** 47 | * Generic collision query for generic OPCODE models. After the call, access the results: 48 | * - with GetContactStatus() 49 | * - with GetNbTouchedPrimitives() 50 | * - with GetTouchedPrimitives() 51 | * 52 | * \param cache [in/out] a box cache 53 | * \param box [in] collision OBB in local space 54 | * \param model [in] Opcode model to collide with 55 | * \param worldb [in] OBB's world matrix, or null 56 | * \param worldm [in] model's world matrix, or null 57 | * \return true if success 58 | * \warning SCALE NOT SUPPORTED IN OBB MATRIX. The obb's matrix must contain rotation & translation parts only. 59 | */ 60 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 61 | bool Collide(OBBCache& cache, const IceMaths::OBB& box, const Model& model, const IceMaths::Matrix4x4* worldb=null, const IceMaths::Matrix4x4* worldm=null); 62 | 63 | // Settings 64 | 65 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 66 | /** 67 | * Settings: select between full box-box tests or "SAT-lite" tests (where Class III axes are discarded) 68 | * \param flag [in] true for full tests, false for coarse tests 69 | */ 70 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 71 | inline_ void SetFullBoxBoxTest(bool flag) { mFullBoxBoxTest = flag; } 72 | 73 | // Settings 74 | 75 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 76 | /** 77 | * Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider. 78 | * \return null if everything is ok, else a string describing the problem 79 | */ 80 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 81 | override(Collider) const char* ValidateSettings(); 82 | 83 | protected: 84 | // Precomputed data 85 | IceMaths::Matrix3x3 mAR; //!< Absolute rotation matrix 86 | IceMaths::Matrix3x3 mRModelToBox; //!< Rotation from model space to obb space 87 | IceMaths::Matrix3x3 mRBoxToModel; //!< Rotation from obb space to model space 88 | IceMaths::Point mTModelToBox; //!< Translation from model space to obb space 89 | IceMaths::Point mTBoxToModel; //!< Translation from obb space to model space 90 | 91 | IceMaths::Matrix3x3 mSRModelToBox; //!< Scale and Rotation from model space to obb space 92 | 93 | IceMaths::Point mBoxExtents; 94 | IceMaths::Point mB0; //!< - mTModelToBox + mBoxExtents 95 | IceMaths::Point mB1; //!< - mTModelToBox - mBoxExtents 96 | 97 | float mBBx1; 98 | float mBBy1; 99 | float mBBz1; 100 | 101 | float mBB_1; 102 | float mBB_2; 103 | float mBB_3; 104 | float mBB_4; 105 | float mBB_5; 106 | float mBB_6; 107 | float mBB_7; 108 | float mBB_8; 109 | float mBB_9; 110 | 111 | // Leaf description 112 | IceMaths::Point mLeafVerts[3]; //!< Triangle vertices 113 | // Settings 114 | bool mFullBoxBoxTest; //!< Perform full BV-BV tests (true) or SAT-lite tests (false) 115 | // Internal methods 116 | void _Collide(const AABBCollisionNode* node); 117 | void _Collide(const AABBNoLeafNode* node); 118 | void _Collide(const AABBQuantizedNode* node); 119 | void _Collide(const AABBQuantizedNoLeafNode* node); 120 | void _CollideNoPrimitiveTest(const AABBCollisionNode* node); 121 | void _CollideNoPrimitiveTest(const AABBNoLeafNode* node); 122 | void _CollideNoPrimitiveTest(const AABBQuantizedNode* node); 123 | void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node); 124 | // Overlap tests 125 | inline_ BOOL OBBContainsBox(const IceMaths::Point& bc, const IceMaths::Point& be); 126 | inline_ BOOL BoxBoxOverlap(const IceMaths::Point& extents, const IceMaths::Point& center); 127 | inline_ BOOL TriBoxOverlap(); 128 | // Init methods 129 | BOOL InitQuery(OBBCache& cache, const IceMaths::OBB& box, const IceMaths::Matrix4x4* worldb=null, const IceMaths::Matrix4x4* worldm=null); 130 | }; 131 | 132 | class OPCODE_API HybridOBBCollider : public OBBCollider 133 | { 134 | public: 135 | // Constructor / Destructor 136 | HybridOBBCollider(); 137 | virtual ~HybridOBBCollider(); 138 | 139 | bool Collide(OBBCache& cache, const IceMaths::OBB& box, const HybridModel& model, const IceMaths::Matrix4x4* worldb=null, const IceMaths::Matrix4x4* worldm=null); 140 | protected: 141 | Container mTouchedBoxes; 142 | }; 143 | 144 | #endif // __OPC_OBBCOLLIDER_H__ 145 | -------------------------------------------------------------------------------- /opcodemesh/opcode/OPC_VolumeCollider.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /* 3 | * OPCODE - Optimized Collision Detection 4 | * Copyright (C) 2001 Pierre Terdiman 5 | * Homepage: http://www.codercorner.com/Opcode.htm 6 | */ 7 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 10 | /** 11 | * Contains base volume collider class. 12 | * \file OPC_VolumeCollider.h 13 | * \author Pierre Terdiman 14 | * \date June, 2, 2001 15 | */ 16 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | // Include Guard 20 | #ifndef __OPC_VOLUMECOLLIDER_H__ 21 | #define __OPC_VOLUMECOLLIDER_H__ 22 | 23 | struct OPCODE_API VolumeCache 24 | { 25 | VolumeCache() : Model(null) {} 26 | ~VolumeCache() {} 27 | 28 | Container TouchedPrimitives; //!< Indices of touched primitives 29 | const BaseModel* Model; //!< Owner 30 | }; 31 | 32 | class OPCODE_API VolumeCollider : public Collider 33 | { 34 | public: 35 | // Constructor / Destructor 36 | VolumeCollider(); 37 | virtual ~VolumeCollider() = 0; 38 | 39 | // Collision report 40 | 41 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 42 | /** 43 | * Gets the number of touched primitives after a collision query. 44 | * \see GetContactStatus() 45 | * \see GetTouchedPrimitives() 46 | * \return the number of touched primitives 47 | */ 48 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 49 | inline_ udword GetNbTouchedPrimitives() const { return mTouchedPrimitives ? mTouchedPrimitives->GetNbEntries() : 0; } 50 | 51 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 52 | /** 53 | * Gets the list of touched primitives after a collision query. 54 | * \see GetContactStatus() 55 | * \see GetNbTouchedPrimitives() 56 | * \return the list of touched primitives (primitive indices) 57 | */ 58 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 59 | inline_ const udword* GetTouchedPrimitives() const { return mTouchedPrimitives ? mTouchedPrimitives->GetEntries() : null; } 60 | 61 | // Stats 62 | 63 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 64 | /** 65 | * Stats: gets the number of Volume-BV overlap tests after a collision query. 66 | * \see GetNbVolumePrimTests() 67 | * \return the number of Volume-BV tests performed during last query 68 | */ 69 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 70 | inline_ udword GetNbVolumeBVTests() const { return mNbVolumeBVTests; } 71 | 72 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 73 | /** 74 | * Stats: gets the number of Volume-Triangle overlap tests after a collision query. 75 | * \see GetNbVolumeBVTests() 76 | * \return the number of Volume-Triangle tests performed during last query 77 | */ 78 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 79 | inline_ udword GetNbVolumePrimTests() const { return mNbVolumePrimTests; } 80 | 81 | // Settings 82 | 83 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 84 | /** 85 | * Validates current settings. You should call this method after all the settings / callbacks have been defined for a collider. 86 | * \return null if everything is ok, else a string describing the problem 87 | */ 88 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 89 | override(Collider) const char* ValidateSettings(); 90 | 91 | protected: 92 | // Touched primitives 93 | Container* mTouchedPrimitives; //!< List of touched primitives 94 | // Precompured scale cache 95 | IceMaths::Point mLocalScale; //!< Collision model's local scale (stripped off from its matrix) 96 | // Dequantization coeffs 97 | IceMaths::Point mCenterCoeff; 98 | IceMaths::Point mExtentsCoeff; 99 | // Stats 100 | udword mNbVolumeBVTests; //!< Number of Volume-BV tests 101 | udword mNbVolumePrimTests; //!< Number of Volume-Primitive tests 102 | // Internal methods 103 | void _Dump(const AABBCollisionNode* node); 104 | void _Dump(const AABBNoLeafNode* node); 105 | void _Dump(const AABBQuantizedNode* node); 106 | void _Dump(const AABBQuantizedNoLeafNode* node); 107 | 108 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 109 | /** 110 | * Initializes a query 111 | */ 112 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 113 | override(Collider) inline_ void InitQuery() 114 | { 115 | // Reset stats & contact status 116 | mNbVolumeBVTests = 0; 117 | mNbVolumePrimTests = 0; 118 | Collider::InitQuery(); 119 | } 120 | 121 | inline_ BOOL IsCacheValid(VolumeCache& cache) 122 | { 123 | // We're going to do a volume-vs-model query. 124 | if(cache.Model!=mCurrentModel) 125 | { 126 | // Cached list was for another model so we can't keep it 127 | // Keep track of new owner and reset cache 128 | cache.Model = mCurrentModel; 129 | return FALSE; 130 | } 131 | else 132 | { 133 | // Same models, no problem 134 | return TRUE; 135 | } 136 | } 137 | }; 138 | 139 | #endif // __OPC_VOLUMECOLLIDER_H__ 140 | -------------------------------------------------------------------------------- /opcodemesh/opcode/Ice/IceHPoint.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /** 3 | * Contains code for homogeneous points. 4 | * \file IceHPoint.h 5 | * \author Pierre Terdiman 6 | * \date April, 4, 2000 7 | */ 8 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | // Include Guard 12 | #ifndef __ICEHPOINT_H__ 13 | #define __ICEHPOINT_H__ 14 | 15 | class ICEMATHS_API HPoint : public Point 16 | { 17 | public: 18 | 19 | //! Empty constructor 20 | inline_ HPoint() {} 21 | //! Constructor from floats 22 | inline_ HPoint(float _x, float _y, float _z, float _w=0.0f) : Point(_x, _y, _z), w(_w) {} 23 | //! Constructor from array 24 | inline_ HPoint(const float f[4]) : Point(f), w(f[3]) {} 25 | //! Constructor from a Point 26 | inline_ HPoint(const Point& p, float _w=0.0f) : Point(p), w(_w) {} 27 | //! Destructor 28 | inline_ ~HPoint() {} 29 | 30 | //! Clear the point 31 | inline_ HPoint& Zero() { x = y = z = w = 0.0f; return *this; } 32 | 33 | //! Assignment from values 34 | inline_ HPoint& Set(float _x, float _y, float _z, float _w ) { x = _x; y = _y; z = _z; w = _w; return *this; } 35 | //! Assignment from array 36 | inline_ HPoint& Set(const float f[4]) { x = f[_X]; y = f[_Y]; z = f[_Z]; w = f[_W]; return *this; } 37 | //! Assignment from another h-point 38 | inline_ HPoint& Set(const HPoint& src) { x = src.x; y = src.y; z = src.z; w = src.w; return *this; } 39 | 40 | //! Add a vector 41 | inline_ HPoint& Add(float _x, float _y, float _z, float _w ) { x += _x; y += _y; z += _z; w += _w; return *this; } 42 | //! Add a vector 43 | inline_ HPoint& Add(const float f[4]) { x += f[_X]; y += f[_Y]; z += f[_Z]; w += f[_W]; return *this; } 44 | 45 | //! Subtract a vector 46 | inline_ HPoint& Sub(float _x, float _y, float _z, float _w ) { x -= _x; y -= _y; z -= _z; w -= _w; return *this; } 47 | //! Subtract a vector 48 | inline_ HPoint& Sub(const float f[4]) { x -= f[_X]; y -= f[_Y]; z -= f[_Z]; w -= f[_W]; return *this; } 49 | 50 | //! Multiplies by a scalar 51 | inline_ HPoint& Mul(float s) { x *= s; y *= s; z *= s; w *= s; return *this; } 52 | 53 | //! Returns MIN(x, y, z, w); 54 | float Min() const { return MIN(x, MIN(y, MIN(z, w))); } 55 | //! Returns MAX(x, y, z, w); 56 | float Max() const { return MAX(x, MAX(y, MAX(z, w))); } 57 | //! Sets each element to be componentwise minimum 58 | HPoint& Min(const HPoint& p) { x = MIN(x, p.x); y = MIN(y, p.y); z = MIN(z, p.z); w = MIN(w, p.w); return *this; } 59 | //! Sets each element to be componentwise maximum 60 | HPoint& Max(const HPoint& p) { x = MAX(x, p.x); y = MAX(y, p.y); z = MAX(z, p.z); w = MAX(w, p.w); return *this; } 61 | 62 | //! Computes square magnitude 63 | inline_ float SquareMagnitude() const { return x*x + y*y + z*z + w*w; } 64 | //! Computes magnitude 65 | inline_ float Magnitude() const { return sqrtf(x*x + y*y + z*z + w*w); } 66 | 67 | //! Normalize the vector 68 | inline_ HPoint& Normalize() 69 | { 70 | float M = Magnitude(); 71 | if(M) 72 | { 73 | M = 1.0f / M; 74 | x *= M; 75 | y *= M; 76 | z *= M; 77 | w *= M; 78 | } 79 | return *this; 80 | } 81 | 82 | // Arithmetic operators 83 | //! Operator for HPoint Negate = - HPoint; 84 | inline_ HPoint operator-() const { return HPoint(-x, -y, -z, -w); } 85 | 86 | //! Operator for HPoint Plus = HPoint + HPoint; 87 | inline_ HPoint operator+(const HPoint& p) const { return HPoint(x + p.x, y + p.y, z + p.z, w + p.w); } 88 | //! Operator for HPoint Minus = HPoint - HPoint; 89 | inline_ HPoint operator-(const HPoint& p) const { return HPoint(x - p.x, y - p.y, z - p.z, w - p.w); } 90 | 91 | //! Operator for HPoint Mul = HPoint * HPoint; 92 | inline_ HPoint operator*(const HPoint& p) const { return HPoint(x * p.x, y * p.y, z * p.z, w * p.w); } 93 | //! Operator for HPoint Scale = HPoint * float; 94 | inline_ HPoint operator*(float s) const { return HPoint(x * s, y * s, z * s, w * s); } 95 | //! Operator for HPoint Scale = float * HPoint; 96 | inline_ friend HPoint operator*(float s, const HPoint& p) { return HPoint(s * p.x, s * p.y, s * p.z, s * p.w); } 97 | 98 | //! Operator for HPoint Div = HPoint / HPoint; 99 | inline_ HPoint operator/(const HPoint& p) const { return HPoint(x / p.x, y / p.y, z / p.z, w / p.w); } 100 | //! Operator for HPoint Scale = HPoint / float; 101 | inline_ HPoint operator/(float s) const { s = 1.0f / s; return HPoint(x * s, y * s, z * s, w * s); } 102 | //! Operator for HPoint Scale = float / HPoint; 103 | inline_ friend HPoint operator/(float s, const HPoint& p) { return HPoint(s / p.x, s / p.y, s / p.z, s / p.w); } 104 | 105 | //! Operator for float DotProd = HPoint | HPoint; 106 | inline_ float operator|(const HPoint& p) const { return x*p.x + y*p.y + z*p.z + w*p.w; } 107 | // No cross-product in 4D 108 | 109 | //! Operator for HPoint += HPoint; 110 | inline_ HPoint& operator+=(const HPoint& p) { x += p.x; y += p.y; z += p.z; w += p.w; return *this; } 111 | //! Operator for HPoint += float; 112 | inline_ HPoint& operator+=(float s) { x += s; y += s; z += s; w += s; return *this; } 113 | 114 | //! Operator for HPoint -= HPoint; 115 | inline_ HPoint& operator-=(const HPoint& p) { x -= p.x; y -= p.y; z -= p.z; w -= p.w; return *this; } 116 | //! Operator for HPoint -= float; 117 | inline_ HPoint& operator-=(float s) { x -= s; y -= s; z -= s; w -= s; return *this; } 118 | 119 | //! Operator for HPoint *= HPoint; 120 | inline_ HPoint& operator*=(const HPoint& p) { x *= p.x; y *= p.y; z *= p.z; w *= p.w; return *this; } 121 | //! Operator for HPoint *= float; 122 | inline_ HPoint& operator*=(float s) { x*=s; y*=s; z*=s; w*=s; return *this; } 123 | 124 | //! Operator for HPoint /= HPoint; 125 | inline_ HPoint& operator/=(const HPoint& p) { x /= p.x; y /= p.y; z /= p.z; w /= p.w; return *this; } 126 | //! Operator for HPoint /= float; 127 | inline_ HPoint& operator/=(float s) { s = 1.0f / s; x*=s; y*=s; z*=s; w*=s; return *this; } 128 | 129 | // Arithmetic operators 130 | 131 | //! Operator for Point Mul = HPoint * Matrix3x3; 132 | Point operator*(const Matrix3x3& mat) const; 133 | //! Operator for HPoint Mul = HPoint * Matrix4x4; 134 | HPoint operator*(const Matrix4x4& mat) const; 135 | 136 | // HPoint *= Matrix3x3 doesn't exist, the matrix is first casted to a 4x4 137 | //! Operator for HPoint *= Matrix4x4 138 | HPoint& operator*=(const Matrix4x4& mat); 139 | 140 | // Logical operators 141 | 142 | //! Operator for "if(HPoint==HPoint)" 143 | inline_ bool operator==(const HPoint& p) const { return ( (x==p.x)&&(y==p.y)&&(z==p.z)&&(w==p.w)); } 144 | //! Operator for "if(HPoint!=HPoint)" 145 | inline_ bool operator!=(const HPoint& p) const { return ( (x!=p.x)||(y!=p.y)||(z!=p.z)||(w!=p.w)); } 146 | 147 | // Cast operators 148 | 149 | //! Cast a HPoint to a Point. w is discarded. 150 | #ifdef _MSC_VER 151 | inline_ operator Point() const { return Point(x, y, z); } 152 | // gcc complains that conversion to a base class will never use a type conversion operator 153 | #endif 154 | 155 | public: 156 | float w; 157 | }; 158 | 159 | #endif // __ICEHPOINT_H__ 160 | 161 | --------------------------------------------------------------------------------