Archive for the ‘Physics & Simulation’ Category

Abstract

This was a project for my Masters in Computer Graphics, Games and Virtual Reality at URJC.

We were asked to develop some sort of mine train real-time animation from scratch. It had to feature dinamically-generated tunnel bumps with Perlin noise, on-board camera view and three rendering modes: Polygon fill, Wireframe and Points. We chose OpenSceneGraph for the job.

Design tools

As a big fan of rollercoasters I had spent hours on the NoLimits Rollercoaster Simulator which has a quite mature coaster editor. There’s plenty of coasters made with NoLimits around the net, most of them are reconstructions of real ones.

I thought it could be a good idea to be able to load coaster models in NoLimits (.nltrack) format as it would allow us to design the track and the scene in a visual way using the NL Editor.

The .nltrack format is binary and not documented. It contains the shape of the track as control points of cubic Bezier curves. It also contains info about the colors, supports, external .3DS objects and info about the general appearance of the rollercoaster.

Using Hexplorer and the NL editor itself I was able to figure out the control points and the location/scaling/rotation of the external 3D models. Later I discovered that there’s a library called libnltrack, which helped a lot.

My pal Danny modeled a couple of rooms, an outdoor scene and a lot of mine props (barrels, shovels, …). Then he imported them into the editor and laid out a coaster track passing trough all of the scene.

Coaster geometry

Correct generation of the rails and the crossbeams for the track was a bit of a challenge, and it needed to be efficient!.

I came up with a solution based on the concept of a “slider”, a virtual train which can be placed at any place around the track (just specifying how many kilometers away from the origin (the station) it would be), and it returns three orthonormal vectors forming a base which was then used to transform vertices to the train’s POV.

By using two sliders, one ahead of the other one can set vertices back and forth to form triangle strips in order to generate perfectly stitched cylinders. I ran into a couple of problems when the track was almost vertical but I finally managed to solve them.

Upon startup, the geometry for the whole coaster is generated. The engine generates about 15 meters of track per geode, this way OpenSceneGraph is able to cull the out-of-sight track segments efficiently. Besides, two levels of detail are generated based on the distance to the camera.

As for the crossbeams, it’s just a .3ds model which is repeatedly placed along the track.

Tunnels

The program generates a 256×256 grayscale perlin noise texture which is then used as a displacement mapping for a cylinder mesh generated around the track on load time.

The editor is able to mark segments as ‘tunnel’ easily turning tunnels on or of in a per-segment basis.

The meshes are also segmented for better culling and stitched together. They have a diffuse rock and floor texture applied.

Train

The train is a .3DS model by Danny which has a slider assigned to it and its animated following an extremely simple phyisics scheme based on the potential energy of the train. It has a spotlight on the front so the track, rooms and tunnels are illuminated as the train goes trhough. Moreover the illumination of the train mesh is switched from the sunlight to the spotlight based on wether it’s in a tunnel or not.

Effects

A skydome, lens flare (props to Tomás), and OSG’s impementation of shadow mapping were added in.

Audio and others

In the last minute before the deadline, supports for the track were generated as regularly-placed cylinders, but unfortunately that wasn’t there yet at the time the screenshots and the videos were taken.

A white noise audio file is played with a pitch and volume proportional to the train speed.

To be done

Due to the tight timing constraints we were subject to I was forced to leave a lot of things to be done, among them:

– Per-pixel lighting.

– Post-processing effects (vignette and HDR)

 

Advertisements

Intro

This is a project I developed while working at LSyM at the University of Valencia (Spain).
They had recently built a C.A.V.E system mounted on top of a powerful Manesmann 6 DOF Stewart mobile platform.
The system was sitting virtually unused and I wanted to develop some demo to show to visitors until a decent application was finally done.
I wasn’t allowed much time to do so and had to spend lots of my spare time working on it.
This is what I had:
The C.A.V.E platform at IRTIC (University of Valencia)
A C.A.V.E composed of:
  • Four hi-performance active-stereoscopic ProjectionDesign projectors.
  • A chair with a little dashboard with two joysticks and some buttons.

As you can see in the picture, the projectors are mounted on-board and have a wide-angle lens for retroprojection on the screens through mirrors. Each one has two DVI inputs (left/right field) and a genlock signal output.

A 6-DOF mobile platform:

  • It features X, Y, Z, heave, surge, and sway (rotation around the three axis).
  • It’s electro-hydraulic and its linear actuators are driven by that gray box at the bottom.
  • The box is connected to a dedicated control PC via fiber optic communication.
  • It’s capable of lifting up to 1000 Kg (I’m not really sure about this)
  • It works with 380 V (industrial range).
  • The control PC is connected via Ethernet to the application machine and runs a propietary manufacturer control program.
  • It receives frames over UDP with the instant position (the 6 DOF) at a rate of 60Hz approx.

A cluster composed of 5 machines:

  • 4 Quad-Core with nVidia Quadro. Each one of them renders a wall of the C.A.V.E (both left and right fields using independent DVI cables connected to both heads of the Quadros).
  • The cards are synchronized using nVidia Quadro G-Sync and an IR emitter is located on-board the C.A.V.E and connected to the master projector via GenLock for syncing the 3D glasses up.
  • The machines are running Windows XP x64.
  • 1 Master machine with a mid-range graphics card and a bit more underpowered.
  • The 5 machines are interconnected via a Gigabit Ethernet hub.

Amazing, huh?.

Just do it

I found myself with an equipment worth tens of thousands of euros and little time to leverage its full potential, and of course I was pretty much on my own.

I found Rollercoaster 2000 by PlusPlus, which is basically a very basic rollercoaster simulator. It takes a plain-text file containing the description of the track as Bezier control points and plays a 3D animation of the coaster in an OpenGL window. Graphics are VERY basic but it is fully open-sourced, so that’s just what I needed.

Rollercoaster 2K screenshot

Of course this app wasn’t ready for our CAVE & platform off the shelf and here it comes the fun part:

We were using VRJuggler as a middleware for rendering in the CAVE (by Carolina Cruz-Neira, the inventor of the CAVE herself!).

This middleware is a convenient way to deploy graphics applications across a wide range of VR systems and configurations.

It takes  care of intra-cluster communications, cameras orientation and frustum settings, I/O devices management ……

Making things work

Don’t get me wrong, the RC2K app basically works, it’s correct in math terms and it’s free. You can’t complain under these conditions and I’m grateful to its author for it. But the source is not very well commented out and not very well structured (lots of global vars, almost no use of structs…). Besides a lot of comments and symbols were written in French, which I don’t speak so I had to figure out a lot of things but it was pretty straightforward.

The first step was to encapsulate the app into a C++ class derived from some VRJuggler stuff.

Then I discovered that the physics (dynamic) loop was tightly coupled to the rendering loop. In fact they were the same!. As an immediate result the coaster physics were not very stable.

The physics thread

The solution was to spawn a thread in charge of physics. I isolated the variables involved in physics calculation and the thread just perform a simulation step at a constant rate. I defined a double buffer with the dynamic state protected with a mutex.

Master/Slaves model

In order to fit the architecture of our cluster I defined the master machine as the simulation controller. It only calculates the next physics step, and draws a view in an OpenGL window for the operator’s delight 😀

For each frame, VRJuggler takes the front physics buffer and broadcasts it to the slaves which are the 4 other machines in charge of rendering the C.A.V.E walls.

The slave machines basically get the data and draw its corresponding view (both left and right stereoscopic fields).

An XML config file allows VRJuggler to apply different camera configurations on a per-machine basis (based on the machine host name).

So the .EXE and .XML files are the same for all the machines and VRJuggler takes care of the rest (windows setup, stereo camera calculations, …).

It may look simple, however nobody knows how much pain did I pass through to get that working :-p

For execution I had set up a shared folder in the master machine with read access for all the slaves. I tried to launch them all via RPC but after hours of research I gave up and ended up using some simple TCP-based remote launcher a co-worker made.

Feeling accelerated?

The platform was for sure the most exciting part. Here’s how I did it.

The idea with mobile platforms is to simulate the accelerations and decelerations by tilting the platform. This changes our center of gravity and tricks your inner ear into thinking that you’re on the  go.

The best way of dealing with these platforms is the Classical Washout filter, mostly used in flight simulators. To put it in simple words it’s a PID that transforms aircraft accelerations into motion cues that can be directly fed to the platform. It also does tilt coordination. Its objective is to orient the gravity vector so the rider feels a sustained acceleration while the visual display remains the same.

We had this filter and the library sending packets to the platform implemented in old Borland C++ which I had to port to Visual Studio. Once the port was done I had to adjust the filters thresholds that were stored in plain text files using a software “Platform simulator” and then fine-tune them in the real thing to match my taste.

The filter takes the angular velocity and the specific forces for the coaster train. For the angular velocities someone pointed me to the Darboux vector.

Now that all the explanations are done, let’s watch it in action!

Result

Conclusions

As you can see in the video the platform doesn’t rock you so bad (I wish it did :-D). I had to further adjust the Washout thresholds to make it a tougher ride.

It would also have been cool to simulate the track shaking and do better graphics (I didn’t rewrite the OpenGL part except for a few details, so that’s pure RC2K graphics).

It took me 1 and a half weeks.

Of course, the platform has mechanical limits and it can’t play a 360º loop, cobra rolls or corkscrews but it does its best.

I wish I had implemented a run counter since it quickly become one of our best valued demos and a mandatory one for visitors. I had spent hours running the demo for large groups of visitors from other universities and others.

Even the rector of the university ‘s wife had a ride at a special event the last year !! Amazing

Special thanks

Props to Ignacio Garcia for his advice and to M.A. Gamón for his support on the Washout filter.