mirror of
https://github.com/bloeys/physx-go.git
synced 2025-12-29 16:08:20 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c740204bd5 | |||
| 8c12404511 | |||
| fdb8fbbccf | |||
| 3d0a4f977b | |||
| 5a55870493 |
28
main.go
28
main.go
@ -2,12 +2,17 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
|
||||
"github.com/bloeys/physx-go/pgo"
|
||||
)
|
||||
|
||||
func contactHandler(cph pgo.ContactPairHeader) {
|
||||
|
||||
// ra1 := cph.GetRigidActors()[0]
|
||||
// ra2 := cph.GetRigidActors()[1]
|
||||
// fmt.Printf("Collision! User data 1: %v; User data 2: %v\n", ra1.GetUserData(), ra2.GetUserData())
|
||||
|
||||
// pairs := cph.GetPairs()
|
||||
// for i := 0; i < len(pairs); i++ {
|
||||
|
||||
@ -138,6 +143,21 @@ func main() {
|
||||
raycastBuffer := pgo.NewRaycastBuffer(1)
|
||||
defer raycastBuffer.Release()
|
||||
|
||||
// Example of correct usage of user data
|
||||
x := new(int64)
|
||||
*x = 1095
|
||||
ra.SetUserData(unsafe.Pointer(x))
|
||||
z := (*int64)(ra.GetUserData())
|
||||
fmt.Println("User data:", *z)
|
||||
|
||||
// The rigid actor might get garbage collected after this point (as its no longer used), but that will now cause
|
||||
// a memory leak and a crash since the user data got pinned (i.e. GC will not move or free it) when we used SetUserData above, but can no longer be unpinned as the runtime.Pinner object will get garbage collected with the rigid actor.
|
||||
//
|
||||
// To solve this we have 2 options:
|
||||
// 1. The pinner is unpinned before it is garbage collected by calling ClearUserData
|
||||
// 2. The object holding the active pinner (the rigid actor on which SetUserData was used) must remain alive (e.g. by pinning it, putting it in file scope, in a long lived object etc)
|
||||
ra.ClearUserData()
|
||||
|
||||
scene.SetScratchBuffer(4)
|
||||
for {
|
||||
scene.Collide(1 / 50.0)
|
||||
@ -147,10 +167,10 @@ func main() {
|
||||
|
||||
scene.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())
|
||||
// block := raycastBuffer.GetBlock()
|
||||
// d := block.GetDistance()
|
||||
// pos := block.GetPos()
|
||||
// fmt.Printf("Raycast hit at dist (%v) and post %v\n", d, pos.String())
|
||||
}
|
||||
// fmt.Printf("\nRaycast hit: %v\n", rHit)
|
||||
// fmt.Println("Press enter...")
|
||||
|
||||
Binary file not shown.
Binary file not shown.
85
pgo/pgo.go
85
pgo/pgo.go
@ -16,6 +16,7 @@ void goOnContactCallback_cgo(void* pairHeader);
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"runtime"
|
||||
"unsafe"
|
||||
|
||||
"github.com/bloeys/gglm/gglm"
|
||||
@ -544,7 +545,6 @@ type Quat struct {
|
||||
cQ C.struct_CPxQuat
|
||||
}
|
||||
|
||||
// CPxAPI CPxInline CSTRUCT CPxQuat NewCPxQuat(float angleRads, float x, float y, float z);
|
||||
func NewQuat(angleRads, x, y, z float32) *Quat {
|
||||
return &Quat{
|
||||
cQ: C.NewCPxQuat(C.float(angleRads), C.float(x), C.float(y), C.float(z)),
|
||||
@ -555,6 +555,50 @@ type Transform struct {
|
||||
cT C.struct_CPxTransform
|
||||
}
|
||||
|
||||
func (t *Transform) Pos() Vec3 {
|
||||
return Vec3{cV: t.cT.p}
|
||||
}
|
||||
|
||||
func (t *Transform) PosX() float32 {
|
||||
return float32(t.cT.p.x)
|
||||
}
|
||||
|
||||
func (t *Transform) PosY() float32 {
|
||||
return float32(t.cT.p.y)
|
||||
}
|
||||
|
||||
func (t *Transform) PosZ() float32 {
|
||||
return float32(t.cT.p.z)
|
||||
}
|
||||
|
||||
func (t *Transform) SetPos(v *Vec3) {
|
||||
t.cT.p = v.cV
|
||||
}
|
||||
|
||||
func (t *Transform) Rot() Quat {
|
||||
return Quat{cQ: t.cT.q}
|
||||
}
|
||||
|
||||
func (t *Transform) RotX() float32 {
|
||||
return float32(t.cT.q.x)
|
||||
}
|
||||
|
||||
func (t *Transform) RotY() float32 {
|
||||
return float32(t.cT.q.y)
|
||||
}
|
||||
|
||||
func (t *Transform) RotZ() float32 {
|
||||
return float32(t.cT.q.z)
|
||||
}
|
||||
|
||||
func (t *Transform) RotW() float32 {
|
||||
return float32(t.cT.q.w)
|
||||
}
|
||||
|
||||
func (t *Transform) SetRot(r *Quat) {
|
||||
t.cT.q = r.cQ
|
||||
}
|
||||
|
||||
// struct CPxTransform NewCPxTransform(struct CPxVec3*, struct CPxQuat*);
|
||||
func NewTransform(v *Vec3, q *Quat) *Transform {
|
||||
return &Transform{
|
||||
@ -661,14 +705,49 @@ type Actor struct {
|
||||
}
|
||||
|
||||
type RigidActor struct {
|
||||
cRa C.struct_CPxRigidActor
|
||||
cRa C.struct_CPxRigidActor
|
||||
pinner runtime.Pinner
|
||||
}
|
||||
|
||||
func (ra *RigidActor) SetSimFilterData(fd *FilterData) {
|
||||
C.CPxRigidActor_setSimFilterData(ra.cRa, fd.cFilterData)
|
||||
}
|
||||
|
||||
// CPxAPI void CPxRigidActor_setSimFilterData(CSTRUCT CPxRigidActor* cra, CSTRUCT CPxFilterData* cfd);
|
||||
// SetUserData sets the void* field on the rigid actor which can be used for any purpose.
|
||||
// For example, it can be used to store an id or pointer that ties this rigid actor to some other object
|
||||
//
|
||||
// Note-1: The passed pointer will be stored in C and as such needs to be pinned, which this function will do.
|
||||
// You can refer to this for notes on pinning and pointer rules: Refer to: https://pkg.go.dev/cmd/cgo#hdr-Passing_pointers
|
||||
//
|
||||
// Note-2: Since this RigidActor object is the one that pinned the user data, it MUST be kept alive at least until ClearUserData is used, at which point the data is unpinned and cleared.
|
||||
// If this RigidActor object gets garabage collected before clear, the pinner will detect its getting collected with stuff still pinned (which is a leak) and will panic.
|
||||
func (ra *RigidActor) SetUserData(userData unsafe.Pointer) {
|
||||
|
||||
// Note: Do NOT use interfaces here, as we need to ensure the original value
|
||||
// pointed to is pinned, not the pointer to the interface (i.e. pinning the interface).
|
||||
// Better avoid crazy to debug issues
|
||||
|
||||
// User data is a Go pointer stored in C/C++ code, and as such MUST be pinned
|
||||
// before that is done, and must be unpinned when no longer stored in C/C++.
|
||||
//
|
||||
// Here we assume every write is of a different object, and so we always unpin before storing
|
||||
// the new object.
|
||||
//
|
||||
// Refer to: https://pkg.go.dev/cmd/cgo#hdr-Passing_pointers
|
||||
ra.pinner.Unpin()
|
||||
ra.pinner.Pin(userData)
|
||||
|
||||
C.CPxRigidActor_set_userData(ra.cRa, userData)
|
||||
}
|
||||
|
||||
func (ra *RigidActor) GetUserData() unsafe.Pointer {
|
||||
return C.CPxRigidActor_get_userData(ra.cRa)
|
||||
}
|
||||
|
||||
func (ra *RigidActor) ClearUserData() {
|
||||
ra.pinner.Unpin()
|
||||
C.CPxRigidActor_set_userData(ra.cRa, nil)
|
||||
}
|
||||
|
||||
type RigidStatic struct {
|
||||
cRs C.struct_CPxRigidStatic
|
||||
|
||||
@ -4,16 +4,19 @@
|
||||
#include "CPxFilterData.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
struct CPxRigidActor
|
||||
{
|
||||
void* obj;
|
||||
void *obj;
|
||||
};
|
||||
|
||||
//Sets the CPxFilterData on all the shapes of the actor.
|
||||
// Sets the CPxFilterData on all the shapes of the actor.
|
||||
CPxAPI void CPxRigidActor_setSimFilterData(CSTRUCT CPxRigidActor cra, CSTRUCT CPxFilterData cfd);
|
||||
CPxAPI void CPxRigidActor_set_userData(CSTRUCT CPxRigidActor cra, void *userData);
|
||||
CPxAPI void *CPxRigidActor_get_userData(CSTRUCT CPxRigidActor cra);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -30,7 +30,17 @@ extern "C" {
|
||||
CPxAPI CPxReal CPxRigidDynamic_getAngularDamping(CSTRUCT CPxRigidDynamic crd);
|
||||
|
||||
CPxAPI CSTRUCT CPxVec3 CPxRigidDynamic_getLinearVelocity(CSTRUCT CPxRigidDynamic crd);
|
||||
CPxAPI void CPxRigidDynamic_setLinearVelocity(CSTRUCT CPxRigidDynamic crd, CSTRUCT CPxVec3* velocity, bool autoAwake);
|
||||
|
||||
CPxAPI CPxReal CPxRigidDynamic_getMaxLinearVelocity(CSTRUCT CPxRigidDynamic crd);
|
||||
CPxAPI void CPxRigidDynamic_setMaxLinearVelocity(CSTRUCT CPxRigidDynamic crd, CPxReal maxLinearVelocity);
|
||||
|
||||
|
||||
CPxAPI CSTRUCT CPxVec3 CPxRigidDynamic_getAngularVelocity(CSTRUCT CPxRigidDynamic crd);
|
||||
CPxAPI void CPxRigidDynamic_setAngularVelocity(CSTRUCT CPxRigidDynamic crd, CSTRUCT CPxVec3* velocity, bool autoAwake);
|
||||
|
||||
CPxAPI CPxReal CPxRigidDynamic_getMaxAngularVelocity(CSTRUCT CPxRigidDynamic crd);
|
||||
CPxAPI void CPxRigidDynamic_setMaxAngularVelocity(CSTRUCT CPxRigidDynamic crd, CPxReal maxAngularVelocity);
|
||||
|
||||
CPxAPI void CPxRigidDynamic_setMass(CSTRUCT CPxRigidDynamic crd, CPxReal mass);
|
||||
CPxAPI CPxReal CPxRigidDynamic_getMass(CSTRUCT CPxRigidDynamic crd);
|
||||
|
||||
@ -29,14 +29,14 @@ func (rd *RigidDynamic) SetLinearDamping(damping float32) {
|
||||
C.CPxRigidDynamic_setLinearDamping(rd.cRd, C.float(damping))
|
||||
}
|
||||
|
||||
func (rd *RigidDynamic) SetAngularDamping(damping float32) {
|
||||
C.CPxRigidDynamic_setAngularDamping(rd.cRd, C.float(damping))
|
||||
}
|
||||
|
||||
func (rd *RigidDynamic) GetLinearDamping() float32 {
|
||||
return float32(C.CPxRigidDynamic_getLinearDamping(rd.cRd))
|
||||
}
|
||||
|
||||
func (rd *RigidDynamic) SetAngularDamping(damping float32) {
|
||||
C.CPxRigidDynamic_setAngularDamping(rd.cRd, C.float(damping))
|
||||
}
|
||||
|
||||
func (rd *RigidDynamic) GetAngularDamping() float32 {
|
||||
return float32(C.CPxRigidDynamic_getAngularDamping(rd.cRd))
|
||||
}
|
||||
@ -47,12 +47,36 @@ func (rd *RigidDynamic) GetLinearVelocity() Vec3 {
|
||||
}
|
||||
}
|
||||
|
||||
func (rd *RigidDynamic) SetLinearVelocity(vel *Vec3, autoWake bool) {
|
||||
C.CPxRigidDynamic_setLinearVelocity(rd.cRd, &vel.cV, C._Bool(autoWake))
|
||||
}
|
||||
|
||||
func (rd *RigidDynamic) GetAngularVelocity() Vec3 {
|
||||
return Vec3{
|
||||
cV: C.CPxRigidDynamic_getAngularVelocity(rd.cRd),
|
||||
}
|
||||
}
|
||||
|
||||
func (rd *RigidDynamic) SetAngularVelocity(vel *Vec3, autoWake bool) {
|
||||
C.CPxRigidDynamic_setAngularVelocity(rd.cRd, &vel.cV, C._Bool(autoWake))
|
||||
}
|
||||
|
||||
func (rd *RigidDynamic) GetMaxLinearVelocity() float32 {
|
||||
return float32(C.CPxRigidDynamic_getMaxLinearVelocity(rd.cRd))
|
||||
}
|
||||
|
||||
func (rd *RigidDynamic) SetMaxLinearVelocity(vel float32) {
|
||||
C.CPxRigidDynamic_setMaxLinearVelocity(rd.cRd, C.float(vel))
|
||||
}
|
||||
|
||||
func (rd *RigidDynamic) GetMaxAngularVelocity() float32 {
|
||||
return float32(C.CPxRigidDynamic_getMaxAngularVelocity(rd.cRd))
|
||||
}
|
||||
|
||||
func (rd *RigidDynamic) SetMaxAngularVelocity(vel float32) {
|
||||
C.CPxRigidDynamic_setMaxAngularVelocity(rd.cRd, C.float(vel))
|
||||
}
|
||||
|
||||
func (rd *RigidDynamic) SetMass(mass float32) {
|
||||
C.CPxRigidDynamic_setMass(rd.cRd, C.float(mass))
|
||||
}
|
||||
@ -122,6 +146,13 @@ func (rd *RigidDynamic) ToRigidActor() RigidActor {
|
||||
}
|
||||
|
||||
func CreateDynamic(p Physics, t *Transform, g Geometry, m Material, density float32, shapeOffset *Transform) RigidDynamic {
|
||||
|
||||
if shapeOffset == nil {
|
||||
return RigidDynamic{
|
||||
cRd: C.CPxCreateDynamic(p.cPhysics, &t.cT, g.cG, m.cM, C.float(density), nil),
|
||||
}
|
||||
}
|
||||
|
||||
return RigidDynamic{
|
||||
cRd: C.CPxCreateDynamic(p.cPhysics, &t.cT, g.cG, m.cM, C.float(density), &shapeOffset.cT),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user