Meshdrawer invisible when moving to the side

Hi! I’ve spent many time trying to figure out what is going on, and nothing I’ve tried worked.

I am trying to draw a laser path using meshdrawer. Everything seems to work at first, but I’ve noticed that when I move my ship to the side, the path disappear.

Here is what I am doing, adapted for easier understanding:

generator = MeshDrawer()
generator.setBudget(20)
generatorNode = generator.getRoot()
generatorNode.reparentTo(render)
generatorNode.setDepthWrite(False)
generatorNode.setTransparency(True)
generatorNode.setTwoSided(True)
generatorNode.setTexture(loader.loadTexture("assets/sprites/laser.png"))
generatorNode.setTexRotate(TextureStage.getDefault(), 0)
generatorNode.setBin("fixed",0)
generatorNode.setLightOff(True)

taskMgr.add(drawLaser, 'drawLaser', extraArgs=[laser], appendTask=True)

def drawLaser(laser, task):
    generator = laser['GENERATOR']
    color = Vec4(1,1,1,1)
    frame = Vec4(1,1,1,1)

    laser['TRAIL_PATH'] += [entity['NODE'].getPos()]
    if len(entity['TRAIL_PATH']) >= 20:
        del entity['TRAIL_PATH'][0]

    head_position = laser['TRAIL_PATH'][-1]
    tail_position = laser['TRAIL_PATH'][0]

    generator.begin(base.cam, render)
    generator.linkSegment(head_position,frame,1,color)
    generator.linkSegment(tail_position,frame,1,color)
    generator.linkSegmentEnd(Vec4(1,1,1,1),color)
    generator.end()
    return task.cont

What I get with that is a working laser, but as I said, if I move my camera up,down,left or right too much (not that much), the meshdrawer become invisible. When I move back to my original position, it reappear. If I make a mesh with constant position:

    generator.begin(base.cam, render)
    generator.linkSegment(Vec3(0,1000,0),frame,1,color)
    generator.linkSegment(Vec3(0,0,0),frame,1,color)
    generator.linkSegmentEnd(Vec4(1,1,1,1),color)
    generator.end()

I can move on the side as much as I want, and the trail still appear. Another way to see it is that if someone is by my side and fire a laser in the direction I am looking, the trail is invisible to me.

So a moving laser (meshdrawer) disapear when moving on the side, but not a fixed one.

Help would be much appreciated!

To make myself more clear:

The camera is a little to left side of the spawning point of the laser :


And if move a liiiiiittle more to the left, the trail disappear:


In both cases, the laser path is straight forward. In a vector interpretation, laser_path = (0,1,0); my position = (-x,0,0)
And you can understand that the trail should still visible!!! (at least until I get so much to the left that the path of the laser doesn’t go by my screen, which is not the case).

Again, if I draw a fixed path, (0,0,0) to (0,1000,0), this problem doesn’t occur:


Sorry for the big post, I want to make sure that my problem is clear!

I’ve made a sample program that display the behaviour:

from direct.showbase.ShowBase import ShowBase
from panda3d.core import WindowProperties, loadPrcFileData
from panda3d.bullet import *
from panda3d.core import *
from math import *
global ENTITIES
ENTITIES = {}
global ENTITY_ID
ENTITY_ID = 0
TEXTURE_PATH = "laser.png"

class DEMO(ShowBase):

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

        self.setFrameRateMeter(True)
        wp = WindowProperties()
        wp.setSize(1280, 720)
        wp.setFullscreen(False)
        self.win.requestProperties(wp)
        self.disableMouse()
        self.setBackgroundColor((0, 0, 0, 1))
        self.accept('f6', self.changeCamera)
        self.bullet_world = BulletWorld()
        self.bullet_world.setGravity(0,0,0)
        taskMgr.add(self.update, 'fire')

        #TASK THAT FIRE LASER
        taskMgr.doMethodLater(0.5, self.fire, 'fire')

        #GENERATOR FOR THE FIXED LASER
        generator = MeshDrawer()
        generator.setBudget(1000)
        generatorNode = generator.getRoot()
        generatorNode.reparentTo(render)
        generatorNode.setDepthWrite(False)
        generatorNode.setTransparency(True)
        generatorNode.setTwoSided(True)
        generatorNode.setTexture(loader.loadTexture(TEXTURE_PATH))
        generatorNode.setTexRotate(TextureStage.getDefault(), 0)
        generatorNode.setBin("fixed",0)
        generatorNode.setLightOff(True)
        #TASK THAT DRAW THE FIXED LASER
        taskMgr.add(self.drawFixedLaser, 'drawFixedLaser', extraArgs=[generator], appendTask=True)

        
    def changeCamera(self):    
        self.oobe()

    def update(self, task):
        dt = globalClock.getDt()
        time = globalClock.getFrameTime()
        self.bullet_world.doPhysics(dt, 50,1./180.)      
        self.camera.setPos(sin((time*2))*12-6,0,0)
        return task.cont

    def fire(self, task):
        global ENTITY_ID
        global ENTITIES
        global TEXTURE_PATH
        bullet_vector = Vec3(0,500,0)

        shape = BulletBoxShape(Vec3(0.5, 0.5, 0.5))
        body = render.attachNewNode(BulletRigidBodyNode(str(ENTITY_ID)))
        body.node().addShape(shape)
        body.node().setMass(0.02)
        body.node().setLinearVelocity(bullet_vector)
        body.setPos(4,20,0)
        self.bullet_world.attachRigidBody(body.node())
   
        #GENERATOR FOR THE MOVING LASER
        generator = MeshDrawer()
        generator.setBudget(1000)
        generatorNode = generator.getRoot()
        generatorNode.reparentTo(render)
        generatorNode.setDepthWrite(False)
        generatorNode.setTransparency(True)
        generatorNode.setTwoSided(True)
        generatorNode.setTexture(loader.loadTexture(TEXTURE_PATH))
        generatorNode.setTexRotate(TextureStage.getDefault(), 0)
        generatorNode.setBin("fixed",0)
        generatorNode.setLightOff(True)
        #MOVING LASER DRAW TASK
        taskMgr.add(self.drawLaser, 'drawLaser_%i' % ENTITY_ID, extraArgs=[ENTITY_ID], appendTask=True)

        ENTITIES[ENTITY_ID] = {'NODE':body,'TRAIL':generator, 'TRAIL_PATH':[body.getPos()]}
        ENTITY_ID += 1

        return task.again

    def drawLaser(self, entity_id, task):
        entity = ENTITIES[entity_id]
        generator = entity['TRAIL']
        color = Vec4(1,1,1,1)
        entity['TRAIL_PATH'] += [entity['NODE'].getPos()]

        #MOVING BULLET - LINE DISAPPEAR
        generator.begin(base.cam,render)
        generator.linkSegment(entity['TRAIL_PATH'][-1],Vec4(1,1,1,1),1,color)
        generator.linkSegment(entity['TRAIL_PATH'][0],Vec4(1,1,1,1),1,color)
        generator.linkSegmentEnd(Vec4(1,1,1,1),color)
        generator.end()

        if len(entity['TRAIL_PATH']) >= 50:
            del entity['TRAIL_PATH'][0]

        return task.cont

    def drawFixedLaser(self, generator, task):
        color = Vec4(1,1,1,1)

        #FIXED LASER - LINE DOESN'T DISSAPEAR
        generator.begin(base.cam,render)
        generator.linkSegment(Vec3(0,5000,5),Vec4(1,1,1,1),1,color)
        generator.linkSegment(Vec3(0,0,5),Vec4(1,1,1,1),1,color)
        generator.linkSegmentEnd(Vec4(1,1,1,1),color)
        generator.end()

        return task.cont

game = DEMO()
game.run()

You should only have to input your texture path to make it work.

When making this demo program, I’ve noted that if I draw the fixed laser only one time out of two, the fixed laser start disappearing on the side too. Weird.
Am I not understanding what is the meshDrawer? Should I use something else?

Thanks!

Simpler version of the drawLaser function:

    def drawLaser(self, entity_id, task):
        entity = ENTITIES[entity_id]
        generator = entity['TRAIL']
        color = Vec4(1,1,1,1)
        entity['TRAIL_PATH'] += [entity['NODE'].getPos()]

        #MOVING BULLET - LINE DISAPPEAR
        generator.begin(base.cam,render)
        startY = entity['TRAIL_PATH'][-1][1]
        endY = startY - 5
        generator.linkSegment(Vec3(0,startY,0),Vec4(0,0,1,1),1,color)
        generator.linkSegment(Vec3(0,endY,0),Vec4(0,0,1,1),1,color)
        generator.linkSegmentEnd(Vec4(0,0,1,1),color)
        generator.end()

        return task.cont

It’s driving me crazy! I’ve many many test and nothing worked…
As soon as the meshdrawer is on movement, it stop working.
The only thing that make the “disappearing point” further from the center is when I increase the segment size (endY = startY -100). And yet, the problem persist. My guess is that the inside geometry is too small? But I have no idea how to verify this and the API didn’t offer much help on that regard.

Some help would be much appreciated!

Thanks!

Although I couldn’t say where it’s going wrong, I think I do know what is going wrong: somehow, the laser geometry seems to get moved outside of its bounds, causing it to get culled so it is no longer rendered.

A quick fix for this is to simply set an OmniBoundingVolume on the generatorNode, so the relevant part of your previous code becomes:

        #GENERATOR FOR THE MOVING LASER
        generator = MeshDrawer()
        generator.setBudget(1000)
        generatorNode = generator.getRoot()

        # set an OmniBoundingVolume on the generatorNode to prevent it from being culled
        generatorNode.node().setBounds(OmniBoundingVolume())
        generatorNode.node().setFinal(True)

        generatorNode.reparentTo(render)
        generatorNode.setDepthWrite(False)
        generatorNode.setTransparency(True)
        generatorNode.setTwoSided(True)
        generatorNode.setTexture(loader.loadTexture(TEXTURE_PATH))
        generatorNode.setTexRotate(TextureStage.getDefault(), 0)
        generatorNode.setBin("fixed",0)
        generatorNode.setLightOff(1)
        #MOVING LASER DRAW TASK
        taskMgr.add(self.drawLaser, 'drawLaser_%i' % ENTITY_ID, extraArgs=[ENTITY_ID], appendTask=True)

But I’m not sure you should consider this to be a real solution, since it might reduce the performance of your game unnecessarily. Hopefully someone more knowledgeable will be able to figure out why it’s happening in the first place.

On a side note, I changed setLightOff(True) to setLightOff(1), since the parameter is not a boolean, but a priority to turn it off at a lower level.

Thank you so much!

Right now I don’t think that it could lead to any performance issue (small scale of the game), so I’ll use your fix until a better solution is found!

Thanks again!