Mark Bufton

Drag and Drop - Apply to specific mesh(es)

Recommended Posts

Hi everyone.

I'm attempting to make a train simulator which includes working controls (brake lever, throttle leaver, switches, horn controls....I'm sure you get the idea). With switches I decided I could just toggle them on picking with the actions manager. The levers, however, provide me with more of a challenge.

As they revolve on a pivot I thought of using an (invisible) imposter mesh for the user input and setting the rotation of the lever meshes to correspond with the imposters x, y or z position, meaning the user's input will "move" the lever, so added the drag and drop code from the playground demo.

It works in principle. A bit messy maybe - especially as I also need to figure out how best to accurately 'reset' the imposter to the levers handle position on the pick up event to be best placed for the next use. My question (finally) is, "is there a way to apply drag drop input to only the imposter mesh(es), rather than having desks, windows, instuments etc etc moving around the scene (as highly amusing as that is)?"

Thanks everyone. I'll include a couple of screenshots to give a little context. In short, I want the levers to be movable (rotatable) by the 'driver'.

Mark.

Screenshot_2017-05-12-20-47-00.png

Screenshot_2017-05-12-20-44-12.png

Share this post


Link to post
Share on other sites

Hi Mark!  Good-lookin' scene/control panel.

Can I ask... what made you want physics active on the controls?  I don't think that is the best of ideas, but maybe you have some plans.

Perhaps you need something like mesh.isPickable = true/false... to get drag'n'drop selectivity.  That might be handy.

==== tons of extra crap ====

Have you studied our drag'n'drop demo?  If so, you probably realize the importance of the getGroundPosition() function... to the onPointerMove event handler (see line 106).

Some kind of "ground" must be "behind" the drag-start and drag-end positions, or else onPointerMove cannot calculate a "diff".

Here is a modification of the drag'n'drop demo, where a user needed a fake joystick... to control a submarine movement.  As you can see, it is variable.  The more you pull the joystick, the faster the xspeed and zspeed.  Note: Some user has put a slow-rotation into the sub... at line 134, possibly to help test lines 142-143... not important to you, but still, might be nice to remove before your tests.

Even in that demo, a "ground" is kept behind the entire joystick handle... for the very same reason... to calculate a diff.  In lines 142/143, the xspeed and zspeed are applied to the green submarine.  Not important, though.

Lines 110-114 are rotation limiters... making sure that the joystick (currentmesh) only rotates a certain amount of degrees.  You may need similar code to limit the rotation of your controls.

For your black-handle rotating control, and white-handle slider control... the "knobs" for both... extend higher than the panel they are mounted-upon - a panel which could be used for that darned getGroundPosition func.  You might have another ground behind the dashboard panels (perhaps the same ground that the tracks are laid-upon), and you simply need to set some dashboard panels .isPickable = false ... to keep them from being accidentally dragged.

As you can tell, camera position is very important, so that both controls can have a "ground" behind them.  If you tilt the camera on the red-bat joystick demo... in a way that the ground is NOT behind the joystick handle, the drag'n'drop does not work on the handle.

SO, maybe... a locked camera beta might be important.  Here is another version... where I have locked the camera.upperBetaLimit = 1.0 (line 8).  This keeps the camera from rotating downward to an amount > 1.0 radians.  (1.57 radians means camera can orbit-down to straight-on look, and 3.14 means camera can go well below ground.)  With 1.0, the joystick handle ALWAYS has a ground behind its entire height.

SO, if you make your control handles slightly shorter, and/or make the panel they are mounted-to... slightly deeper, and/or set the camera in a way that ALWAYS keeps their panel... behind them (so getGroundPosition() keeps working properly)... then you might be more successful, and without using any physics.

Of course, you can read the .rotation numbers on both levers... and convert those to values used for train brakes, dynamic brakes, loco brakes, throttle, etc.  I'm a train sim fan BIGTIME.  :)   I even did some early physics engine work... for steam loco wheels (with help from physics expert friends).  Note:  Lately, CannonJS has been starting in "slow motion mode"... and we have not yet found the reason.  You might wish to switch that playground... from version: latest, to version: 2.5.  (via a pull-down menu in upper right corner of playground app).  It should run 100% using 2.5.  It has not yet been proven that I ALONE am not seeing CannonJS sometimes start in slow-motion-mode.  It might be my computer only.  :o

I need to ping @enwolveren here, because I promised that when I got the train wheel demo updated (we formerly-used setPhysicsState calls, but lately, BJS has changed to mesh.physicsImpostor = (blah blah blah) format)...  I would tell him.  I hadn't updated the train wheel demo until... just now.  :)

I didn't really answer your question about how to keep physicsImpostors perfectly aligned-with the mesh... after the mesh is force-moved/stopped.  It is not always easy, because physicsImpostors are supposed to control mesh, and not mesh controlling physicsImpostors.  But, just the same, let me tell you something I've learned.  Physics bodies sometimes have "residual energy" that might need nulling-out when their mesh is manually forced to a stop.  Here are 2 "energy removers" that might be handy.  They are for CannonJS, but OimoJS (the by-default 3rd-party physics engine for BJS) has similar settables.

// using our CannonJS OR OimoJS physicsPlugin layer (preferred method)
mesh.physicsImpostor.setLinearVelocity(mesh.physicsImpostor, BABYLON.Vector3.Zero());
mesh.physicsImpostor.setAngularVelocity(mesh.physicsImpostor, new BABYLON.Vector3(0, 0, 0));

// or... using the "native" CannonJS physics "bodies" - deep-hacking
mesh.physicsImpostor.physicsBody.velocity = new CANNON.Vec3(0,0,0);
mesh.physicsImpostor.physicsBody.angularVelocity = new CANNON.Vec3(0,0,0);

I think you get the idea.  :)  Here's some assorted playgrounds that use "setLinearVelocity".

Again, I would suggest NOT using physics in the control handles, but... you might have some plan that I don't know about.  :) 

Main thing is... have fun!  Hope this helps, somehow.

Share this post


Link to post
Share on other sites

Thanks Wingnut, you've been a great help, as always.

I always look forward to your replies as I learn so much more than I would on my own. I shall have a play with my scene now and see if I can get things moving forwards......and backwards, left and right a little.....hell, maybe do a few barrel rolls haha.

Mark.

Share this post


Link to post
Share on other sites
    var getGroundPosition = function () {
        // Use a predicate to get position on the ground
        var pickinfo = scene.pick(scene.pointerX, scene.pointerY, function (mesh) { return mesh == ground; });
        if (pickinfo.hit) {
            return pickinfo.pickedPoint;
        }
        return null;
    }

See that return mesh == ground; out there on the end of that line?  A "predicate".  Let's pretend that you DID change from using a WORLD ground (where tracks might be laid) in a var named 'ground'... to using the panel that the controls are mounted-upon.  I think you understand... that this predicate MIGHT need to be changed to == panel; or similar.  I think a plane will work just as well as a ground.

Let's talk for a second about ONE reason why you MIGHT want physics on the controls... and that is... when the steam boiler (or a dropped bomb) blows-up the loco.  :) 

You'll want pieces of loco flying and bouncing across the ground, including those handles.  But, possibly, all those loco parts get physics added AFTER the yea-decision to blow-up the loco.  That's how I would do it.  You can launch a few boiler bolts and rivets while setting-up your pre-explosion physics and prepare setLinearVelocity directions and amounts for each loco part.  Then puff some particleSystem smoke and fire, and POOM... set all linearVelocities and watch stuff fly.

If using this idea... the physics (on little loco & rolling-stock parts) is active ONLY during the explosion.  Set the physicsEngine.world.allowSleep = true... so the parts don't "Brownian jitter" after they skid to a stop.  Just after explosion, you could iterate thru the loco parts... and check for physicsBody.isSleeping.  If sleeping, possibly... um... part.bakeCurrentTransformIntoVertices() (freeze the part where it is, and reset its .rotation, .position, and .scaling back to 0,0,0), and then remove it's physicsImpostor (keep performance high).  I'm not sure if you NEED to do that "bake"... but... if you remove the impostor from a mesh, it MIGHT move.  If it doesn't, no problems.  If it does, the bake might prevent that.  You also might look-into changing mesh impostor... to "noImpostor".

And, you know, for good train explosions (they were bombed pretty heavily in certain wars)... you need lots of separate pieces on the loco.  But this might hurt performance for regular gameplay.  So... possibly a complete model swap-out just before explosion... might be the wise way.  camera/mesh .layerMask might be handy, too.  It allows you to display SOME mesh and hide other mesh.  Then with one command, show different mesh, and hide different mesh. 

So, most of the time, you would hide the hi-rez (hi-parts) loco until explosion time.  At explosion time, you position the hi-rez loco == lo-rez loco, then tell the camera to change layerMask.  If everything works nice, the user doesn't notice.  And then POOM!  :)

By the way, when I say hi-rez... it doesn't necessarily mean hi-detail.  In fact, low-detail would be fine for explosion.  But, the more separate fly-able parts, the cooler the explosion.  :)  Using some parts as emitters for particleSystems... can cause a stream of smoke/sparks spewing from a flying part.  Gorgeous.  :)

I've never written a video game, so... there's a good chance that I am predominantly clueless.  But, it's still some crap to think about, especially if you are doing a war sim where bombing trains is pertinent.  :) 

Forum superhero Jerome once made a rollercoaster thing.  You can watch from afar, or use the followCam, or climb aboard (motion-sickness barf-warning).  See ya later... good luck.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.