Train Simulator, Realistic Graphics & Physics

Hi,

I want to program a Train Simulator, with realistic graphics. So I installed Render Pipeline and played around with it, but my computer couldn’t handle it XD

So my first question is: Do I really need to use Render Pipeline for realistic graphics, or can I just use some specific filters, and if so, which filters?

I didn’t actually program anything related to the simulator yet, I first wanna plan out things, so now I’m running into the second issue: Because I would like to have multiple train cars, I considered connecting them with Bullet Spherical Constraints, but I don’t know how I can implement the bogies or however the things that have the actual train “wheels” attached to them, and the car ontop of them. Would it be possible to have the two bogies moving on the Motion Path and the car ontop ot them? Or do I even need to use Bullet?

So, to sum things up:

  1. How can I create realistic graphics/lighting without having performance issues, but maintaining adjustable sunlight (<-So I can’t bake lightmaps, or maybe one lightmap for every hour?)
  2. Do I need to use Bullet to implement the rolling of the cars and locomotive, so the overall train? Is it even possible to have physics while being on a fixed MoPath?

To address your first question, I think that the answer depends on just what level of realism is sufficient. I daresay that you could produce reasonably realistic graphics without using the Render Pipeline; the main constraints are, I think, the capabilities of your system and the amount of work that you want to spend on the matter.

To clarify: you can likely do quite a lot with Panda’s shader generator and the use of appropriate textures, and perhaps go further still by writing your own custom shaders–presuming that your system is up to everything that you want it to do.

1 Like

I think the Bloom & Ambient Occlusion filters would be a good solution. If you can write shaders, I’d definitely give it a try, as Thaumaturge already said.

For the physics, I’d first try out playing with the method ‘setPlayRate’ of the MopathInterval, maybe someone can help you with the formulas of calculating the speed of the train based off of it’s throttle & uphill & downhill aspects.

If you have more questions, I’d recommend you just post them here, maybe I or somebody else can help you further if you have specific questions when you actually started programming the simulator :slight_smile:

1 Like

If your train models are using glTF format or can be converted to glTF, you can also use panda3d-simplepbr instead of RP which give a nice rendering yet can run on a potato.

3 Likes

Thanks, simplepbr is great!

However though, I’m already running into the first issue, I created a simple motion path in Blender, I exported it with YABEE, everything worked fine, this is my code, i’m testing out the motion path:

from direct.showbase.ShowBase import ShowBase
from direct.directutil import Mopath
from direct.interval.MopathInterval import *
import simplepbr


class Game(ShowBase):

    def __init__(self):
        ShowBase.__init__(self)

        simplepbr.init()
        
        self.moPath = Mopath.Mopath()
        self.moPath.loadFile("models/mopath.egg")

        self.sphere = self.loader.loadModel("models/misc/sphere")
        self.sphere.reparentTo(self.render)

        self.interval = MopathInterval(self.moPath, self.sphere)
        self.interval.loop()


app = Game()
app.run()

But when I execute it, the sphere weirdly moves fast on one side of the path, but on the other side it passes by slowly, as it should be, when I play the animation in blender, the sphere also behaves weirdly, can anyone explain this behavior, and how to fix it?

Here the motion path as an .egg and a .blend:
http://www.mediafire.com/file/orfx6f0behdsuat/mopath.egg/file
http://www.mediafire.com/file/b2cc2unocfeiz04/mopath.blend/file

Pandas motion path implementation doesn’t support cyclic paths. When it reaches the last point on that path, it will simply jump to the first one as it’s set to loop. One way to fix this is to simply move the last point of the path to the exact same position as the first point. You may need to move the dots a bit around to resemble the exact same path that way. The best places to set the start and end point would probably be a straight line in the path and not somewhere in a curve to retain smooth movements.

Ok, I decided to use the bullet physics engine for the train, do you think I should use a BulletBoxShape and apply force to it, or a BulletVehicle?

That probably depends on how much control you want to have over every single part. (As a sidenote, I’m not that fond of bullet, but here are my guesses) With the BulletVehicle you probably get a lot of things right out of the box like wheels, suspension, etc, but it may limit you in special cases. On the other hand, with the Box shape, you need to develop those things yourself, but you have control over wether they should actually be physically calculated or not.
You may want to try build a very small prototype and see what fits your needs best.

Also if you want to move your train along the mopath, I think there was a way to define the speed it moves but I just don’t remember from the top of my head.

2 Likes

I’ll use the BulletVehicle, now I don’t really know if Bullet is written completely in C, but if not, maybe I can make a new class that inherits from BulletVehicle and then overwrite some functions.
However though, if Bullet is completely written in C, maybe I’m gonna end up making a copy of the Bullet source, edit it a bit, and then recompile it by myself.

EDIT:
If the recompiling doesn’t work, I’ll analyze the C source code of BulletVehicle, translate it to Python, (if that’s fully possible) and then modify it.
If that’ll be too laggy (because Python), I’ll probably use the Box Shape, but I’m kinda scared of that to be honest :laughing:

EDIT 2:
The best case scenario would of course be that BulletVehicle gives me enough control.

Bullet is written in C++. You cannot extend it from Python.

1 Like

Ok, so there are much more physics involved in the train than I thought, I’m researching on train physics, now I’m not even sure anymore if I’ll even use Bullet or any physics engine at all, it’s much more complex than I thought at first, I’m also digging through OpenRails source code, and I’m basically collecting formulas and data that I need in order to calculate how the train has to move.
So, I know this is crazy, it’s such a small project and I’m probably thinking way too big right now, but does anyone want to join me and help program the simulator and research?

Yes! That’s a great idea!
I’d really like to join you!

But how can we work together?
Maybe open a Discord Server?

I created a Discord Server:
Here’s the link:


Does anyone else want to join us?

Does anyone have an idea how to implement the bogies?
So this is the idea we’ve come up with:
Make two seperate BulletVehicles for each bogie, and then put the locomotive itself on top.
But the problem is that there are no bearings, so we can’t connect the locomotive to the BulletVehicles that would be the bogies.
How would you approach it?
Or maybe make a ConeTwistConstraint and limit it’s rotation so that it can only rotate vertically?

I’m running into a weird issue when trying to just simply view an .egg file, it gets displayed normally, but as soon as I place a light, the model disappears, no matter where I place the light.
This is the source code:

from direct.showbase.ShowBase import ShowBase
from panda3d.core import PointLight


class EggViewer(ShowBase):

    def __init__(self):
        ShowBase.__init__(self)

        self.model = self.loader.loadModel("bogie-0")
        self.model.reparentTo(self.render)

        self.accept("a", self.enableLight)

    def enableLight(self):
        l = PointLight("pl")
        lNP = self.render.attachNewNode(l)
        lNP.setPos(1, 1, 1)
        self.render.setLight(lNP)


app = EggViewer()
app.run()

Here’s the .egg file:
http://www.mediafire.com/file/zumzo44kdemn0lm/bogie-0.egg/file

Hmm… I see the same in PView, too. (Unless I activate per-pixel lighting, in which case it comes back.)

However, if I ask Panda to display transparency, I see that your model appears to indeed be transparent. Thus what I think is happening is that you have full transparency applied in some way–perhaps in your material colours–and that when lighting is applied and the material takes effect your model thus becomes invisible.

1 Like

Thanks!
It worked by just changing the Alpha Channel of the materials in the egg, but I have no clue why it got exported with Alpha 0, the transparency checkmark wasn’t even checked in the material editor in Blender.

1 Like

Ok, so I got the locomotive running now, I implemented the bogies as BulletVehicles, and connected them via BulletBoneTwistConstraints to the locomotive itself.
Does anyone know what the units of measurement for the applyEngineForce and setBrake methods of BulletVehicle are?

EDIT:
And somehow, if the locomotive doesn’t move for about 5 seconds, the BulletDebugNode marks it as green and red, if I then apply force to the engine, it’s not moving anymore.

You should, if I recall correctly, be able to indicate to Bullet that the physics body/bodies in question shouldn’t be “put to sleep” (i.e. disabled). In the case of the BulletBodyNode class, I think that this is done by calling “setDeactivationEnabled(False)”; I’m not sure of how the vehicle controller is set up, and thus how this is achieved there.

1 Like

Thanks, setDeactivationEnabled, works.

1 Like