中国农业大学计算机图形学 2022课程设计 三维美术馆漫游
写在前面:这玩意还是蛮有趣的哈哈哈
第一部分:加载场景,让人物动起来
import sys #加载库文件
import viz
import vizact
import vizinfo
import vizshape
import vizact
import math
import datetime
speed = 2.0 #设置移动速度
view = viz.MainView #设置视角,get the main viewpoint object
viz.setMultiSample(18)
viz.go()
viz.mouse.setVisible(viz.OFF) #关闭鼠标图案
avatar = viz.addAvatar('vcc_male.cfg', pos=(0,0,0), euler=(0,0,0)) #加入人物,模型是自带男性,位置坐标,欧拉角
gallery = viz.add('gallery.osgb') #载入美术馆模型
car = viz.addChild('mini.osg', pos=(0,0,6), euler=(-90,0,0)) #加入一辆minicooper
运行该片段,用鼠标进行移动,可以观察该场景和各模型
第二部分:让这个人走起来
我们现在需要让这个痴呆小人没病走两步,下面来实现一些基础代码
在移动的时候,先不考虑转圈和视角移动,在上一个代码段后插入该段代码
核心思路,人动,视角追,人转,视角变换之后转
其中坐标计算的有关数学知识部分见周学长的讲解:http://t.csdn.cn/Lzc6E
def UpdateView():
m = viz.Matrix.euler(0,0,0) #定义人物模型移动的坐标矩阵
camera = viz.Matrix.euler(0,0,0) #定义相机移动的坐标矩阵
dm = viz.getFrameElapsed() * speed #定义一个dm,记录获取自上一帧以来经过的时间*速度的结果
temp=avatar.getEuler()[0]*math.pi/180 #获取人物当前的欧拉矩阵,并用temp记录其在x方向上的夹角
if viz.key.isDown('w'): #如果按下‘W’键,则对人物模型和相机的坐标矩阵根据欧拉角进行改变,并播放移动动作
m.preTrans([dm*math.sin(temp),0,dm*math.cos(temp)]) #人物
camera.preTrans([dm*math.sin(temp),0,dm*math.cos(temp)]) #相机
avatar.state(2) #播放移动动作
elif viz.key.isDown('s'): #同理
m.preTrans([-dm*math.sin(temp),0,-dm*math.cos(temp)])
camera.preTrans([-dm*math.sin(temp),0,-dm*math.cos(temp)])
avatar.state(2)
elif viz.key.isDown('a'):
m.preTrans([-dm*0.3*math.cos(temp),0,dm*0.3*math.sin(temp)])
camera.preTrans([-dm*0.3*math.cos(temp),0,dm*0.3*math.sin(temp)])
avatar.state(12)
elif viz.key.isDown('d'):
m.preTrans([dm*0.3*math.cos(temp),0,-dm*0.3*math.sin(temp)])
camera.preTrans([dm*0.3*math.cos(temp),0,-dm*0.3*math.sin(temp)])
avatar.state(13)
else :
avatar.state(1) #如果站着不动蛤起,也要播一个动作
avatar.setPosition(m.getPosition(), viz.REL_PARENT) #setPosition(x,y,z,参数),其中viz.REL_PARENT代表根据其现在的位置重新构筑的相对坐标系,前面的m.getPosition()即是在相对坐标系下进行修改
view.setPosition(camera.getPosition(), viz.REL_PARENT)
vizact.ontimer(0,UpdateView) #让其重复执行该函数
第三部分:让这个人转起来
这一部分,原理见帮助文档视角窗变换章节
#【函数】鼠标控制第三人称摄像机跟随人物旋转
def onMouseMove(e):
p1 = avatar.getPosition() #摄像机位置坐标
p2 = view.getPosition() #摄像机位置坐标
e1 = avatar.getEuler() #旋转前人 物的朝向欧拉角
e2 = view.getEuler() #旋转前摄像机的朝向欧拉角
e1[0] = e1[0]+e.dx/10 #鼠标横向偏移,将鼠标偏移量除以10控制鼠标灵敏度,人 物旋转,偏航角e1[0]改变
avatar.setEuler(e1) #旋转后人 物的朝向欧拉角
p2[1] = p1[1]+2 #摄像机在y轴的相对高度比人物高,即在y轴方向摄像机以人物高2个单位
p2[0] = p1[0]-3*math.sin(math.pi*(e1[0]/180)) #摄像机在x轴的相对距离在人物后,即摄像机在x轴方向偏移了3sin(θ)个单位
p2[2] = p1[2]-3*math.cos(math.pi*(e1[0]/180)) #摄像机在z轴的相对距离在人物后,即摄像机在z轴方向偏移了3cos(θ)个单位
e2[0]=e1[0]
e2[2]=e1[2]
e2[1] = e2[1]-e.dy/10 #鼠标纵向偏移,将鼠标偏移量除以20控制鼠标灵敏度,摄像机旋转,俯仰角e2[1]改变
e2[1] = viz.clamp(e2[1],-85.0,85.0) #控制俯仰角
view.setEuler(e2)
view.setPosition(p2) #设置旋转后摄像机的位置坐标
viz.callback(viz.MOUSE_MOVE_EVENT,onMouseMove) #回调函数检测鼠标偏移量
其中利用clamp函数控制摄像机在y轴的夹角,避免小人晕头转向!!
第四部分:加入关键要素,时钟
此部分讲解学长讲得非常详细http://t.csdn.cn/Lzc6E
这里我就只粘贴代码了,四个模型建好放在resources文件夹下,运行即可
biaopan=viz.add('Biaopan.obj') #加入表盘模型
shizhen=viz.add('Shizhen.obj') #加入时针模型
fenzhen=viz.add('fenzhen.obj') #加入分针模型
miaozhen=viz.add('miaozhen.obj') #加入秒针模型
#调整时钟模型大小
biaopan.setScale([0.25,0.25,0.25]) #调整模型大小
shizhen.setScale([0.25,0.25,0.25]) #调整模型大小
fenzhen.setScale([0.25,0.25,0.25]) #调整模型大小
miaozhen.setScale([0.25,0.25,0.25]) #调整模型大小
#设置时钟初始位置
biaopan.setPosition(0,4,9.98) #表盘坐标位置
shizhen.setPosition(0,4,9.97) #时针坐标位置
fenzhen.setPosition(0,4,9.97) #分针坐标位置
miaozhen.setPosition(0,4,9.97) #秒针坐标位置
#设置时钟初始朝向
biaopan.setEuler(0,-90,0) #表盘初始朝向
shizhen.setEuler(-90,180,0) #时针初始朝向
fenzhen.setEuler(-90,180,0) #分针初始朝向
miaozhen.setEuler(-90,180,0) #秒针初始朝向
#【函数】时钟渲染
def Clock():
t = datetime.datetime.now() #获取系统时间(系统时间是实时变化的,必须将其值赋值给其他变量才可以处理)
hour=t.hour #将系统的小时值赋值给hour
minute=t.minute #将系统的分钟值赋值给minute
second=t.second #将系统的秒数值赋值给second
hour=hour%12 #时钟一圈只有12小时,对于12:00~24:00的情况需要对hour进行模12除法的处理
second_angle=second/60.0*360 #计算一秒钟秒针的旋转角度
minute_angle=minute/60.0*360+second/60.0*6 #计算一秒钟分针的旋转角度
hour_angle=hour/12.0*360+minute/60.0*30 #计算一秒钟时针的旋转角度
miaozhen.setEuler(-90,270-second_angle,0) #设置一秒钟后的秒针角度
fenzhen.setEuler(-90,270-minute_angle,0) #设置一秒钟后的分针角度
shizhen.setEuler(-90,270-hour_angle,0) #设置一秒钟后的时针角度
vizact.ontimer(1,Clock) #每隔一秒刷新一次,实现时钟功能
第五部分:小人讲话和鸽子
此处详情见帮助文档Tutorial: Adding Avatars
#小人讲话
def PersonTalk():
female = viz.addAvatar('vcc_female.cfg', pos=(1,0,8), euler=(-90,0,0))
male = viz.addAvatar('vcc_male2.cfg', pos=(0,0,8), euler=(90,0,0))
female.state(14)
male.state(4)
#鸽子走路
pigeon = viz.addAvatar('pigeon.cfg',pos=(2,0,5))
random_walk = vizact.walkTo(pos=[vizact.randfloat(1.5,2.5),0,vizact.randfloat(4.5,5.5)])
random_animation = vizact.method.state(vizact.choice([1,3],vizact.RANDOM))
random_wait = vizact.waittime(vizact.randfloat(2.0,8.0))
pigeon_idle = vizact.sequence( random_walk, random_animation, random_wait, viz.FOREVER)
pigeon.runAction(pigeon_idle)
PersonTalk();