mirror of
git://opensimulator.org/git/opensim-libs
synced 2026-08-14 00:58:00 +00:00
a few more changes to ubode
This commit is contained in:
@@ -21,7 +21,6 @@ libOPCODE_la_SOURCES = OPC_AABBCollider.cpp OPC_AABBCollider.h \
|
||||
OPC_OBBCollider.cpp OPC_OBBCollider.h \
|
||||
Opcode.cpp Opcode.h \
|
||||
OPC_OptimizedTree.cpp OPC_OptimizedTree.h \
|
||||
OPC_Picking.cpp OPC_Picking.h \
|
||||
OPC_PlanesCollider.cpp OPC_PlanesCollider.h \
|
||||
OPC_RayCollider.cpp OPC_RayCollider.h \
|
||||
OPC_SphereCollider.cpp OPC_SphereCollider.h \
|
||||
|
||||
@@ -320,70 +320,6 @@ void AABBCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node)
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Recursive collision query for quantized AABB trees.
|
||||
* \param node [in] current collision node
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void AABBCollider::_Collide(const AABBQuantizedNode* node)
|
||||
{
|
||||
// Dequantize box
|
||||
const QuantizedAABB& Box = node->mAABB;
|
||||
const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
|
||||
const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
|
||||
|
||||
// Perform AABB-AABB overlap test
|
||||
if(!AABBAABBOverlap(Extents, Center)) return;
|
||||
|
||||
TEST_BOX_IN_AABB(Center, Extents)
|
||||
|
||||
if(node->IsLeaf())
|
||||
{
|
||||
AABB_PRIM(node->GetPrimitive(), OPC_CONTACT)
|
||||
}
|
||||
else
|
||||
{
|
||||
_Collide(node->GetPos());
|
||||
|
||||
if(ContactFound()) return;
|
||||
|
||||
_Collide(node->GetNeg());
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Recursive collision query for quantized AABB trees, without primitive tests.
|
||||
* \param node [in] current collision node
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void AABBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node)
|
||||
{
|
||||
// Dequantize box
|
||||
const QuantizedAABB& Box = node->mAABB;
|
||||
const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
|
||||
const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
|
||||
|
||||
// Perform AABB-AABB overlap test
|
||||
if(!AABBAABBOverlap(Extents, Center)) return;
|
||||
|
||||
TEST_BOX_IN_AABB(Center, Extents)
|
||||
|
||||
if(node->IsLeaf())
|
||||
{
|
||||
SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
|
||||
}
|
||||
else
|
||||
{
|
||||
_CollideNoPrimitiveTest(node->GetPos());
|
||||
|
||||
if(ContactFound()) return;
|
||||
|
||||
_CollideNoPrimitiveTest(node->GetNeg());
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Recursive collision query for no-leaf AABB trees.
|
||||
@@ -393,17 +329,27 @@ void AABBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node)
|
||||
void AABBCollider::_Collide(const AABBNoLeafNode* node)
|
||||
{
|
||||
// Perform AABB-AABB overlap test
|
||||
if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return;
|
||||
if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter))
|
||||
return;
|
||||
|
||||
TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents)
|
||||
|
||||
if(node->HasPosLeaf()) { AABB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
|
||||
else _Collide(node->GetPos());
|
||||
if(node->HasPosLeaf())
|
||||
{
|
||||
AABB_PRIM(node->GetPosPrimitive(), OPC_CONTACT)
|
||||
}
|
||||
else
|
||||
_Collide(node->GetPos());
|
||||
|
||||
if(ContactFound()) return;
|
||||
if(ContactFound())
|
||||
return;
|
||||
|
||||
if(node->HasNegLeaf()) { AABB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
|
||||
else _Collide(node->GetNeg());
|
||||
if(node->HasNegLeaf())
|
||||
{
|
||||
AABB_PRIM(node->GetNegPrimitive(), OPC_CONTACT)
|
||||
}
|
||||
else
|
||||
_Collide(node->GetNeg());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -428,60 +374,6 @@ void AABBCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node)
|
||||
else _CollideNoPrimitiveTest(node->GetNeg());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Recursive collision query for quantized no-leaf AABB trees.
|
||||
* \param node [in] current collision node
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void AABBCollider::_Collide(const AABBQuantizedNoLeafNode* node)
|
||||
{
|
||||
// Dequantize box
|
||||
const QuantizedAABB& Box = node->mAABB;
|
||||
const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
|
||||
const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
|
||||
|
||||
// Perform AABB-AABB overlap test
|
||||
if(!AABBAABBOverlap(Extents, Center)) return;
|
||||
|
||||
TEST_BOX_IN_AABB(Center, Extents)
|
||||
|
||||
if(node->HasPosLeaf()) { AABB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
|
||||
else _Collide(node->GetPos());
|
||||
|
||||
if(ContactFound()) return;
|
||||
|
||||
if(node->HasNegLeaf()) { AABB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
|
||||
else _Collide(node->GetNeg());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Recursive collision query for quantized no-leaf AABB trees, without primitive tests.
|
||||
* \param node [in] current collision node
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void AABBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node)
|
||||
{
|
||||
// Dequantize box
|
||||
const QuantizedAABB& Box = node->mAABB;
|
||||
const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
|
||||
const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
|
||||
|
||||
// Perform AABB-AABB overlap test
|
||||
if(!AABBAABBOverlap(Extents, Center)) return;
|
||||
|
||||
TEST_BOX_IN_AABB(Center, Extents)
|
||||
|
||||
if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
|
||||
else _CollideNoPrimitiveTest(node->GetPos());
|
||||
|
||||
if(ContactFound()) return;
|
||||
|
||||
if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
|
||||
else _CollideNoPrimitiveTest(node->GetNeg());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Recursive collision query for vanilla AABB trees.
|
||||
@@ -509,8 +401,6 @@ void AABBCollider::_Collide(const AABBTreeNode* node)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Constructor.
|
||||
|
||||
@@ -191,17 +191,20 @@ inline_ BOOL AABBCollider::AABBAABBOverlap(const Point& extents, const Point& ce
|
||||
return ((_mm_movemask_ps(ma) & 0x07) == 0);
|
||||
|
||||
#else
|
||||
float tx = mBox.mCenter.x - center.x;
|
||||
float ex = extents.x + mBox.mExtents.x;
|
||||
if (fabs(tx) > ex) return FALSE;
|
||||
float t = mBox.mCenter.x - center.x;
|
||||
float e = extents.x + mBox.mExtents.x;
|
||||
if (fabs(t) > e)
|
||||
return FALSE;
|
||||
|
||||
float ty = mBox.mCenter.y - center.y;
|
||||
float ey = extents.y + mBox.mExtents.y;
|
||||
if (fabs(ty) > ey) return FALSE;
|
||||
t = mBox.mCenter.y - center.y;
|
||||
e = extents.y + mBox.mExtents.y;
|
||||
if (fabs(t) > e)
|
||||
return FALSE;
|
||||
|
||||
float tz = mBox.mCenter.z - center.z;
|
||||
float ez = extents.z + mBox.mExtents.z;
|
||||
if (fabs(tz) > ez) return FALSE;
|
||||
t = mBox.mCenter.z - center.z;
|
||||
e = extents.z + mBox.mExtents.z;
|
||||
if (fabs(t) > e)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,183 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/*
|
||||
* OPCODE - Optimized Collision Detection
|
||||
* Copyright (C) 2001 Pierre Terdiman
|
||||
* Homepage: http://www.codercorner.com/Opcode.htm
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Contains code to perform "picking".
|
||||
* \file OPC_Picking.cpp
|
||||
* \author Pierre Terdiman
|
||||
* \date March, 20, 2001
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Precompiled Header
|
||||
#include "Stdafx.h"
|
||||
|
||||
using namespace Opcode;
|
||||
|
||||
#ifdef OPC_RAYHIT_CALLBACK
|
||||
|
||||
/*
|
||||
Possible RayCollider usages:
|
||||
- boolean query (shadow feeler)
|
||||
- closest hit
|
||||
- all hits
|
||||
- number of intersection (boolean)
|
||||
|
||||
*/
|
||||
|
||||
bool Opcode::SetupAllHits(RayCollider& collider, CollisionFaces& contacts)
|
||||
{
|
||||
struct Local
|
||||
{
|
||||
static void AllContacts(const CollisionFace& hit, void* user_data)
|
||||
{
|
||||
CollisionFaces* CF = (CollisionFaces*)user_data;
|
||||
CF->AddFace(hit);
|
||||
}
|
||||
};
|
||||
|
||||
collider.SetFirstContact(false);
|
||||
collider.SetHitCallback(Local::AllContacts);
|
||||
collider.SetUserData(&contacts);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Opcode::SetupClosestHit(RayCollider& collider, CollisionFace& closest_contact)
|
||||
{
|
||||
struct Local
|
||||
{
|
||||
static void ClosestContact(const CollisionFace& hit, void* user_data)
|
||||
{
|
||||
CollisionFace* CF = (CollisionFace*)user_data;
|
||||
if(hit.mDistance<CF->mDistance) *CF = hit;
|
||||
}
|
||||
};
|
||||
|
||||
collider.SetFirstContact(false);
|
||||
collider.SetHitCallback(Local::ClosestContact);
|
||||
collider.SetUserData(&closest_contact);
|
||||
closest_contact.mDistance = MAX_FLOAT;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Opcode::SetupShadowFeeler(RayCollider& collider)
|
||||
{
|
||||
collider.SetFirstContact(true);
|
||||
collider.SetHitCallback(null);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Opcode::SetupInOutTest(RayCollider& collider)
|
||||
{
|
||||
collider.SetFirstContact(false);
|
||||
collider.SetHitCallback(null);
|
||||
// Results with collider.GetNbIntersections()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Opcode::Picking(
|
||||
CollisionFace& picked_face,
|
||||
const Ray& world_ray, const Model& model, const Matrix4x4* world,
|
||||
float min_dist, float max_dist, const Point& view_point, CullModeCallback callback, void* user_data)
|
||||
{
|
||||
struct Local
|
||||
{
|
||||
struct CullData
|
||||
{
|
||||
CollisionFace* Closest;
|
||||
float MinLimit;
|
||||
CullModeCallback Callback;
|
||||
void* UserData;
|
||||
Point ViewPoint;
|
||||
const MeshInterface* IMesh;
|
||||
};
|
||||
|
||||
// Called for each stabbed face
|
||||
static void RenderCullingCallback(const CollisionFace& hit, void* user_data)
|
||||
{
|
||||
CullData* Data = (CullData*)user_data;
|
||||
|
||||
// Discard face if we already have a closer hit
|
||||
if(hit.mDistance>=Data->Closest->mDistance) return;
|
||||
|
||||
// Discard face if hit point is smaller than min limit. This mainly happens when the face is in front
|
||||
// of the near clip plane (or straddles it). If we keep the face nonetheless, the user can select an
|
||||
// object that he may not even be able to see, which is very annoying.
|
||||
if(hit.mDistance<=Data->MinLimit) return;
|
||||
|
||||
// This is the index of currently stabbed triangle.
|
||||
udword StabbedFaceIndex = hit.mFaceID;
|
||||
|
||||
// We may keep it or not, depending on backface culling
|
||||
bool KeepIt = true;
|
||||
|
||||
// Catch *render* cull mode for this face
|
||||
CullMode CM = (Data->Callback)(StabbedFaceIndex, Data->UserData);
|
||||
|
||||
if(CM!=CULLMODE_NONE) // Don't even compute culling for double-sided triangles
|
||||
{
|
||||
// Compute backface culling for current face
|
||||
|
||||
VertexPointers VP;
|
||||
ConversionArea VC;
|
||||
Data->IMesh->GetTriangle(VP, StabbedFaceIndex, VC);
|
||||
if(VP.BackfaceCulling(Data->ViewPoint))
|
||||
{
|
||||
if(CM==CULLMODE_CW) KeepIt = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(CM==CULLMODE_CCW) KeepIt = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(KeepIt) *Data->Closest = hit;
|
||||
}
|
||||
};
|
||||
|
||||
RayCollider RC;
|
||||
RC.SetMaxDist(max_dist);
|
||||
RC.SetTemporalCoherence(false);
|
||||
RC.SetCulling(false); // We need all faces since some of them can be double-sided
|
||||
RC.SetFirstContact(false);
|
||||
RC.SetHitCallback(Local::RenderCullingCallback);
|
||||
|
||||
picked_face.mFaceID = INVALID_ID;
|
||||
picked_face.mDistance = MAX_FLOAT;
|
||||
picked_face.mU = 0.0f;
|
||||
picked_face.mV = 0.0f;
|
||||
|
||||
Local::CullData Data;
|
||||
Data.Closest = &picked_face;
|
||||
Data.MinLimit = min_dist;
|
||||
Data.Callback = callback;
|
||||
Data.UserData = user_data;
|
||||
Data.ViewPoint = view_point;
|
||||
Data.IMesh = model.GetMeshInterface();
|
||||
|
||||
if(world)
|
||||
{
|
||||
// Get matrices
|
||||
Matrix4x4 InvWorld;
|
||||
InvertPRMatrix(InvWorld, *world);
|
||||
|
||||
// Compute camera position in mesh space
|
||||
Data.ViewPoint *= InvWorld;
|
||||
}
|
||||
|
||||
RC.SetUserData(&Data);
|
||||
if(RC.Collide(world_ray, model, world))
|
||||
{
|
||||
return picked_face.mFaceID!=INVALID_ID;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,45 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/*
|
||||
* OPCODE - Optimized Collision Detection
|
||||
* Copyright (C) 2001 Pierre Terdiman
|
||||
* Homepage: http://www.codercorner.com/Opcode.htm
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Contains code to perform "picking".
|
||||
* \file OPC_Picking.h
|
||||
* \author Pierre Terdiman
|
||||
* \date March, 20, 2001
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Include Guard
|
||||
#ifndef __OPC_PICKING_H__
|
||||
#define __OPC_PICKING_H__
|
||||
|
||||
#ifdef OPC_RAYHIT_CALLBACK
|
||||
|
||||
enum CullMode
|
||||
{
|
||||
CULLMODE_NONE = 0,
|
||||
CULLMODE_CW = 1,
|
||||
CULLMODE_CCW = 2
|
||||
};
|
||||
|
||||
typedef CullMode (*CullModeCallback)(udword triangle_index, void* user_data);
|
||||
|
||||
OPCODE_API bool SetupAllHits (RayCollider& collider, CollisionFaces& contacts);
|
||||
OPCODE_API bool SetupClosestHit (RayCollider& collider, CollisionFace& closest_contact);
|
||||
OPCODE_API bool SetupShadowFeeler (RayCollider& collider);
|
||||
OPCODE_API bool SetupInOutTest (RayCollider& collider);
|
||||
|
||||
OPCODE_API bool Picking(
|
||||
CollisionFace& picked_face,
|
||||
const Ray& world_ray, const Model& model, const Matrix4x4* world,
|
||||
float min_dist, float max_dist, const Point& view_point, CullModeCallback callback, void* user_data);
|
||||
#endif
|
||||
|
||||
#endif //__OPC_PICKING_H__
|
||||
@@ -126,20 +126,6 @@ using namespace Opcode;
|
||||
/* In any case the contact has been found and recorded in mStabbedFace */ \
|
||||
mStabbedFace.mFaceID = prim_index;
|
||||
|
||||
#ifdef OPC_RAYHIT_CALLBACK
|
||||
|
||||
#define HANDLE_CONTACT(prim_index, flag) \
|
||||
SET_CONTACT(prim_index, flag) \
|
||||
\
|
||||
if(mHitCallback) (mHitCallback)(mStabbedFace, mUserData);
|
||||
|
||||
#define UPDATE_CACHE \
|
||||
if(cache && GetContactStatus()) \
|
||||
{ \
|
||||
*cache = mStabbedFace.mFaceID; \
|
||||
}
|
||||
#else
|
||||
|
||||
#define HANDLE_CONTACT(prim_index, flag) \
|
||||
SET_CONTACT(prim_index, flag) \
|
||||
\
|
||||
@@ -169,7 +155,6 @@ using namespace Opcode;
|
||||
if(Current) *cache = Current->mFaceID; \
|
||||
else *cache = INVALID_ID; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define SEGMENT_PRIM(prim_index, flag) \
|
||||
/* Request vertices from the app */ \
|
||||
@@ -180,7 +165,7 @@ using namespace Opcode;
|
||||
{ \
|
||||
/* Intersection point is valid if dist < segment's length */ \
|
||||
/* We know dist>0 so we can use integers */ \
|
||||
if(IR(mStabbedFace.mDistance)<IR(mMaxDist)) \
|
||||
if(mStabbedFace.mDistance < mMaxDist) \
|
||||
{ \
|
||||
HANDLE_CONTACT(prim_index, flag) \
|
||||
} \
|
||||
@@ -203,13 +188,8 @@ using namespace Opcode;
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
RayCollider::RayCollider() :
|
||||
#ifdef OPC_RAYHIT_CALLBACK
|
||||
mHitCallback (null),
|
||||
mUserData (0),
|
||||
#else
|
||||
mStabbedFaces (null),
|
||||
mClosestHit (false),
|
||||
#endif
|
||||
mNbRayBVTests (0),
|
||||
mNbRayPrimTests (0),
|
||||
mNbIntersections (0),
|
||||
@@ -236,12 +216,12 @@ RayCollider::~RayCollider()
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const char* RayCollider::ValidateSettings()
|
||||
{
|
||||
if(mMaxDist<0.0f) return "Higher distance bound must be positive!";
|
||||
if(mMaxDist < 0.0f) return "Higher distance bound must be positive!";
|
||||
if(TemporalCoherenceEnabled() && !FirstContactEnabled()) return "Temporal coherence only works with ""First contact"" mode!";
|
||||
#ifndef OPC_RAYHIT_CALLBACK
|
||||
|
||||
if(mClosestHit && FirstContactEnabled()) return "Closest hit doesn't work with ""First contact"" mode!";
|
||||
if(TemporalCoherenceEnabled() && mClosestHit) return "Temporal coherence can't guarantee to report closest hit!";
|
||||
#endif
|
||||
|
||||
if(SkipPrimitiveTests()) return "SkipPrimitiveTests not possible for RayCollider ! (not implemented)";
|
||||
return null;
|
||||
}
|
||||
@@ -268,18 +248,19 @@ bool RayCollider::Collide(const Ray& world_ray, const Model& model, const Matrix
|
||||
// Init collision query
|
||||
if(InitQuery(world_ray, world, cache)) return true;
|
||||
|
||||
const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
|
||||
const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
|
||||
|
||||
// Perform stabbing query
|
||||
if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(Tree->GetNodes());
|
||||
else _RayStab(Tree->GetNodes());
|
||||
// Perform stabbing query
|
||||
if(mMaxDist != MAX_FLOAT)
|
||||
_SegmentStab(Tree->GetNodes());
|
||||
else
|
||||
_RayStab(Tree->GetNodes());
|
||||
|
||||
// Update cache if needed
|
||||
UPDATE_CACHE
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Initializes a stabbing query :
|
||||
@@ -301,9 +282,9 @@ BOOL RayCollider::InitQuery(const Ray& world_ray, const Matrix4x4* world, udword
|
||||
mNbRayBVTests = 0;
|
||||
mNbRayPrimTests = 0;
|
||||
mNbIntersections = 0;
|
||||
#ifndef OPC_RAYHIT_CALLBACK
|
||||
if(mStabbedFaces) mStabbedFaces->Reset();
|
||||
#endif
|
||||
|
||||
if(mStabbedFaces)
|
||||
mStabbedFaces->Reset();
|
||||
|
||||
// Compute ray in local space
|
||||
// The (Origin/Dir) form is needed for the ray-triangle test anyway (even for segment tests)
|
||||
@@ -341,48 +322,16 @@ BOOL RayCollider::InitQuery(const Ray& world_ray, const Matrix4x4* world, udword
|
||||
// Test previously colliding primitives first
|
||||
if(TemporalCoherenceEnabled() && FirstContactEnabled() && face_id && *face_id!=INVALID_ID)
|
||||
{
|
||||
#ifdef OLD_CODE
|
||||
#ifndef OPC_RAYHIT_CALLBACK
|
||||
if(!mClosestHit)
|
||||
#endif
|
||||
{
|
||||
// Request vertices from the app
|
||||
VertexPointers VP;
|
||||
ConversionArea VC;
|
||||
mIMesh->GetTriangle(VP, *face_id, VC);
|
||||
// Perform ray-cached tri overlap test
|
||||
if(RayTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2]))
|
||||
{
|
||||
// Intersection point is valid if:
|
||||
// - distance is positive (else it can just be a face behind the orig point)
|
||||
// - distance is smaller than a given max distance (useful for shadow feelers)
|
||||
// if(mStabbedFace.mDistance>0.0f && mStabbedFace.mDistance<mMaxDist)
|
||||
if(IR(mStabbedFace.mDistance)<IR(mMaxDist)) // The other test is already performed in RayTriOverlap
|
||||
{
|
||||
// Set contact status
|
||||
mFlags |= OPC_TEMPORAL_CONTACT;
|
||||
|
||||
mStabbedFace.mFaceID = *face_id;
|
||||
|
||||
#ifndef OPC_RAYHIT_CALLBACK
|
||||
if(mStabbedFaces) mStabbedFaces->AddFace(mStabbedFace);
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
// New code
|
||||
// We handle both Segment/ray queries with the same segment code, and a possible infinite limit
|
||||
SEGMENT_PRIM(*face_id, OPC_TEMPORAL_CONTACT)
|
||||
|
||||
// Return immediately if possible
|
||||
if(GetContactStatus()) return TRUE;
|
||||
#endif
|
||||
if(GetContactStatus())
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Precompute data (moved after temporal coherence since only needed for ray-AABB)
|
||||
if(IR(mMaxDist)!=IEEE_MAX_FLOAT)
|
||||
if(mMaxDist != MAX_FLOAT)
|
||||
{
|
||||
// For Segment-AABB overlap
|
||||
mData = 0.5f * mDir * mMaxDist;
|
||||
@@ -470,36 +419,6 @@ void RayCollider::_SegmentStab(const AABBCollisionNode* node)
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Recursive stabbing query for quantized AABB trees.
|
||||
* \param node [in] current collision node
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void RayCollider::_SegmentStab(const AABBQuantizedNode* node)
|
||||
{
|
||||
// Dequantize box
|
||||
const QuantizedAABB& Box = node->mAABB;
|
||||
const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
|
||||
const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
|
||||
|
||||
// Perform Segment-AABB overlap test
|
||||
if(!SegmentAABBOverlap(Center, Extents)) return;
|
||||
|
||||
if(node->IsLeaf())
|
||||
{
|
||||
SEGMENT_PRIM(node->GetPrimitive(), OPC_CONTACT)
|
||||
}
|
||||
else
|
||||
{
|
||||
_SegmentStab(node->GetPos());
|
||||
|
||||
if(ContactFound()) return;
|
||||
|
||||
_SegmentStab(node->GetNeg());
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Recursive stabbing query for no-leaf AABB trees.
|
||||
@@ -526,36 +445,6 @@ void RayCollider::_SegmentStab(const AABBNoLeafNode* node)
|
||||
else _SegmentStab(node->GetNeg());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Recursive stabbing query for quantized no-leaf AABB trees.
|
||||
* \param node [in] current collision node
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void RayCollider::_SegmentStab(const AABBQuantizedNoLeafNode* node)
|
||||
{
|
||||
// Dequantize box
|
||||
const QuantizedAABB& Box = node->mAABB;
|
||||
const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
|
||||
const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
|
||||
|
||||
// Perform Segment-AABB overlap test
|
||||
if(!SegmentAABBOverlap(Center, Extents)) return;
|
||||
|
||||
if(node->HasPosLeaf())
|
||||
{
|
||||
SEGMENT_PRIM(node->GetPosPrimitive(), OPC_CONTACT)
|
||||
}
|
||||
else _SegmentStab(node->GetPos());
|
||||
|
||||
if(ContactFound()) return;
|
||||
|
||||
if(node->HasNegLeaf())
|
||||
{
|
||||
SEGMENT_PRIM(node->GetNegPrimitive(), OPC_CONTACT)
|
||||
}
|
||||
else _SegmentStab(node->GetNeg());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
@@ -608,36 +497,6 @@ void RayCollider::_RayStab(const AABBCollisionNode* node)
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Recursive stabbing query for quantized AABB trees.
|
||||
* \param node [in] current collision node
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void RayCollider::_RayStab(const AABBQuantizedNode* node)
|
||||
{
|
||||
// Dequantize box
|
||||
const QuantizedAABB& Box = node->mAABB;
|
||||
const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
|
||||
const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
|
||||
|
||||
// Perform Ray-AABB overlap test
|
||||
if(!RayAABBOverlap(Center, Extents)) return;
|
||||
|
||||
if(node->IsLeaf())
|
||||
{
|
||||
RAY_PRIM(node->GetPrimitive(), OPC_CONTACT)
|
||||
}
|
||||
else
|
||||
{
|
||||
_RayStab(node->GetPos());
|
||||
|
||||
if(ContactFound()) return;
|
||||
|
||||
_RayStab(node->GetNeg());
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Recursive stabbing query for no-leaf AABB trees.
|
||||
@@ -664,37 +523,6 @@ void RayCollider::_RayStab(const AABBNoLeafNode* node)
|
||||
else _RayStab(node->GetNeg());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Recursive stabbing query for quantized no-leaf AABB trees.
|
||||
* \param node [in] current collision node
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void RayCollider::_RayStab(const AABBQuantizedNoLeafNode* node)
|
||||
{
|
||||
// Dequantize box
|
||||
const QuantizedAABB& Box = node->mAABB;
|
||||
const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
|
||||
const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
|
||||
|
||||
// Perform Ray-AABB overlap test
|
||||
if(!RayAABBOverlap(Center, Extents)) return;
|
||||
|
||||
if(node->HasPosLeaf())
|
||||
{
|
||||
RAY_PRIM(node->GetPosPrimitive(), OPC_CONTACT)
|
||||
}
|
||||
else _RayStab(node->GetPos());
|
||||
|
||||
if(ContactFound()) return;
|
||||
|
||||
if(node->HasNegLeaf())
|
||||
{
|
||||
RAY_PRIM(node->GetNegPrimitive(), OPC_CONTACT)
|
||||
}
|
||||
else _RayStab(node->GetNeg());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Recursive stabbing query for vanilla AABB trees.
|
||||
|
||||
@@ -24,48 +24,49 @@
|
||||
{
|
||||
public:
|
||||
//! Constructor
|
||||
inline_ CollisionFace() {}
|
||||
inline_ CollisionFace() {}
|
||||
//! Destructor
|
||||
inline_ ~CollisionFace() {}
|
||||
inline_ ~CollisionFace() {}
|
||||
|
||||
udword mFaceID; //!< Index of touched face
|
||||
float mDistance; //!< Distance from collider to hitpoint
|
||||
float mU, mV; //!< Impact barycentric coordinates
|
||||
udword mFaceID; //!< Index of touched face
|
||||
float mDistance; //!< Distance from collider to hitpoint
|
||||
float mU, mV; //!< Impact barycentric coordinates
|
||||
};
|
||||
|
||||
class OPCODE_API CollisionFaces : public Container
|
||||
{
|
||||
public:
|
||||
//! Constructor
|
||||
CollisionFaces() {}
|
||||
CollisionFaces() {}
|
||||
//! Destructor
|
||||
~CollisionFaces() {}
|
||||
~CollisionFaces() {}
|
||||
|
||||
inline_ udword GetNbFaces() const { return GetNbEntries()>>2; }
|
||||
inline_ const CollisionFace* GetFaces() const { return (const CollisionFace*)GetEntries(); }
|
||||
inline_ udword GetNbFaces() const
|
||||
{
|
||||
return GetNbEntries() >> 2;
|
||||
}
|
||||
inline_ const CollisionFace* GetFaces() const
|
||||
{
|
||||
return (const CollisionFace*)GetEntries();
|
||||
}
|
||||
|
||||
inline_ void Reset() { Container::Reset(); }
|
||||
inline_ void Reset()
|
||||
{
|
||||
Container::Reset();
|
||||
}
|
||||
|
||||
inline_ void AddFace(const CollisionFace& face) { Add(face.mFaceID).Add(face.mDistance).Add(face.mU).Add(face.mV); }
|
||||
inline_ void AddFace(const CollisionFace& face)
|
||||
{
|
||||
Add(face.mFaceID).Add(face.mDistance).Add(face.mU).Add(face.mV);
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef OPC_RAYHIT_CALLBACK
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* User-callback, called by OPCODE to record a hit.
|
||||
* \param hit [in] current hit
|
||||
* \param user_data [in] user-defined data from SetCallback()
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
typedef void (*HitCallback) (const CollisionFace& hit, void* user_data);
|
||||
#endif
|
||||
|
||||
class OPCODE_API RayCollider : public Collider
|
||||
{
|
||||
public:
|
||||
// Constructor / Destructor
|
||||
RayCollider();
|
||||
virtual ~RayCollider();
|
||||
RayCollider();
|
||||
virtual ~RayCollider();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
@@ -81,12 +82,11 @@
|
||||
* \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
bool Collide(const Ray& world_ray, const Model& model, const Matrix4x4* world=null, udword* cache=null);
|
||||
bool Collide(const Ray& world_ray, const Model& model, const Matrix4x4* world=null, udword* cache=null);
|
||||
//
|
||||
bool Collide(const Ray& world_ray, const AABBTree* tree, Container& box_indices);
|
||||
bool Collide(const Ray& world_ray, const AABBTree* tree, Container& box_indices);
|
||||
// Settings
|
||||
|
||||
#ifndef OPC_RAYHIT_CALLBACK
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Settings: enable or disable "closest hit" mode.
|
||||
@@ -96,8 +96,11 @@
|
||||
* \see SetDestination(StabbedFaces* sf)
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
inline_ void SetClosestHit(bool flag) { mClosestHit = flag; }
|
||||
#endif
|
||||
inline_ void SetClosestHit(bool flag)
|
||||
{
|
||||
mClosestHit = flag;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Settings: enable or disable backface culling.
|
||||
@@ -107,7 +110,10 @@
|
||||
* \see SetDestination(StabbedFaces* sf)
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
inline_ void SetCulling(bool flag) { mCulling = flag; }
|
||||
inline_ void SetCulling(bool flag)
|
||||
{
|
||||
mCulling = flag;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
@@ -118,12 +124,11 @@
|
||||
* \see SetDestination(StabbedFaces* sf)
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
inline_ void SetMaxDist(float max_dist=MAX_FLOAT) { mMaxDist = max_dist; }
|
||||
inline_ void SetMaxDist(float max_dist = MAX_FLOAT)
|
||||
{
|
||||
mMaxDist = max_dist;
|
||||
}
|
||||
|
||||
#ifdef OPC_RAYHIT_CALLBACK
|
||||
inline_ void SetHitCallback(HitCallback cb) { mHitCallback = cb; }
|
||||
inline_ void SetUserData(void* user_data) { mUserData = user_data; }
|
||||
#else
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Settings: sets the destination array for stabbed faces.
|
||||
@@ -133,8 +138,10 @@
|
||||
* \see SetMaxDist(float max_dist)
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
inline_ void SetDestination(CollisionFaces* cf) { mStabbedFaces = cf; }
|
||||
#endif
|
||||
inline_ void SetDestination(CollisionFaces* cf)
|
||||
{
|
||||
mStabbedFaces = cf;
|
||||
}
|
||||
// Stats
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
@@ -144,7 +151,10 @@
|
||||
* \return the number of Ray-BV tests performed during last query
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
inline_ udword GetNbRayBVTests() const { return mNbRayBVTests; }
|
||||
inline_ udword GetNbRayBVTests() const
|
||||
{
|
||||
return mNbRayBVTests;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
@@ -154,7 +164,10 @@
|
||||
* \return the number of Ray-Triangle tests performed during last query
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
inline_ udword GetNbRayPrimTests() const { return mNbRayPrimTests; }
|
||||
inline_ udword GetNbRayPrimTests() const
|
||||
{
|
||||
return mNbRayPrimTests;
|
||||
}
|
||||
|
||||
// In-out test
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -165,7 +178,10 @@
|
||||
* \return the number of valid intersections during last query
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
inline_ udword GetNbIntersections() const { return mNbIntersections; }
|
||||
inline_ udword GetNbIntersections() const
|
||||
{
|
||||
return mNbIntersections;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
@@ -177,48 +193,38 @@
|
||||
|
||||
protected:
|
||||
// Ray in local space
|
||||
Point mOrigin; //!< Ray origin
|
||||
Point mDir; //!< Ray direction (normalized)
|
||||
Point mFDir; //!< fabsf(mDir)
|
||||
Point mData, mData2;
|
||||
Point mOrigin; //!< Ray origin
|
||||
Point mDir; //!< Ray direction (normalized)
|
||||
Point mFDir; //!< fabsf(mDir)
|
||||
Point mData, mData2;
|
||||
// Stabbed faces
|
||||
CollisionFace mStabbedFace; //!< Current stabbed face
|
||||
#ifdef OPC_RAYHIT_CALLBACK
|
||||
HitCallback mHitCallback; //!< Callback used to record a hit
|
||||
void* mUserData; //!< User-defined data
|
||||
#else
|
||||
CollisionFaces* mStabbedFaces; //!< List of stabbed faces
|
||||
bool mClosestHit; //!< Report closest hit only
|
||||
#endif
|
||||
CollisionFace mStabbedFace; //!< Current stabbed face
|
||||
CollisionFaces* mStabbedFaces; //!< List of stabbed faces
|
||||
bool mClosestHit; //!< Report closest hit only
|
||||
// Stats
|
||||
udword mNbRayBVTests; //!< Number of Ray-BV tests
|
||||
udword mNbRayPrimTests; //!< Number of Ray-Primitive tests
|
||||
udword mNbRayBVTests; //!< Number of Ray-BV tests
|
||||
udword mNbRayPrimTests; //!< Number of Ray-Primitive tests
|
||||
// In-out test
|
||||
udword mNbIntersections; //!< Number of valid intersections
|
||||
udword mNbIntersections; //!< Number of valid intersections
|
||||
// Dequantization coeffs
|
||||
Point mCenterCoeff;
|
||||
Point mExtentsCoeff;
|
||||
Point mCenterCoeff;
|
||||
Point mExtentsCoeff;
|
||||
// Settings
|
||||
float mMaxDist; //!< Valid segment on the ray
|
||||
|
||||
bool mCulling; //!< Stab culled faces or not
|
||||
float mMaxDist; //!< Valid segment on the ray
|
||||
bool mCulling; //!< Stab culled faces or not
|
||||
// Internal methods
|
||||
void _SegmentStab(const AABBCollisionNode* node);
|
||||
void _SegmentStab(const AABBNoLeafNode* node);
|
||||
void _SegmentStab(const AABBQuantizedNode* node);
|
||||
void _SegmentStab(const AABBQuantizedNoLeafNode* node);
|
||||
void _SegmentStab(const AABBTreeNode* node, Container& box_indices);
|
||||
void _RayStab(const AABBCollisionNode* node);
|
||||
void _RayStab(const AABBNoLeafNode* node);
|
||||
void _RayStab(const AABBQuantizedNode* node);
|
||||
void _RayStab(const AABBQuantizedNoLeafNode* node);
|
||||
void _RayStab(const AABBTreeNode* node, Container& box_indices);
|
||||
// Overlap tests
|
||||
inline_ BOOL RayAABBOverlap(const Point& center, const Point& extents);
|
||||
inline_ BOOL SegmentAABBOverlap(const Point& center, const Point& extents);
|
||||
inline_ BOOL RayTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2);
|
||||
void _SegmentStab(const AABBCollisionNode* node);
|
||||
void _SegmentStab(const AABBNoLeafNode* node);
|
||||
void _SegmentStab(const AABBTreeNode* node, Container& box_indices);
|
||||
void _RayStab(const AABBCollisionNode* node);
|
||||
void _RayStab(const AABBNoLeafNode* node);
|
||||
void _RayStab(const AABBTreeNode* node, Container& box_indices);
|
||||
// Overlap tests
|
||||
inline_ BOOL RayAABBOverlap(const Point& center, const Point& extents);
|
||||
inline_ BOOL SegmentAABBOverlap(const Point& center, const Point& extents);
|
||||
inline_ BOOL RayTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2);
|
||||
// Init methods
|
||||
BOOL InitQuery(const Ray& world_ray, const Matrix4x4* world=null, udword* face_id=null);
|
||||
BOOL InitQuery(const Ray& world_ray, const Matrix4x4* world=null, udword* face_id=null);
|
||||
};
|
||||
|
||||
#endif // __OPC_RAYCOLLIDER_H__
|
||||
|
||||
@@ -23,10 +23,10 @@ inline_ BOOL RayCollider::RayTriOverlap(const Point& vert0, const Point& vert1,
|
||||
Point edge2 = vert2 - vert0;
|
||||
|
||||
// Begin calculating determinant - also used to calculate U parameter
|
||||
Point pvec = mDir^edge2;
|
||||
Point pvec = mDir ^ edge2;
|
||||
|
||||
// If determinant is near zero, ray lies in plane of triangle
|
||||
float det = edge1|pvec;
|
||||
float det = edge1 | pvec;
|
||||
|
||||
if(mCulling)
|
||||
{
|
||||
@@ -62,7 +62,7 @@ inline_ BOOL RayCollider::RayTriOverlap(const Point& vert0, const Point& vert1,
|
||||
else
|
||||
{
|
||||
// the non-culling branch
|
||||
if(FastFabs(det) <= LOCAL_EPSILON * FCMin2(edge1.SquareMagnitude(), edge2.SquareMagnitude())) return FALSE;
|
||||
if(fabsf(det) <= LOCAL_EPSILON * FCMin2(edge1.SquareMagnitude(), edge2.SquareMagnitude())) return FALSE;
|
||||
float OneOverDet = 1.0f / det;
|
||||
|
||||
// Calculate distance from vert0 to ray origin
|
||||
|
||||
@@ -32,9 +32,6 @@
|
||||
//! Discard negative pointer in vanilla trees
|
||||
#define OPC_NO_NEG_VANILLA_TREE
|
||||
|
||||
//! Use a callback in the ray collider
|
||||
//#define OPC_RAYHIT_CALLBACK
|
||||
|
||||
// NB: no compilation flag to enable/disable stats since they're actually needed in the box/box overlap test
|
||||
|
||||
#endif //__OPC_SETTINGS_H__
|
||||
|
||||
@@ -106,8 +106,6 @@
|
||||
#include "OPC_LSSCollider.h"
|
||||
#include "OPC_PlanesCollider.h"
|
||||
// Usages
|
||||
#include "OPC_Picking.h"
|
||||
|
||||
|
||||
FUNCTION OPCODE_API bool InitOpcode();
|
||||
FUNCTION OPCODE_API bool CloseOpcode();
|
||||
|
||||
@@ -62,7 +62,7 @@ int dCollideTrimeshPlane( dxGeom *o1, dxGeom *o2, int flags, dContactGeom* conta
|
||||
dReal alpha;
|
||||
dVector3 vertex;
|
||||
|
||||
dVector3 int_vertex; // Intermediate vertex for double precision mode.
|
||||
//dVector3 int_vertex; // Intermediate vertex for double precision mode.
|
||||
|
||||
const unsigned uiTLSKind = trimesh->getParentSpaceTLSKind();
|
||||
dIASSERT(uiTLSKind == plane->getParentSpaceTLSKind()); // The colliding spaces must use matching cleanup method
|
||||
|
||||
Reference in New Issue
Block a user