physx proper controller creation?

CodeKrash

16-03-2011 22:08:10

i know this is the wrong forum, but is this the right way to start a new controller?[Players_Client] System.ArgumentNullException: Value cannot be null.
at Mogre.PhysX.giNxProxy<NxController\,Mogre::PhysX::giNxRegisteredObject<Mogre::PhysX::ControllerManager> >..ctor(NxController* data)
at Mogre.PhysX.CapsuleController..ctor(ControllerManager mng, Scene scene, NxController* data)
at Mogre.PhysX.CreateControllerGeneric<class Mogre::PhysX::CapsuleControllerDesc,class Mogre::PhysX::CapsuleController>(ControllerManager mng, Scene scene, CapsuleControllerDesc Desc)
at Mogre.PhysX.ControllerManager.CreateController(Scene Scene, CapsuleControllerDesc Desc)
at ExtraMegaBlob.plugin.init()


private CapsuleControllerDesc ccd = new CapsuleControllerDesc();
private CapsuleController control = null;
control = OgreWindow.Instance.physics.ControllerManager.CreateController(OgreWindow.Instance.scene, ccd);

CodeKrash

17-03-2011 04:44:58

BoxController seems to work :D private BoxControllerDesc bcd = new BoxControllerDesc();
private BoxController control = null;
control = OgreWindow.Instance.physics.ControllerManager.CreateController(OgreWindow.Instance.scene, bcd);

Pyritie

19-03-2011 17:28:26

I started implementing Controllers in my game that uses physx today, and I'm getting the same problem

no idea why boxes work and capsules don't


var desc = new CapsuleControllerDesc {
Position = SpawnPosition,
Height = this.Height,
Radius = this.Radius,
SkinWidth = 0.1f,
SlopeLimit = Mogre.Math.DegreesToRadians(45),
StepOffset = 0.5f, // we use this to test above us if we're in a cave or something
UpDirection = HeightFieldAxes.Y,
ClimbingMode = CapsuleClimbingModes.Easy,
Callback = new StandardControllerHitReport(),
UserData = this,
};

var box = new BoxControllerDesc {
Position = SpawnPosition,
Extents = new Vector3(1, 1, 1),
SkinWidth = 0.1f,
SlopeLimit = Mogre.Math.DegreesToRadians(45),
StepOffset = 0.5f,
UpDirection = HeightFieldAxes.Y,
Callback = new StandardControllerHitReport(),
UserData = this,
};
LKernel.Get<PhysXMain>().ControllerManager.CreateController(LKernel.Get<PhysXMain>().Scene, box);
LKernel.Get<PhysXMain>().ControllerManager.CreateController(LKernel.Get<PhysXMain>().Scene, desc);


it crashes when I do the second CreateController line but the first works just fine. Getting the same error as the OP.

CodeKrash

19-03-2011 20:24:13

box controller descriptions work for me, but capsule descriptions crash.

smoove

26-03-2011 13:08:22

Hello!

By the looks of it, your capsule controller's Desc is not valid. Check its IsValid property. I suspect there's something wrong with the values of Position, Height or Radius.

If a controller can't be created from a Desc, PhysX will return null and the wrapper will throw an exception since a null object can't be wrapped. If you used the debug version of PhysX Candy Wrapper, you'd get an assertion failure also.

Maybe you're trying to create your controller too early at startup, therefore this.Height, this.Radius and SpawnPosition still contain junk.

Happy coding,
smoove.

Pyritie

26-03-2011 13:38:45

okay, so it was just me being stupid there.

Though now for some reason it doesn't like a height of 0. Is this normal? Or to get spheres do I just have to have the height be 0.0001f or something?

smoove

26-03-2011 13:48:56

Hello!

I checked the PhysX code:
NX_INLINE bool NxCapsuleControllerDesc::isValid() const
{
if(!NxControllerDesc::isValid()) return false;
if(radius<=0.0f) return false;
if(height<=0.0f) return false;
return true;
}


It says that both radius and height must be above zero. I guess the value 0.0001f would work.

Happy coding,
smoove.

Pyritie

26-03-2011 13:54:07

I edited my post up there with this but I wasn't expecting such a fast reply :D

I don't get how to move stuff around, am I doing it right?

ControllerFlags flags;
Controller.Move(displacement, activeGroups, minDist, out flags, smoothing);
// displacement = Vector3(0, 0, 0)
// activeGroups = 6
// minDist = 0.5 (same as radius)
// smoothing = 0.8


Because when I do it like this I get an AccessViolationException.

smoove

26-03-2011 14:05:15

Hello!

I've tried your code (moved a capsule controller) in my engine and it works. Maybe the exception is thrown by your IUserControllerHitReport implementation, if you have one (the Callback property on CapsuleControlerDesc). It would help if you pasted the console output of your program around the time it crashes.

Happy coding,
smoove.

Pyritie

26-03-2011 14:18:30

My hit report thingy is basically a C#-ified version of the one that's in the physx tutorial

public class StandardControllerHitReport : IUserControllerHitReport {

/// <summary>
/// Push around things with the CollidablePushableID, don't push anything else
/// </summary>
/// <param name="value"></param>
/// <returns>Do we automatically apply forces to the touched shape?</returns>
public ControllerActions OnShapeHit(ControllerShapeHit value) {
if (value != null) {
uint ID = value.ID;
// check the group
if (ID == Groups.CollidablePushableID) {
Actor actor = value.Shape.Actor;
// of course we can only push dynamic things
if (actor.IsDynamic) {
// We only allow horizontal pushes. Vertical pushes
// when we stand on dynamic objects creates
// useless stress on the solver. It would be possible
// to enable/disable vertical pushes on
// particular objects, if the gameplay requires it.
if (value.Direction.y == 0) {
float coeff = actor.Mass * value.Length * 10;
actor.AddForceAtLocalPos(value.Direction * coeff, Vector3.ZERO, ForceModes.Impulse);
}
}
}
}
return ControllerActions.None;
}

/// <summary>
/// Don't push other controllers
/// </summary>
/// <param name="value"></param>
/// <returns>Do we automatically apply forces to the touched controller?</returns>
public ControllerActions OnControllerHit(ControllersHit value) {

return ControllerActions.None;
}
}


...console output? It doesn't really have anything helpful

System.AccessViolationException was unhandled
Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Source=eyecm.PhysX
StackTrace:
at Mogre.PhysX.Controller.Move(Vector3 Displacement, UInt32 ActiveGroups, Single MinDistance, ControllerFlags& CollisionFlags, Single Sharpness)
at Lymph.Actors.MobileThing.Move(Vector3 displacement, UInt32 activeGroups, Single minDist, Single smoothing) in A:\Pyritie\Documents\Computer Science\MOgre\Lymph\Lymph\Actors\MobileThing.cs:line 77
at Lymph.Actors.MobileThing.Move(Vector3 displacement) in A:\Pyritie\Documents\Computer Science\MOgre\Lymph\Lymph\Actors\MobileThing.cs:line 87
at Lymph.Handlers.PlayerMovementHandler.FrameStarted(FrameEvent evt) in A:\Pyritie\Documents\Computer Science\MOgre\Lymph\Lymph\Handlers\PlayerMovementHandler.cs:line 47
at Mogre.Root.raise_FrameStarted(FrameEvent evt)
at Mogre.Root.OnFrameStarted(FrameEvent evt)
at Mogre.FrameListener_Director.frameStarted(FrameListener_Director* , FrameEvent* evt)
at Ogre.Root.renderOneFrame(Root* )
at Mogre.Root.RenderOneFrame()
at Lymph.Main.StartRendering() in A:\Pyritie\Documents\Computer Science\MOgre\Lymph\Lymph\Main.cs:line 73
at Lymph.Main.Go() in A:\Pyritie\Documents\Computer Science\MOgre\Lymph\Lymph\Main.cs:line 25
at Lymph.Launch.Main() in A:\Pyritie\Documents\Computer Science\MOgre\Lymph\Lymph\Launch.cs:line 17
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:

smoove

26-03-2011 14:28:03

Hello!

Hmm, I don't really have an idea. Could you set a breakpoint at the start of Lymph.Actors.MobileThing.Move method and check if the reference to your controller is valid (not null) and if the controller's properties seem ok to you (in the watch window). I'm assuming of course that MobileThing contains a reference to the controller you've created. Check if MobileThing itself is valid.

Also, comment everything in your StandardControllerHitReport except return ControllerActions.None;

That's all I can think of right now. If the problem persists, maybe you could send me a minimal version of your project that reproduces this situation and I can find out if there is a bug in the wrapper.

Happy coding,
smoove.

Pyritie

26-03-2011 14:55:05

Tried uncommenting everything; still doesn't work. The controller references are fine as well.

I'm not sure how much of a minimal project I could send, but I could send you a version with most of the large media files removed, if that would work.

CodeKrash

26-03-2011 19:34:32

okay, so it was just me being stupid there.

Though now for some reason it doesn't like a height of 0. Is this normal? Or to get spheres do I just have to have the height be 0.0001f or something?



Ccan you please elaborate just in case i was doing the same thing?

smoove

26-03-2011 19:35:38

Hello!

I'm posting this to let anyone interested in the topic know, that currently (March 2011) there is a logical inconsistency in the PhysX Candy Wrapper (thanks, Pyritie), relating to ownership of CharacterController-s. If a scene on which a CharacterController was created is Dispose-d, the CharacterController remains alive, but in an invalid state, which may cause problems later on.

The workaround is simple: Dispose all related CharacterControllers, before disposing any Scene-s.

Happy coding,
smoove.

smoove

26-03-2011 19:42:29

Hello!

Ccan you please elaborate just in case i was doing the same thing?

PhysX API calls isValid() method on the NxCapsuleControllerDesc before making the actual controller. isValid() returns false if height <= 0. If isValid() is false createController() doesn't even try creating the controller and just returns null. Null objects can't be wrapped, so the wrapper throws an exception.

Happy coding,
smoove.

Pyritie

26-03-2011 19:50:01

So it goes

dispose controller -> make controllermanager purge all of the controllers -> dispose scene

or is the first step not necessary?

EDIT never mind you just answered that in the email

I do indeed need the three steps

CodeKrash

29-03-2011 19:39:13

Hello!

Ccan you please elaborate just in case i was doing the same thing?

PhysX API calls isValid() method on the NxCapsuleControllerDesc before making the actual controller. isValid() returns false if height <= 0. If isValid() is false createController() doesn't even try creating the controller and just returns null. Null objects can't be wrapped, so the wrapper throws an exception.

Happy coding,
smoove.

kudos