Colour/transparency of object not loading in scene

I am trying to load my 'ocean' model into my scene. Right now, i have some very basic code:

from direct.showbase.ShowBase import ShowBase

class game(ShowBase):
    def __init__(self):
        super().__init__()
        path = 'ocean.something'
        ocean = self.loader.loadModel(path)
        ocean.reparentTo(self.render)

code = game()
code.run()

Using the .glb and .stl formats, the model would load in completely white. When I asked ChatGPT (never a good idea), it could only say things I could’ve messed up and give me some code that didn’t work.

Since I’m considered a ‘new user’, I can’t upload the file.

I am using a method of making my model transparent (this one) and I am giving it colour.

Also, how do you make wasd controls without sin, cos, tan etc. Is there a camera.forward() or something similar?

As to your first question, I don’t have the answer offhand, but I do think that I’ve seen similar threads in the past–you might perhaps find an answer by searching the forums (if you haven’t done so already).

As to your second question, there are actually a few ways to do that, I do believe! Let me outline two:

  1. You can set a NodePath’s position relative to a given NodePath–including itself. And by setting a NodePath’s position relative to itself, you set its position within its own coordinate space, with the y-axis being the “forward” axis.

For example:

# Set a NodePath's position to be a position (3, 0, 1) relative to
#  another NodePath
self.myNodePath.setPos(self.someOtherNodePath, 3, 0, 1)

# Set a NodePath's position to be 1 unit in its "forward" direction.
self.myNodePath.setY(self.myNodePath, 1)

# Set a NodePath's position to be 2 units in its "forward" direction
#  and 1 unit in its "left" direction
self.myNodePath.setPos(self.myNodePath, -1, 2, 0)

However! Do note that the NodePath’s coordinate space includes things like its scaling factor (including any applied by nodes above it in the scene graph), which can affect the results of such operations!

  1. You can extract a NodePath’s “forward”, “right”, and “up” vectors, and use those.

For example:

# First, get the NodePath's orientation as a quaternion.
#  (If you're not familiar with quaterions, don't worry--
#   for this process you don't have to be.)
quat = self.myNodePath.getQuat()

# Then extract the relevant vector(s) from that quaternion
forward = quat.getForward()
#right = quat.getRight()
#up = quat.getUp()

# Get the NodePath's current position
currentPos = self.myNodePath.getPos()

# And finally, set the NodePath's position to be 2 units
#  in the "forward" direction
self.myNodePath.setPos(currentPos + forward * 2)

Note of course that, in both of these approaches, the result takes into account the full orientation of the NodePath. As a result, if your NodePath is tilted up, for example, the “forward” direction will likely be tilted up. If this is undesirable, you can perhaps use multiple parented nodes to separate out things like “horizontal turning” from “looking up and down”, allowing you to get a horizontal “forward” vector from the former.

Thanks. I’ll use the second method. Correct me if I’m wrong, but I should be able to use GlobalClock.getAverageFrameRate() to help me deal with changes in the frame rate, although, it’s not an entirely stable speed. I think it would be better to use the previous frame time. What function can I call to get that?

Also, after doing what this post says to do, I got an error. After looking back through the traceback, I realised I had to move the ‘.bin’ file into the project. After that, same issue as i was having before; it would load, but not with colour or transparency. Could you please tell me how to add transparency to a model in the code? I already know how to add colour.

As you say, I think that the time since the last frame is likely better than the average time.

The time since the last frame can be had from the default ClockObject, and specifically from its “getDt()” method–like so:

# If we're in a class derived from ShowBase:
timeSinceLastFrame = self.clock.getDt()

# Or, if we're not in such a class, but have access to
#  an instance of ShowBase (or a sub-class thereof):
timeSinceLastFrame = showBaseObject.clock.getDt()

(“Dt” standing for “Delta-time”–that is, the amount of time between two points–I believe.)

(There’s also a global variable that gives direct access to the clock, but I believe that the engine is trying to move away from such things.

And finally, you could–I think–access the same clock-object directly from the “ClockObject” class by calling “getGlobalClock()”.)

If the only problem is that the model doesn’t have the “transparency” flag set, then you should be able to do so as follows:

myNodePath.setTransparency(True)

(There are other values that can be given than “True”, which I think are described in the manual. For basic transparency, however, “True” should likely enough suffice.)

If that doesn’t work, then the problem I imagine lies elsewhere. In that case, I’m not sure of what might be the issue–I don’t really use the “glTF” format myself–and so leave the matter to others!

You need a light source active to be able to see materials.

1 Like

Thanks. I’ll try and figure out ambient light.

Probably the last thing; is there a way to give a ‘fog’ effect when I’m below a certain y level, like in minecraft, so that it actually feels like you’re underwater?

Hmm… My first thought would be to use a custom shader, I think. I don’t know offhand whether there’s any built-in feature that would do this.

(There’s a standard fog-effect, of course, but I don’t know whether it might support differentiation by height…)

If there’s a way to do it without a config.prc file, I should just be able to check the y level in my update() function and then enable/disable it, and if that’s too hard on the frames then I store whether I was in the water last frame in a variable and only execute the function if I am not in the water and the variable says I was last frame, of I am in the water and the variable says I was not last frame.

Ah, I see–that wouldn’t allow you to have the fog depict a state of being partway-under the water (i.e. with fog covering only part of the screen), but that should, I think, allow you to depict a state of being entirely submerged or entirely out of the water, indeed.

But how do I do it?

Well, you’ve outlined the logic yourself; the fog itself can I daresay be handled as described in the manual, here:
https://docs.panda3d.org/1.10/python/programming/render-attributes/fog

When I apply the effect everything turns grey - I did try changing the background colour like it said.

1 Like

What values did you apply to it? It sounds like your fog may be so intense that it’s preventing you from seeing anything else.

(A quick way to check might be to change the fog colour to something that’s clearly different–bright green, perhaps–and see whether everything turns that colour.)

i applied blue (like water) and put in loads of different valeus like 1, 0.5, 0.2, 0.1, and 0.0001. Also, when i said ‘everythong’, i meant my models that i loaded into the scene; it didn’t impact the background.

also click on my profile my domain is beatiful and it definitely exixts. i call this post a further question related to the topic. u dont even need to click the website.

Ah, that’s very strange! Based on a quick test on my side, fog seems to work as expected: I can apply a green colour to it, and I get a green fog-like effect on objects in the scene.

Here’s a little test-program–perhaps try it on your machine and see whether you have the same problem with it as with your own program:

from direct.showbase.ShowBase import ShowBase

from panda3d.core import Fog

class Game(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
 
        self.model = loader.loadModel("untitled_box") # <-- Replace file-name!
        self.model.reparentTo(render)
        self.model.setY(5) # <-- Adjust as appropriate
        self.model.setHpr(45, 45, 45)

        fog = Fog("kitten")
        fog.setColor(0, 1, 0)
        fog.setExpDensity(0.1)
        render.setFog(fog)


app = Game()
app.run()

If it does show the same problem, then there may be an extraneous issue of some sort. If it doesn’t, then perhaps there’s something in your program that is clashing with the fog-effect.

[edit]
Also, what a convincing website! Wow! :stuck_out_tongue_winking_eye:

i would probably get that website if .com was free

1 Like

The entire code I have right now:

from panda3d.core import *
loadPrcFile('config/config.prc')
from direct.showbase.ShowBase import ShowBase

class game(ShowBase):
    def __init__(self):
        super().__init__()
        self.accept('escape', quit)

        path = 'assets/ocean.glb'
        global keymap
        keymap = {
            'w' : False,
            's' : False
        }
        for i in range(10):
            for j in range(10):
                ocean = loader.loadModel(path)
                ocean.setScale(1000)
                ocean.setColor(0, 0, 1)
                ocean.setPos(i * 600000, j * 600000, 0)
                ocean.setTransparency(True)
                ocean.reparentTo(render)
        # self.cam.setHpr(90, 0, 0)
        light = DirectionalLight('light')
        pnlp = render.attachNewNode(light)
        render.setLight(pnlp)

        self.cam.setHpr(0, -20, 0)

        def startforward():
            keymap['w'] = True
        def stopforward():
            keymap['w'] = False
        def startbackward():
            keymap['s'] = True
        def stopbackward():
            keymap['s'] = False

        def forward():
            quat = self.cam.getQuat()
            forward = quat.getForward()
            currentPos = self.cam.getPos()
            self.cam.setPos(currentPos + forward * 500000 * self.clock.getDt())

        def backward():
            quat = self.cam.getQuat()
            forward = quat.getForward()
            currentPos = self.cam.getPos()
            self.cam.setPos(currentPos + forward * -500000 * self.clock.getDt())

        def update(task):
            global keymap
            if keymap['w']:
                forward()
            if keymap['s']:
                backward()
            if self.mouseWatcherNode.hasMouse():
                x = self.mouseWatcherNode.getMouseX()
                y = self.mouseWatcherNode.getMouseY() # this code was just me testing things
            return task.cont

        self.cam.setPos(0, 0, 10000)

        self.accept('w', startforward)
        self.accept('w-up', stopforward)
        self.accept('s', startbackward)
        self.accept('s-up', stopbackward)

        self.taskMgr.add(update)

        # props = WindowProperties()
        # props.setCursorHidden(True)
        # props.setMouseMode(WindowProperties.M_relative)
        water = Fog("Fog Name")
        water.setColor(0.2, 0.2, 1)
        water.setExpDensity(0.1)
        # render.setFog(water)
        # self.setBackgroundColor(0.2, 0.2, 1)
        # self.win.requestProperties(props)
        self.camLens.setFar(10000000)

code = game()
code.run()

with fog (after moving backwards a bit):

without for (again, after moving backwards a bit, also you can see a slight issue with the texture):

Okay, so based on a quick test, it looks like the fog works perfectly fine–it’s just way too strong for the (huge) scale on which you’re working. Try, for example, an “ExpDensity” of 0.00001.