Thanks for the suggestion. Maybe I was not so clear about what my program do with Panda3D. I list my code at the last paragragh.
My program first load a model (.obj file with texture), and then create a camera looking at its geographic center (or exactly its bounding sphere center). The window it create with Panda3D can accept R key to set new position of the camera around the model (the camera is always looking at its bounding sphere center, just like the figure shown. I rotate three times). The model does not move.
I indeed add a function ProjectToCamera to print the 2D pixel coordinate projected from any 3D point in the model, after each time rotating the camera. For the point A (-0.200000002980,0.209999993443,0.000000000000), it print the following results.
A is located in the screenshot with red circle. It is actually the toppest point of the protrusion on the vehicle. That is how I find it in the screenshots (^-^). I want to know how to obtain its corresponding pixel coordinate in the screenshots.
The following is my complete code,. It can run directly in Python. Donāt laugh at me. My Pyhton skill sucks. If I remove the first piece of code in ProjectToCamera by setting A to pCamera, the results are shown as the following figure.
from direct.showbase.ShowBase import ShowBase
from panda3d.core import Filename
from panda3d.core import LVector3f, LVector4f, LMatrix4f, LVector2d, LPoint3f, LPoint2f, LPlanef
from panda3d.core import PerspectiveLens, OrthographicLens
from panda3d.core import PointLight, AmbientLight, DirectionalLight, AntialiasAttrib, Material
from direct.task import Task
from math import sin, cos, pi, log, floor
class PandaShotMachine(ShowBase):
def __init__(self):
ShowBase.__init__(self)
self.windowhalfedge=768
self.openDefaultWindow(size=[self.windowhalfedge,self.windowhalfedge]);
base.disableMouse()
self.accept('r-up', self.Orbit)
# Exit on pressing the escape button.
self.accept('escape', self.StopRunning)
self.running=True
self.orbitangle=0.0
def StopRunning(self):
self.running=False
def LoadAndConfigModel(self, filepath: str):
self.setBackgroundColor(0.0,0.0,0.0,1.0)
winfile=filepath
pandafile = Filename.fromOsSpecific(winfile)
# Load the environment model.
self.scene = self.loader.loadModel(pandafile, noCache=True)
# Apply scale and position transforms on the model.
#self.scene.setScale(0.25, 0.25, 0.25)
#self.scene.setPos(0, 0, 0)
self.SetCameraAndLight(0.0, False, False);
# Reparent the model to render.
self.scene.reparentTo(self.render)
def SetCameraAndLight(self, centerrotateangle: float, isconceptual: bool, perspective: bool):
c=self.scene.getBounds().getCenter()
r=self.scene.getBounds().getRadius()
edge=self.scene.getTightBounds()[1][0]-self.scene.getTightBounds()[0][0]
if edge<self.scene.getTightBounds()[1][2]-self.scene.getTightBounds()[0][2]:
edge=self.scene.getTightBounds()[1][2]-self.scene.getTightBounds()[0][2]
height=self.scene.getTightBounds()[1][1]-self.scene.getTightBounds()[0][1]
focus=c
eyepos=LVector3f(c[0]+r,c[1]+r,c[2]+r)
filmedge=r
lightmag=0.1
#print([edge, height])
if edge*2<height:
if perspective:
focus=LVector3f(c[0],self.scene.getTightBounds()[1][1]-edge,c[2])
filmedge=height-edge/1.414
er=log(height/edge/2)+1
eyepos=LVector3f(focus[0]+edge*er,focus[1]+edge*er,focus[2]+edge*er)
lightmag=0.2
**# Rotate camera**
cr=eyepos[0]-focus[0]
eyepos=LVector3f(focus[0]+cr*cos(centerrotateangle*pi/180), focus[1]+cr, focus[2]+cr*sin(centerrotateangle*pi/180))
if perspective:
lens = PerspectiveLens()
lens.setFov(60)
lens.setViewVector(0.0,0.0,0.0,0.0,1.0,0.0)
base.cam.node().setLens(lens)
else:
lens = OrthographicLens()
lens.setFar(1.732*2*r)
lens.setNear(0.0)
lens.setViewVector(0.0,0.0,0.0,0.0,1.0,0.0)
lens.setFilmSize(2*filmedge, 2*filmedge) # Or whatever is appropriate for your scene
base.cam.node().setLens(lens)
self.camera.setPos(eyepos)
self.camera.lookAt(focus, LVector3f(0.0,1.0,0.0))
hpr=self.camera.getHpr()#ļ¼ļ¼ļ¼ļ¼
self.projectfocus=focus
self.projectcameraplanecenter=eyepos
self.projecthalfedge=filmedge
#å
ęŗ
self.render.clearLight()
dlight_direction = LVector3f(hpr[0], hpr[1], hpr[2]) if isconceptual else LVector3f(0.0,180.0,0.0) #LVector3f(-hpr[0], hpr[1], -hpr[2])
plight_position = LVector3f(focus[0]*2-eyepos[0],eyepos[1],focus[2]*2-eyepos[2]) if isconceptual else eyepos #LVector3f(eyepos[0]+r,eyepos[1]+r,eyepos[2]+r)
dlight = DirectionalLight('dlight')
dlight.setColor((1.0, 1.0, 1.0, 1) if not isconceptual else (0.2,0.2,0.2,1.0))
dlnp = self.render.attachNewNode(dlight)
#print(dlight_direction)
dlnp.setHpr(dlight_direction)
self.render.setLight(dlnp)
#dlight = DirectionalLight('dlight2')
#dlight.setColor((0.2, 0.2, 0.2, 1))
#dlnp = self.scene.attachNewNode(dlight)
##dlnp.setHpr(-hpr[0], hpr[1], -hpr[2])
#dlnp.setHpr(hpr)
#self.scene.setLight(dlnp)
plight = PointLight('plight')
plight.setColor((lightmag, lightmag, lightmag, 1))
plight.attenuation=(0.1, 0.0, 0)
plight.setMaxDistance(1.732*2*r)
plnp = self.render.attachNewNode(plight)
plnp.setPos(plight_position)
self.render.setLight(plnp)
plight = PointLight('plight2')
plight.setColor((0.6*lightmag, 0.6*lightmag, 0.6*lightmag, 1))
plight.attenuation=(0.1, 0.0, 0)
plight.setMaxDistance(1.732*2*r)
plnp = self.render.attachNewNode(plight)
plnp.setPos(focus[0]*2-eyepos[0],eyepos[1],focus[2]*2-eyepos[2])
self.render.setLight(plnp)
alight = AmbientLight('alight')
alight.setColor((0.2, 0.2, 0.2, 1))
alnp = self.render.attachNewNode(alight)
self.render.setLight(alnp)
def Orbit(self):
self.orbitangle+=15.0
self.SetCameraAndLight(self.orbitangle, False, False)
res=self.ProjectToCamera(LPoint3f(-0.200000002980, 0.209999993443, 0))
self.ProjectToCamera(LPoint3f(0.0, 1.30704, 0))
def ProjectToCamera(self, A: LPoint3f):
cameraToWorld=self.camera.getMat()
#print(len.getFov())
ctw_inverse=LMatrix4f()
ctw_inverse.invertFrom(cameraToWorld)
pp=LVector4f(A[0],A[1],A[2],1);
pCamera=LVector4f()
for i in range(4):
pCamera[i]=pp.dot(ctw_inverse.getCol(i))
pCamera=LPoint3f(pCamera[0],pCamera[1],pCamera[2])
lens = base.camNode.getLens()
resultPoint = LPoint3f()
success = lens.project(pCamera, resultPoint)
if success:
finalPoint = base.pixel2d.getRelativePoint(base.render2d, LPoint3f(resultPoint.x, 0, resultPoint.z))
print(finalPoint[0],finalPoint[1], finalPoint[2])
if name == āmainā:
try:
winfile = uāpath to any obj.objā
app = PandaShotMachine()
app.LoadAndConfigModel(winfile)
app.SetCameraAndLight(0.0, False, False)
while app.running:
if not app.win.getProperties().getOpen():
app.running=False
break
app.taskMgr.step()
app.destroy()
except Exception as e:
print(e)