diff --git a/main.go b/main.go index 240755e..0a855ed 100755 --- a/main.go +++ b/main.go @@ -127,6 +127,9 @@ func main() { //Run simulation // r := bufio.NewReader(os.Stdin) + raycastBuffer := pgo.NewRaycastBuffer(1) + defer raycastBuffer.Release() + s.SetScratchBuffer(4) for { s.Collide(1 / 50.0) @@ -134,9 +137,9 @@ func main() { s.Advance() s.FetchResults(true) - _, b := s.Raycast(pgo.NewVec3(0, 0, 0), pgo.NewVec3(0, 1, 0), 9) - if b.HasBlock() { - block := b.GetBlock() + s.RaycastWithHitBuffer(pgo.NewVec3(0, 0, 0), pgo.NewVec3(0, 1, 0), 9, raycastBuffer, 1) + if raycastBuffer.HasBlock() { + block := raycastBuffer.GetBlock() d := block.GetDistance() pos := block.GetPos() fmt.Printf("Raycast hit at dist (%v) and post %v\n", d, pos.String()) diff --git a/pgo/libs/libphysx-c.a b/pgo/libs/libphysx-c.a index a2679b7..6fe69d1 100755 Binary files a/pgo/libs/libphysx-c.a and b/pgo/libs/libphysx-c.a differ diff --git a/pgo/pgo.go b/pgo/pgo.go index 019aa07..e03f80b 100755 --- a/pgo/pgo.go +++ b/pgo/pgo.go @@ -135,6 +135,12 @@ func (s *Scene) Raycast(origin, unitDir *Vec3, distance float32) (bool, RaycastB return bool(ret), rb } +func (s *Scene) RaycastWithHitBuffer(origin, unitDir *Vec3, distance float32, rb *RaycastBuffer, touchesToRead uint) bool { + + ret := C.CPxScene_raycastWithHitBuffer(s.cS, &origin.cV, &unitDir.cV, C.float(distance), rb.cRb, C.uint(touchesToRead)) + return bool(ret) +} + type RaycastBuffer struct { cRb *C.struct_CPxRaycastBuffer } @@ -164,6 +170,19 @@ func (rb *RaycastBuffer) GetTouches() []RaycastHit { return hits } +func (rb *RaycastBuffer) Release() { + C.CPxRaycastBuffer_release(rb.cRb) +} + +func NewRaycastBuffer(maxTouches uint32) *RaycastBuffer { + + rb := &RaycastBuffer{ + cRb: C.NewCPxRaycastBufferWithAlloc(C.uint(maxTouches)), + } + + return rb +} + type RaycastHit struct { cRh *C.struct_CPxRaycastHit } diff --git a/pgo/physx-c/CPxRaycastBuffer.h b/pgo/physx-c/CPxRaycastBuffer.h new file mode 100755 index 0000000..e2b46de --- /dev/null +++ b/pgo/physx-c/CPxRaycastBuffer.h @@ -0,0 +1,67 @@ +#ifndef CPxRaycastBuffer_H +#define CPxRaycastBuffer_H + +#include "CPxVec3.h" +#include "CPxShape.h" +#include "CPxRigidActor.h" + +#ifdef __cplusplus +extern "C" { +#endif + + enum CPxHitFlag + { + CPxHitFlag_ePOSITION = (1 << 0), //!< "position" member of #PxQueryHit is valid + CPxHitFlag_eNORMAL = (1 << 1), //!< "normal" member of #PxQueryHit is valid + CPxHitFlag_eUV = (1 << 3), //!< "u" and "v" barycentric coordinates of #PxQueryHit are valid. Not applicable to sweep queries. + CPxHitFlag_eASSUME_NO_INITIAL_OVERLAP = (1 << 4), //!< Performance hint flag for sweeps when it is known upfront there's no initial overlap. + //!< NOTE: using this flag may cause undefined results if shapes are initially overlapping. + CPxHitFlag_eMESH_MULTIPLE = (1 << 5), //!< Report all hits for meshes rather than just the first. Not applicable to sweep queries. + CPxHitFlag_eMESH_ANY = (1 << 6), //!< Report any first hit for meshes. If neither eMESH_MULTIPLE nor eMESH_ANY is specified, + //!< a single closest hit will be reported for meshes. + CPxHitFlag_eMESH_BOTH_SIDES = (1 << 7), //!< Report hits with back faces of mesh triangles. Also report hits for raycast + //!< originating on mesh surface and facing away from the surface normal. Not applicable to sweep queries. + //!< Please refer to the user guide for heightfield-specific differences. + CPxHitFlag_ePRECISE_SWEEP = (1 << 8), //!< Use more accurate but slower narrow phase sweep tests. + //!< May provide better compatibility with PhysX 3.2 sweep behavior. + CPxHitFlag_eMTD = (1 << 9), //!< Report the minimum translation depth, normal and contact point. + CPxHitFlag_eFACE_INDEX = (1 << 10), //!< "face index" member of #PxQueryHit is valid + CPxHitFlag_eDEFAULT = CPxHitFlag_ePOSITION | CPxHitFlag_eNORMAL | CPxHitFlag_eFACE_INDEX, + /** \brief Only this subset of flags can be modified by pre-filter. Other modifications will be discarded. */ + CPxHitFlag_eMODIFIABLE_FLAGS = CPxHitFlag_eMESH_MULTIPLE | CPxHitFlag_eMESH_BOTH_SIDES | CPxHitFlag_eASSUME_NO_INITIAL_OVERLAP | CPxHitFlag_ePRECISE_SWEEP + }; + + struct CPxRaycastHit + { + CENUM CPxHitFlag flags; //!< Hit flags specifying which members contain valid values. + CSTRUCT CPxVec3 position; //!< World-space hit position (flag: #PxHitFlag::ePOSITION) + CSTRUCT CPxVec3 normal; //!< World-space hit normal (flag: #PxHitFlag::eNORMAL) + + /** + \brief Distance to hit. + \note If the eMTD flag is used, distance will be a negative value if shapes are overlapping indicating the penetration depth. + \note Otherwise, this value will be >= 0 */ + CPxF32 distance; + CPxReal u, v; + CPxU32 faceIndex; + CSTRUCT CPxShape shape; + CSTRUCT CPxRigidActor actor; + }; + + struct CPxRaycastBuffer + { + CSTRUCT CPxRaycastHit block; + CSTRUCT CPxRaycastHit* touches; + CPxU32 nbTouches; + bool hasBlock; + }; + + CPxAPI CSTRUCT CPxRaycastBuffer* NewCPxRaycastBufferWithAlloc(CPxU32 maxTouches); + CPxAPI void CPxRaycastBuffer_release(CSTRUCT CPxRaycastBuffer* crb); + +#ifdef __cplusplus +} +#endif + + +#endif // !CPxRaycastBuffer_H diff --git a/pgo/physx-c/CPxScene.h b/pgo/physx-c/CPxScene.h index d302618..64a0340 100755 --- a/pgo/physx-c/CPxScene.h +++ b/pgo/physx-c/CPxScene.h @@ -6,58 +6,12 @@ #include "CPxVec3.h" #include "CPxShape.h" #include "CPxRigidActor.h" +#include "CPxRaycastBuffer.h" #ifdef __cplusplus extern "C" { #endif - enum CPxHitFlag - { - CPxHitFlag_ePOSITION = (1 << 0), //!< "position" member of #PxQueryHit is valid - CPxHitFlag_eNORMAL = (1 << 1), //!< "normal" member of #PxQueryHit is valid - CPxHitFlag_eUV = (1 << 3), //!< "u" and "v" barycentric coordinates of #PxQueryHit are valid. Not applicable to sweep queries. - CPxHitFlag_eASSUME_NO_INITIAL_OVERLAP = (1 << 4), //!< Performance hint flag for sweeps when it is known upfront there's no initial overlap. - //!< NOTE: using this flag may cause undefined results if shapes are initially overlapping. - CPxHitFlag_eMESH_MULTIPLE = (1 << 5), //!< Report all hits for meshes rather than just the first. Not applicable to sweep queries. - CPxHitFlag_eMESH_ANY = (1 << 6), //!< Report any first hit for meshes. If neither eMESH_MULTIPLE nor eMESH_ANY is specified, - //!< a single closest hit will be reported for meshes. - CPxHitFlag_eMESH_BOTH_SIDES = (1 << 7), //!< Report hits with back faces of mesh triangles. Also report hits for raycast - //!< originating on mesh surface and facing away from the surface normal. Not applicable to sweep queries. - //!< Please refer to the user guide for heightfield-specific differences. - CPxHitFlag_ePRECISE_SWEEP = (1 << 8), //!< Use more accurate but slower narrow phase sweep tests. - //!< May provide better compatibility with PhysX 3.2 sweep behavior. - CPxHitFlag_eMTD = (1 << 9), //!< Report the minimum translation depth, normal and contact point. - CPxHitFlag_eFACE_INDEX = (1 << 10), //!< "face index" member of #PxQueryHit is valid - CPxHitFlag_eDEFAULT = CPxHitFlag_ePOSITION | CPxHitFlag_eNORMAL | CPxHitFlag_eFACE_INDEX, - /** \brief Only this subset of flags can be modified by pre-filter. Other modifications will be discarded. */ - CPxHitFlag_eMODIFIABLE_FLAGS = CPxHitFlag_eMESH_MULTIPLE | CPxHitFlag_eMESH_BOTH_SIDES | CPxHitFlag_eASSUME_NO_INITIAL_OVERLAP | CPxHitFlag_ePRECISE_SWEEP - }; - - struct CPxRaycastHit - { - CENUM CPxHitFlag flags; //!< Hit flags specifying which members contain valid values. - CSTRUCT CPxVec3 position; //!< World-space hit position (flag: #PxHitFlag::ePOSITION) - CSTRUCT CPxVec3 normal; //!< World-space hit normal (flag: #PxHitFlag::eNORMAL) - - /** - \brief Distance to hit. - \note If the eMTD flag is used, distance will be a negative value if shapes are overlapping indicating the penetration depth. - \note Otherwise, this value will be >= 0 */ - CPxF32 distance; - CPxReal u, v; - CPxU32 faceIndex; - CSTRUCT CPxShape shape; - CSTRUCT CPxRigidActor actor; - }; - - struct CPxRaycastBuffer - { - CSTRUCT CPxRaycastHit block; - CSTRUCT CPxRaycastHit* touches; - CPxU32 nbTouches; - bool hasBlock; - }; - struct CPxScene { void* obj; @@ -72,8 +26,14 @@ extern "C" { CPxAPI bool CPxScene_fetchCollision(CSTRUCT CPxScene*, bool block); CPxAPI void CPxScene_advance(CSTRUCT CPxScene*); CPxAPI bool CPxScene_fetchResults(CSTRUCT CPxScene*, bool block, CPxU32* errorState); + + //Does a scene raycast. Allocates memory for hitRet and then reads data into it. It is the callers responsibility to free. CPxAPI bool CPxScene_raycast(CSTRUCT CPxScene* cs, CSTRUCT CPxVec3* origin, CSTRUCT CPxVec3* unitDir, CPxReal distance, CSTRUCT CPxRaycastBuffer** hitRet); + //Does a scene raycast. 'hit' must be pre-allocated as NO new allocation will happen in the function. + //hit->touches will be filled up to 'touchesToRead' and must also be pre-allocated. If the hit produces more touches than 'touchesToRead' then the additional touches will be ignored. + CPxAPI bool CPxScene_raycastWithHitBuffer(CSTRUCT CPxScene* cs, CSTRUCT CPxVec3* origin, CSTRUCT CPxVec3* unitDir, CPxReal distance, CSTRUCT CPxRaycastBuffer* hit, CPxU32 touchesToRead); + /// /// Creates a scratch buffer thats a multiple of 16K to be used by the scene when running CPxScene_simulate. /// The buffer MUST be 16-byte aligned. If a buffer already exists then it is freed and a new one is allocated.