182 lines
6.1 KiB
Python
182 lines
6.1 KiB
Python
#!/usr/bin/env python
|
|
|
|
# Author: Kwasi Mensah (kmensah@andrew.cmu.edu)
|
|
# Date: 8/02/2005
|
|
#
|
|
# This is meant to be a simple example of how to draw a cube
|
|
# using Panda's new Geom Interface. Quads arent directly supported
|
|
# since they get broken down to trianlges anyway.
|
|
#
|
|
|
|
from direct.showbase.ShowBase import ShowBase
|
|
from direct.showbase.DirectObject import DirectObject
|
|
from direct.gui.DirectGui import *
|
|
from direct.interval.IntervalGlobal import *
|
|
from panda3d.core import lookAt
|
|
from panda3d.core import GeomVertexFormat, GeomVertexData
|
|
from panda3d.core import Geom, GeomTriangles, GeomVertexWriter
|
|
from panda3d.core import Texture, GeomNode
|
|
from panda3d.core import PerspectiveLens
|
|
from panda3d.core import CardMaker
|
|
from panda3d.core import Light, Spotlight
|
|
from panda3d.core import TextNode
|
|
from panda3d.core import LVector3
|
|
import sys
|
|
import os
|
|
|
|
base = ShowBase()
|
|
base.disableMouse()
|
|
base.camera.setPos(0, -10, 0)
|
|
|
|
title = OnscreenText(text="Panda3D: Tutorial - Making a Cube Procedurally",
|
|
style=1, fg=(1, 1, 1, 1), pos=(-0.1, 0.1), scale=.07,
|
|
parent=base.a2dBottomRight, align=TextNode.ARight)
|
|
escapeEvent = OnscreenText(text="1: Set a Texture onto the Cube",
|
|
style=1, fg=(1, 1, 1, 1), pos=(0.06, -0.08),
|
|
align=TextNode.ALeft, scale=.05,
|
|
parent=base.a2dTopLeft)
|
|
spaceEvent = OnscreenText(text="2: Toggle Light from the front On/Off",
|
|
style=1, fg=(1, 1, 1, 1), pos=(0.06, -0.14),
|
|
align=TextNode.ALeft, scale=.05,
|
|
parent=base.a2dTopLeft)
|
|
upDownEvent = OnscreenText(text="3: Toggle Light from on top On/Off",
|
|
style=1, fg=(1, 1, 1, 1), pos=(0.06, -0.20),
|
|
align=TextNode.ALeft, scale=.05,
|
|
parent=base.a2dTopLeft)
|
|
|
|
|
|
# You can't normalize inline so this is a helper function
|
|
def normalized(*args):
|
|
myVec = LVector3(*args)
|
|
myVec.normalize()
|
|
return myVec
|
|
|
|
# helper function to make a square given the Lower-Left-Hand and
|
|
# Upper-Right-Hand corners
|
|
|
|
def makeSquare(x1, y1, z1, x2, y2, z2):
|
|
format = GeomVertexFormat.getV3n3cpt2()
|
|
vdata = GeomVertexData('square', format, Geom.UHDynamic)
|
|
|
|
vertex = GeomVertexWriter(vdata, 'vertex')
|
|
normal = GeomVertexWriter(vdata, 'normal')
|
|
color = GeomVertexWriter(vdata, 'color')
|
|
texcoord = GeomVertexWriter(vdata, 'texcoord')
|
|
|
|
# make sure we draw the sqaure in the right plane
|
|
if x1 != x2:
|
|
vertex.addData3(x1, y1, z1)
|
|
vertex.addData3(x2, y1, z1)
|
|
vertex.addData3(x2, y2, z2)
|
|
vertex.addData3(x1, y2, z2)
|
|
|
|
normal.addData3(normalized(2 * x1 - 1, 2 * y1 - 1, 2 * z1 - 1))
|
|
normal.addData3(normalized(2 * x2 - 1, 2 * y1 - 1, 2 * z1 - 1))
|
|
normal.addData3(normalized(2 * x2 - 1, 2 * y2 - 1, 2 * z2 - 1))
|
|
normal.addData3(normalized(2 * x1 - 1, 2 * y2 - 1, 2 * z2 - 1))
|
|
|
|
else:
|
|
vertex.addData3(x1, y1, z1)
|
|
vertex.addData3(x2, y2, z1)
|
|
vertex.addData3(x2, y2, z2)
|
|
vertex.addData3(x1, y1, z2)
|
|
|
|
normal.addData3(normalized(2 * x1 - 1, 2 * y1 - 1, 2 * z1 - 1))
|
|
normal.addData3(normalized(2 * x2 - 1, 2 * y2 - 1, 2 * z1 - 1))
|
|
normal.addData3(normalized(2 * x2 - 1, 2 * y2 - 1, 2 * z2 - 1))
|
|
normal.addData3(normalized(2 * x1 - 1, 2 * y1 - 1, 2 * z2 - 1))
|
|
|
|
# adding different colors to the vertex for visibility
|
|
color.addData4f(1.0, 0.0, 0.0, 1.0)
|
|
color.addData4f(0.0, 1.0, 0.0, 1.0)
|
|
color.addData4f(0.0, 0.0, 1.0, 1.0)
|
|
color.addData4f(1.0, 0.0, 1.0, 1.0)
|
|
|
|
texcoord.addData2f(0.0, 1.0)
|
|
texcoord.addData2f(0.0, 0.0)
|
|
texcoord.addData2f(1.0, 0.0)
|
|
texcoord.addData2f(1.0, 1.0)
|
|
|
|
# Quads aren't directly supported by the Geom interface
|
|
# you might be interested in the CardMaker class if you are
|
|
# interested in rectangle though
|
|
tris = GeomTriangles(Geom.UHDynamic)
|
|
tris.addVertices(0, 1, 3)
|
|
tris.addVertices(1, 2, 3)
|
|
|
|
square = Geom(vdata)
|
|
square.addPrimitive(tris)
|
|
return square
|
|
|
|
# Note: it isn't particularly efficient to make every face as a separate Geom.
|
|
# instead, it would be better to create one Geom holding all of the faces.
|
|
square0 = makeSquare(-1, -1, -1, 1, -1, 1)
|
|
square1 = makeSquare(-1, 1, -1, 1, 1, 1)
|
|
square2 = makeSquare(-1, 1, 1, 1, -1, 1)
|
|
square3 = makeSquare(-1, 1, -1, 1, -1, -1)
|
|
square4 = makeSquare(-1, -1, -1, -1, 1, 1)
|
|
square5 = makeSquare(1, -1, -1, 1, 1, 1)
|
|
snode = GeomNode('square')
|
|
snode.addGeom(square0)
|
|
snode.addGeom(square1)
|
|
snode.addGeom(square2)
|
|
snode.addGeom(square3)
|
|
snode.addGeom(square4)
|
|
snode.addGeom(square5)
|
|
|
|
cube = render.attachNewNode(snode)
|
|
cube.hprInterval(1.5, (360, 360, 360)).loop()
|
|
|
|
# OpenGl by default only draws "front faces" (polygons whose vertices are
|
|
# specified CCW).
|
|
cube.setTwoSided(True)
|
|
|
|
|
|
class MyTapper(DirectObject):
|
|
|
|
def __init__(self):
|
|
self.testTexture = loader.loadTexture("maps/envir-reeds.png")
|
|
self.accept("1", self.toggleTex)
|
|
self.accept("2", self.toggleLightsSide)
|
|
self.accept("3", self.toggleLightsUp)
|
|
|
|
self.LightsOn = False
|
|
self.LightsOn1 = False
|
|
slight = Spotlight('slight')
|
|
slight.setColor((1, 1, 1, 1))
|
|
lens = PerspectiveLens()
|
|
slight.setLens(lens)
|
|
self.slnp = render.attachNewNode(slight)
|
|
self.slnp1 = render.attachNewNode(slight)
|
|
|
|
def toggleTex(self):
|
|
global cube
|
|
if cube.hasTexture():
|
|
cube.setTextureOff(1)
|
|
else:
|
|
cube.setTexture(self.testTexture)
|
|
|
|
def toggleLightsSide(self):
|
|
global cube
|
|
self.LightsOn = not self.LightsOn
|
|
|
|
if self.LightsOn:
|
|
render.setLight(self.slnp)
|
|
self.slnp.setPos(cube, 10, -400, 0)
|
|
self.slnp.lookAt(10, 0, 0)
|
|
else:
|
|
render.setLightOff(self.slnp)
|
|
|
|
def toggleLightsUp(self):
|
|
global cube
|
|
self.LightsOn1 = not self.LightsOn1
|
|
|
|
if self.LightsOn1:
|
|
render.setLight(self.slnp1)
|
|
self.slnp1.setPos(cube, 10, 0, 400)
|
|
self.slnp1.lookAt(10, 0, 0)
|
|
else:
|
|
render.setLightOff(self.slnp1)
|
|
|
|
t = MyTapper()
|
|
base.run()
|