3D游戏物理开发引擎Panda3D基础

文章目录

    • Panda3D场景安排
    • 模型加载
    • 渲染属性
    • 任务
      • 任务链
      • 事件处理
      • 主循环
    • 视角
      • 相机
      • 阴影
        • 环境灯
        • 方向灯
    • 控制
        • key-events
    • DirectGui
    • 碰撞检测
    • 后续

Panda3D场景安排

​ Panda3D将其对象存储在场景图中,从本质上讲,这是一个对象的层次结构,称为节点。

3D游戏物理开发引擎Panda3D基础_第1张图片

​ 给定节点的状态(位置与旋转等状态)与其父级的状态是相对的,例如”0“的表示值表示与其父级位于同一位置。因此,每个节点都会影响其儿童节点及其子女,依次影响儿童节点。

​ 但通常情况下我们不直接操作节点,而是操作”NodePath“,"NodePath"包含对其节点的引用,描述了从根部到有关节点的通过场景图的路线。

模型加载

​ loader用于加载多种不同类型的对象,包括非动画模型。要加载文件,只需将以下代码添加到__init__中:


loader.loadModel("Models/Misc/environment")

Panda3D 允许不加入后缀名加载模型,加载模型后还需要将其连接到场景图中,通过使其称为NodePath中的一个节点来实现。

通过下列代码,可以将模型简单连接到场景图根部,NodePath由Panda3D自动提供,可在”render“中进行访问


self.environment.reparentTo(render)

在Panda3D中动画模型被称为”Actors“,不通过loader进行加载,而是直接通过实例化进行创建。构造中通过字典传递动画名称和动画文件。act_p3d_chan和a_p3d_chan_run同样为.egg文件。


from direct.actor.Actor import Actor

self.tempActor = Actor("Models/PandaChan/act_p3d_chan", {"walk" : "Models/PandaChan/a_p3d_chan_run"})

self.tempActor.reparentTo(render)

渲染属性

​ 总的来说,对象的所有属性都可以算是对象的渲染状态。

属性的分配


nodePath.node().setAttrib(attributeObject)

任务

Tasks:应用程序执行时每个帧调用一次的特殊功能。

| 变量 | 目的 |

| ------------ | ---------------------------------------- |

| Task.done | 指定任务已完成并将其从任务管理器中删除。 |

| Task.cont | 下一帧再次执行任务。 |

| Task.again | 再次执行任务,使用与最初指定相同的延迟。 |

**TaskMgr:**Panda3D中所有任务都通过该对象进行处理

添加任务taskMgr.add(exampleTask, 'MyTaskName')

若要指定参数,可以:taskMgr.add(exampleTask, 'MyTaskName', extraArgs=[a,b,c], appendTask=True)

删除任务taskMgr.remove('MyTaskName')

任务链

创建


taskMgr.setupTaskChain('chain_name', numThreads = None, tickClock = None,

                       threadPriority = None, frameBudget = None,

                       frameSync = None, timeslicePriority = None)

任务链由其唯一名称识别。重复呼叫设置具有相同任务链名称的TaskChain()将重新配置同一任务链。

numThreads:指定为此任务链提供服务的线程数。默认值为零,这意味着任务链将由主线程处理。如果将此设置为 1,则将生成一个线程,以正常顺序一次处理链中的所有任务。如果将此设置为高于 1 的某个数字,则将生成多个线程来处理链上的任务。在这种情况下,有些任务可能同时运行,任务排序难以保证。

threadPriority:可选择TP_low,TP_normal,TP_high,TP_urgent。指定了分配给此任务链上的线程的优先级。

frameBudget:允许此任务链每帧运行的最大时间(秒内),设置为 -1 表示无限制(默认值)。

frameSync:设置为True则使任务链与时钟同步。

timeslicePriority:时间优先性,将其设置为True更改优先级的含义,以便某些任务的运行频率降低,与其使用的时间与其优先值成正比。

事件处理

接收事件


from direct.showbase import DirectObject

class myDirectObject(DirectObject.DirectObject):

    

#无限接收

myDirectObject.accept('Event Name', myDirectObjectMethod)

#接收一次

myDirectObject.acceptOnce('Event Name', myDirectObjectMethod)

忽略事件


#忽略某个事件

myDirectObject.ignore('Event Name')

#忽略所有事件

myDirectObject.ignoreAll()

发送事件


messenger.send('Event Name')

主循环

​ Panda3D中的主循环通常由run()实现

视角

相机

​ 在Panda3D中,我们所看到的界面视角是以一个"camera"的模块决定的,Panda3D提供了对相机的访问和设置权限,包括一个引用节点路径的变量,即为"camera"。

示例


self.camera.setPos(0, 0, 32)

self.camera.setP(-90)

阴影

​ 在Panda3D中,光也是一种节点,其包括多种类型:方向灯、环境灯……

环境灯

​ 环境灯用恒定的光线填充场景,有助于确保未照明区域不会完全变黑、

示例


from panda3d.core import AmbientLight

from panda3d.core import Vec4

ambientLight = AmbientLight("ambient light")

ambientLight.setColor(Vec4(0.2, 0.2, 0.2, 1))

# 连接到场景中

self.ambientLightNodePath = render.attachNewNode(ambientLight)

# 设置光的影响节点

render.setLight(self.ambientLightNodePath)
方向灯

示例


from panda3d.core import DirectionalLight

mainLight = DirectionalLight("main light")

self.mainLightNodePath = render.attachNewNode(mainLight)

self.mainLightNodePath.setHpr(45, -45, 0)

render.setLight(self.mainLightNodePath)

控制

key-events

​ Panda3D中处理关键事件


# 存储关键信息

self.keyMap = {

    "up" : False,

    "down" : False,

    "left" : False,

    "right" : False,

    "shoot" : False

}

def updateKeyMap(self, controlName, controlState):

    self.keyMap[controlName] = controlState

self.accept("w", self.updateKeyMap, ["up", True])

DirectGui

​ DirectGui 系统用于在程序中创建按钮、标签、文本条目和帧。所有这些项目都可以用文本、图像和 3D 图形进行装饰。

​ Panda3D的坐标系中,x轴指示左右方向,y轴指示屏幕内外方向,z轴指示上下方向。

碰撞检测

​ Panda3D中提供了处理物理碰撞的两个系统:内置碰撞系统和Bullet物理系统

内置碰撞系统有三个主要元素:Traversers, Handlers, and Solids.

Traversers:用于检测各种物理物体的碰撞

Handlers:处理程序当物体碰撞时会发生的事件

Solids:实际的碰撞物体本身

通常我们只能使用一个traverser, 并让它检查每次更新的碰撞情况,ShowBase 类提供了一个名为"cTrav"的默认变量:如果您为此变量分配了一个新的traverser,Panda 将自动为您更新它。

示例


from panda3d.core import CollisionTraverser

self.cTrav = CollisionTraverser()

Handlers的使用

CollisionHandlerQueue:将碰撞事件存储在队列中,并允许您根据需要访问它们。您还可以对队列进行排序,以便轻松获得第一次碰撞。

CollisionHandlerEvent:每当指定的碰撞发生时,就会引发调用事件

CollisionHandlerPusher:防止指定的固体物体与其他固体物体相交

示例


from panda3d.core import CollisionHandlerPusher

from panda3d.core import CollisionSphere, CollisionNode

self.pusher = CollisionHandlerPusher()

colliderNode = CollisionNode("player")

colliderNode.addSolid(CollisionSphere(0, 0, 0, 0.3))

collider = self.tempActor.attachNewNode(colliderNode)

# 显示碰撞物体

collider.show()

# 添加为活跃对象

base.pusher.addCollider(collider, self.tempActor)

base.cTrav.addCollider(collider, self.pusher)

Panda3D 的内置系统不会检查每个对象与所有其他对象,只有程序指定的对象才会进行碰撞检测,其他的对象视为非活跃对象。只有活跃对象能够与其他物体碰撞,非活跃对象仅能被碰撞。

在碰撞中我们还可以指定碰撞响应的维度,否则默认为三维的碰撞响应。


#指定碰撞响应维度为水平

self.pusher.setHorizontal(True)

Panda3D就是通过这样的机制创建具有障碍性质的对象。

后续

 喜欢的话可以关注一下我的公众号技术开发小圈,尤其是对深度学习以及计算机视觉有兴趣的朋友,我会把相关的源码以及更多资料发在上面,希望可以帮助到新入门的大家!
在这里插入图片描述

你可能感兴趣的:(3d游戏,3d渲染)