There is always a problem with the position of the drawing point

As shown in the figure and the program, why did I set up to draw points at the position of the panda, but it appeared elsewhere?

import sys
import random
from pandac.PandaModules import *
from direct.directbase import DirectStart, -216.88, 255.92), -50.13, -0.36)
terrain = loader.loadModel('world')
unit = loader.loadModel("panda")
ls = LineSegs('')
ls.setColor(Vec4(1, 0, 0, 1))
ls.moveTo(0, 0, 100)
ls.drawTo(0, 0, -20)
unit4 = unit.attachNewNode(ls.create())
ls.setVertexColor(0, Vec4(1, 0, 0, 0))
veilColor = 0.2  # the veil/fog color
imgSize = 32
img = PNMImage(imgSize, imgSize)
brush = PNMBrush.makeSpot((1,1,1,1), 3, True)
painter = PNMPainter(img)
tex = Texture()
minb, maxb = terrain.getTightBounds()
dim = maxb-minb
maxDim = max(dim[0], dim[1])
scale = 1/maxDim
center = (minb+maxb)*.5
veilTS = TextureStage('')
terrain.setTexGen(veilTS, RenderAttrib.MWorldPosition)
terrain.setTexScale(veilTS, scale)
terrain.setTexOffset(veilTS, -.5-center[0]*scale, -.5-center[1]*scale)
terrain.setTexture(veilTS, tex)
def move(task):
    dt = globalClock.getDt()
    task.updateDt += dt
    unit.setH(unit, random.uniform(-15, 15))
    unit.setY(unit, 20*dt)
    if not (minb[0] < unit.getX() < maxb[0] and minb[1] < unit.getY() < maxb[1]):
       unit.setH(unit, 180)
       unit.setY(unit, 40*dt)
    if task.updateDt > .2:  # fog update interval, in second
       task.updateDt = 0
       x = unit.getX()
       y = unit.getY()
       painter.drawPoint(x, y)
    return task.cont
moveTask = taskMgr.add(move, 'move')
moveTask.updateDt = 0
base.accept('escape', sys.exit)
base.accept('r', img.fill, [veilColor])

You need to map the position of the Panda to the pixel coordinates of the image, probably something like this:

       pos = unit.getPos().xy - minb.xy
       pos.x /= maxb.x - minb.x
       pos.y /= maxb.y - minb.y
       painter.drawPoint(pos.x * img.getXSize(), (1 - pos.y) * img.getYSize())

After the conversion in this way, the position of the drawing point is indeed near the panda, but when the panda moves to the edge of the scene, it is obvious that the position of the drawing point is biased to the panda. Why is this?

It’s because of how you set up the texture scale. It has been set this way to keep the aspect ratio square. It is fixed if you instead do this:

terrain.setTexScale(veilTS, (1.0/dim[0], 1.0/dim[1]))
terrain.setTexOffset(veilTS, -.5-center[0]/dim[0], -.5-center[1]/dim[0])

However, as you can see, the dot becomes elliptical instead of round, which is presumably why the original code uses only a single scale for both dimensions.

You can fix that by making the bounding volume square:

minb, maxb = terrain.getTightBounds()
dim = maxb-minb

if dim[0] < dim[1]:
    maxb[0] = minb[0] + dim[1]
    dim[0] = dim[1]
    maxb[1] = minb[1] + dim[0]
    dim[1] = dim[0]


Sorry, I do not read Chinese. I have interpreted your question through Google Translate.

The role of the virtual node in the example was to set up a virtual coordinate space that can be used to have Panda3D automatically transform a world-space position to image-space coordinates. It is an alternative to doing the math that I have given in my first reply.

Haha, sorry. My English is also not very good. I also translated it through goole. I may have copied it wrong. Thank you so much, so I will study these two formulas again!