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
base.cam.setPos(-29.66, -216.88, 255.92)
base.cam.setHpr(-0.47, -50.13, -0.36)
terrain = loader.loadModel('world')
terrain.reparentTo(render)
terrain.showTightBounds()
unit = loader.loadModel("panda")
unit.reparentTo(render)
ls = LineSegs('')
ls.setColor(Vec4(1, 0, 0, 1))
ls.moveTo(0, 0, 100)
ls.drawTo(0, 0, -20)
unit4 = unit.attachNewNode(ls.create())
unit4.setTransparency(1)
ls.setVertexColor(0, Vec4(1, 0, 0, 0))
veilColor = 0.2  # the veil/fog color
imgSize = 32
img = PNMImage(imgSize, imgSize)
img.fill(veilColor)
brush = PNMBrush.makeSpot((1,1,1,1), 3, True)
painter = PNMPainter(img)
painter.setPen(brush)
tex = Texture()
tex.load(img)
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)
       tex.load(img)
    return task.cont
moveTask = taskMgr.add(move, 'move')
moveTask.updateDt = 0
base.accept('escape', sys.exit)
base.accept('r', img.fill, [veilColor])
base.run()

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]
else:
    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!