Laser Beam using Mesh Drawer Won't Render?

here is my code:

        generator = MeshDrawer()
        generator.setBudget(1000)
        generatorNode = generator.getRoot()
        generatorNode.reparentTo(self.render)
        generatorNode.setDepthWrite(False)
        generatorNode.setTransparency(True)
        generatorNode.setTwoSided(True)
        generatorNode.setTexture(self.loader.loadTexture("/Users/38167/PycharmProjects/viren/venv/wood.jpg"))
        generatorNode.setBin("fixed", 0)
        generatorNode.setLightOff(True)

        def drawtask(taks):
            generator.begin(base.cam, render)
            t = globalClock.getFrameTime()
            generator.begin(base.cam, self.render)
            generator.end()
    
            return taks.cont

        self.taskMgr.add(drawtask, "meshdrawer task")

I don’t know why it doesn’t want to spawn/render in the map. Can someone please help me, I’m so confused?

Thanks!

P.S if you see another post by me like this one but it got deleted, it’s because I messed up with the first post. Don’t worry it’ll delete in 24 hours😅

As far as I see in your code above, you’re not generating any geometry: you “begin” the MeshDrawer (twice, actually), get the frame-time, and then “end” the MeshDrawer without doing anything with it.

If you look at the MeshDrawer API, you should see a variety of methods for “drawing” various bits of geometry. (For a simple laser, the “segment” method might be a good choice.) These are used between “begin” and “end” to generate your intended geometry, I believe.

ok so I tried editing it and got this

self.accept("shift", self.handleShift, [1])
self.accept("shift-up", self.handleShift, [0])

    def handleShift(self, arg):
        if arg == 1:
            source = self.pandaActor
            target = self.plant
            self.createBeam(source, target)
        else:
            self.deleteBeam()

    def createBeam(self, source, target):
        self.generator = MeshDrawer()
        self.generator.setBudget(1000)
        self.generatorNode = self.generator.getRoot()
        self.generatorNode.reparentTo(self.render)
        self.generatorNode.setDepthWrite(False)
        self.generatorNode.setTransparency(True)
        self.generatorNode.setTwoSided(True)
        self.generatorNode.setTexture(self.loader.loadTexture("/Users/38167/PycharmProjects/viren/venv/wood.jpg"))
        self.generatorNode.setBin("fixed", 0)
        self.generatorNode.setLightOff(True)
        self.taskMgr.add(self.drawBeam, "drawBeamTask", extraArgs=[source, target], appendTask=True)

    def drawBeam(self, source, target, task):
        t = globalClock.getFrameTime()
        self.generator.begin(base.cam, self.render)
        self.generator.end()

        return task.cont

    def deleteBeam(self):
        self.generatorNode.removeNode()
        self.taskMgr.remove("drawBeamTask")

still when I press shift it does nothing. Can you please provide insight?

Thank you!

You’re still not actually calling any of the mesh-generation methods that I mentioned in my previous post, as far as I see. ^^;

(I will note, by the way, that this looks like a less-efficient approach than you had previously. Previously, it looked like you were creating your MeshDrawer just once and using it as called for. Now you’re creating it every time you press “shift”, and destroying it every time you release “shift”.

(If you want your laser to not be drawn when “shift” is no longer held, you could simply hide the MeshDrawer NodePath, I believe.)

That said, this inefficiency may not be a major issue, depending on how your game performs otherwise, and the sort of hardware on which you intend it to run.)

Ah yes sorry about the approach, also this is my first time using mesh drawers could you maybe provide a little example of a mesh generation method and how to implement it into my code?

Thanks for the help🙏

I did. I linked to the API documentation, told you where to place the code, and even recommended a method to consider for use as a laser. ^^;

PS: Don’t worry about your code not being wonderfully efficient! If it works for you, it works! I just want to make sure that you’re aware of the potential efficiency, so that you can learn, I think.

there are several segments, cross segment, link segment, segment, uneven segment. Which one are you referring to? That’s what I meant sorry

Ah, I see! Fair enough.

Well, read through their descriptions, and tell me which you think is best suited to rendering a laser.

PS: To be clear, I don’t mean that to be snarky. (And sorry if it comes across as so!) I just want to encourage you to improve at reading an API and drawing conclusions from it. A minor learning opportunity, so to speak.

crossSegment (const LVector3 start, const LVector3 stop, const LVector4 frame, float thickness, const LVector4 color)
Draws a segment a line with a thickness. More…

linkSegment (const LVector3 pos, const LVector4 frame, float thickness, const LVector4 color)
Stars or continues linked segment. More…

segment (const LVector3 start, const LVector3 stop, const LVector4 frame, float thickness, const LVector4 color)
Draws a segment a line with a thickness. More…

unevenSegment (const LVector3 start, const LVector3 stop, const LVector4 frame, float thickness_start, const LVector4 color_start, float thickness_stop, const LVector4 color_stop)
Draws a segment a line with different thickness and color on both sides. More…

I think that’s all of them, maybe just the segment? IDK

PS you’re not snarky in any way, don’t worry about it. I’m a total nub at this lel

Exactly right! :slight_smile:

“Segment” is, I think, a good way of drawing a simple, straight “line” with a texture applied. It even has a billboarding effect that tries to keep its flat side visible to the camera, I believe. These points make it quite suitable, I feel, for drawing a laser.

Ah, I’m glad. Thank you for reassuring me. :slight_smile:

So would I do?

self.generator.segment()

and also where?

Well, you would want to give it appropriate parameters to define the laser-beam–I’m not sure that it’ll even run with no parameters.

As I said, I believe: between the calls to MeshDrawer’s “begin” and “end” methods.

Ok thanks got it work! :laughing::pray::stuck_out_tongue:

Excellent–I’m glad that you did! :slight_smile:

One question though, right now the source of the beam is from the panda, and the target is always the other actor. This won’t make the game fun if you can automatically kill the actor, my question is how to make it so that the source is the panda but the target is just where the panda is facing. So you actually have to aim to direct the beam at the other actor.

Thanks🙏!

One simple way might be to attach a NodePath to your player-character, place it ahead of the character, and then target that.

any other way? Sorry if I sound snarky or anything, I’m just wondering if there is a easier way that I can do with my code. Also wouldn’t that just create a beam directed up?

@Thaumaturge

Well, the easiest way is probably to not use a second object as your target-point, and just have your code construct the beam in a forwards-facing direction.

As to the direction of the beam in my suggestion above, that might somewhat depend on your code. However, if what you have is code that directs a beam from the player-character to a target-object, and if you place a target-NodePath ahead of the player-character, then the beam should end up pointing ahead of the character, it seems to me.

(Unless you thought that I meant overhead, it occurs to me? For the sake of clarity, in case that’s the source of the confusion, I meant “ahead”, i.e. “placed in front of”.)

If I’m not wrong I believe there are several pandanodes, can I at least know which one are you referring to?

I don’t want to intrude or waste any time of yours, please answer when you can.

thank you!

Don’t worry about it: if I don’t have time to answer, I likely won’t.

I’m… not quite sure of what you mean when you ask which PandaNode I’m referring to.

To start with, PandaNodes (that is, nodes) are separate things from NodePaths, albeit that the two are connected.

But more to the point, what I’m suggesting is that you create an empty NodePath (with a PandaNode in it) to serve as your “target”. Something like this:

# For the sake of the example, let's assume that your player-character's model
# is stored in the variable "self.myActor"; modify as appropriate to your code!

# Create a NodePath pointing to an empty node named "target"
self.targetNP = NodePath(PandaNode("target"))

# Attach the target NodePath to the player-character's model
self.targetNP.reparentTo(self.myActor)

# Place the target NodePath relative to the player-character's model
# Setting a NodePath's position without any additional arguments
# sets its position relative to its parent. In this case, it's a child of
# the player-character's model, and so this sets its position relative
# to the player-character's model.
self.targetNP.setY(5)
# (Adjust the distance as appropriate for your code)