You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Dictionary to access the physics body for a three.js mesh
physics_objects = []
def update_physics(delta_time):
world.step(delta_time)
for mesh in physics_objects:
body = mesh.userData.body
mesh.position.copy(cannon_to_three_vector(body.position))
mesh.quaternion.copy(body.quaternion)
def init_physics_box(mesh, mass):
"""
Initialize a three.js mesh as a cube in the Cannon.js world
Arguments:
mesh -- The three.js mesh
mass -- The mass for the physics object in kg
Returns: The Cannon.js physics body
"""
bounding_box = three.Box3.new().setFromObject(mesh)
size = three.Vector3.new()
bounding_box.getSize(size)
rot_transform = mesh.quaternion.clone()
rot_transform.invert()
size.applyQuaternion(rot_transform)
size.set(abs(size.x), abs(size.y), abs(size.z))
body = Cannon.Body.new({
'mass': mass,
'position': mesh.position.clone(),
'quaternion': mesh.quaternion.clone(),
'shape': Cannon.Box.new(three_to_cannon_vector(size).scale(0.5)),
})
world.addBody(body)
mesh.userData.body = body;
physics_objects.append(mesh)
return body
#-----------------------------------------
Classes
#-----------------------------------------
class NpcRow:
"""
A graphical colored track that has a train of cube npcs that
move across it
"""
row_length = 300
npc_spacing = 3
def __init__(self, color, numNpcs, x, y, z):
"""
Initialize an NpcRow
Arguments:
color -- The color for the backpane of the row
numNpcs -- The number of npc cubes this row should have
x -- The x position for this row
y -- The y position for this row
z -- The z position for this row
"""
self.color = color
self.numNpcs = numNpcs
self.x = x
self.y = y
self.z = z
# This group will contain all the game objects associated with this row
self.group = three.Group.new()
self.group.position.set(self.x, self.y, self.z)
# This group will contain the npcs
self.npc_group = three.Group.new()
self.group.add(self.npc_group)
self.__setup_objects()
self.__setup_animations()
def __setup_objects(self):
"""
Setup the individual three.js objects for this row
"""
self.back_pane = three.Mesh.new(
three.BoxGeometry.new(1, NpcRow.row_length, 0.1),
three.MeshStandardMaterial.new({'color': self.color, 'side': three.DoubleSide})
)
self.back_pane.position.set(0, 0, -1)
self.group.add(self.back_pane)
rect_light = three.RectAreaLight.new(self.color, 2, 1, NpcRow.row_length)
self.group.add(rect_light)
for i in range(self.numNpcs):
npc = self.__make_npc_object()
npc.position.y = NpcRow.npc_spacing * i;
self.npc_group.add(npc)
self.npc_group.position.set(0, -NpcRow.row_length / 2, 0)
def __make_npc_object(self):
"""
Construct an individual NpcCube containing a cube and a light behind it
Returns: The constructed object
"""
box = three.Mesh.new(
three.BoxGeometry.new(1, 1, 1),
three.MeshStandardMaterial.new({'color': '#ffffff'})
)
box.position.set(0, 0, 0)
light = three.PointLight.new(self.color, 1, 100, 1)
light.position.set(0, 0, -0.6)
group = three.Group.new()
group.add(box)
group.add(light)
return group
def __setup_animations(self):
"""
Add this NpcRow to the animation group so it can be animated
"""
npc_row_animation_group.add(self.npc_group)
def begin_animation():
"""
Begin animation for all npc_row objects.
This only needs to be called once per three.js scene in order to
start animation for all NpcRow objects
"""
keyframes = three.VectorKeyframeTrack.new(
'.position',
[0, 3],
[0, -NpcRow.row_length / 2, 0, 0, NpcRow.row_length / 2, 0]
)
clip = three.AnimationClip.new('anim', 3, [keyframes])
action = npc_row_mixer.clipAction(clip)
action.setLoop(three.LoopRepeat)
action.play()
def get_group(self):
return self.group
#-----------------------------------------
Functions
#-----------------------------------------
Scene setup methods
def setup_main_scene():
"""
Setup the first scene of the story board
"""
# Lighting and effects
scene.fog = three.FogExp2.new('#000000', 0.02)
def setup_scene_two():
"""
Setup the second scene of the story board
"""
pass
def get_gus_object():
"""
Create and return an object to represent the main character, Gus.
Gus is a red cube.
This will also add Gus to the physics world
Return: A three.js Mesh representing Gus
"""
gus = three.Mesh.new(three.BoxGeometry.new(1, 1, 1), three.MeshStandardMaterial.new({'color': '#f00'}))
gus.name = 'gus'
return gus
def get_evil_cube_object():
"""
Create and return an object to represent the evil cube
This will also add the evil cube to the physics world
Return: A three.js Mesh representing the evil cube.
"""
evil_cube = three.Mesh.new(
three.BoxGeometry.new(2, 2, 2),
three.MeshStandardMaterial.new({'color': '#444'})
)
evil_cube.name = 'evil_cube'
return evil_cube
def add_ufo(ufo):
"""
This is a callback to be passed to the OBJLoader for the UFO object.
This will run once the ufo is loaded and set it up in the scene
"""
ufo.position.set(9, 13, -30)
ufo.scale.set(0.02, 0.02, 0.02)
ufo.rotation.x -= math.pi / 3
ufo.name = 'ufo'
scene.add(ufo)
program_start = time.time()
def periodic():
"""
This is the periodic method. It gets called rapidly to update graphics,
animations, and physics.
"""
delta_time = clock.getDelta()
update_physics(delta_time)
if time.time() - program_start > LOAD_TIME:
npc_row_mixer.update(delta_time)
try:
scene.getObjectByName('ufo').rotation.z += 0.03
except:
pass
controls.update()
renderer.render(scene, camera)
timer.set_timeout(periodic, 1000 / FPS)
The syntax is a bit weird because I'm using cannon.js through the Brython library for python, but you can get the idea. (It looks like github actually interpreted some of my code as markdown :/)
`import math, time, traceback
from browser import document, window, load, timer
load('https://cdn.jsdelivr.net/npm/three/build/three.min.js')
load('https://cdn.jsdelivr.net/npm/[email protected]/examples/js/controls/OrbitControls.js')
load('https://cdn.jsdelivr.net/npm/[email protected]/examples/js/lights/RectAreaLightUniformsLib.js')
load('https://cdn.jsdelivr.net/npm/[email protected]/examples/js/loaders/OBJLoader.js')
load('https://cdnjs.cloudflare.com/ajax/libs/cannon.js/0.6.2/cannon.min.js')
Make libraries more accessable
three = window.THREE
Cannon = window.CANNON
#-----------------------------------------
Functions used in setup
#-----------------------------------------
def setup_document(doc):
doc.body.innerHTML = ''
doc.body.style.margin = '0'
doc.body.style.overflow = 'hidden'
def cannon_to_three_vector(cannon_vec):
return three.Vector3.new(cannon_vec.x, cannon_vec.y, cannon_vec.z)
def three_to_cannon_vector(three_vec):
return Cannon.Vec3.new(three_vec.x, three_vec.y, three_vec.z)
#-----------------------------------------
Setting up the three.js graphics environment
#-----------------------------------------
setup_document(document)
FPS = 60
LOAD_TIME = 3 # Loading time in seconds
renderer = three.WebGLRenderer.new()
renderer.domElement.style.width = '100%';
renderer.domElement.style.height = '100%';
renderer.setSize(window.innerWidth * 4, window.innerHeight * 4, False)
renderer.shadowMap.enabled = True
document.body.appendChild(renderer.domElement)
scene = three.Scene.new()
camera = three.PerspectiveCamera.new(45, window.innerWidth /
window.innerHeight, 1, 10000)
camera.position.set(10, 15, 30)
camera.quaternion.setFromEuler(three.Euler.new(math.radians(-15), 0, 0))
controls = three.OrbitControls.new(camera, renderer.domElement)
controls.enablePan = False
controls.enableZoom = False
clock = three.Clock.new()
npc_row_animation_group = three.AnimationObjectGroup.new()
npc_row_mixer = three.AnimationMixer.new(npc_row_animation_group)
three.RectAreaLightUniformsLib.init();
#-----------------------------------------
Setting up the Cannon.js physics environment
#-----------------------------------------
world = Cannon.World.new()
world.gravity.set(0, -3, 0)
world.broadphase = Cannon.NaiveBroadphase.new()
world.broadphase.useBoundingBoxes = True
world.solver.iterations = 10
Dictionary to access the physics body for a three.js mesh
physics_objects = []
def update_physics(delta_time):
world.step(delta_time)
for mesh in physics_objects:
body = mesh.userData.body
mesh.position.copy(cannon_to_three_vector(body.position))
mesh.quaternion.copy(body.quaternion)
def init_physics_box(mesh, mass):
"""
Initialize a three.js mesh as a cube in the Cannon.js world
#-----------------------------------------
Classes
#-----------------------------------------
class NpcRow:
"""
A graphical colored track that has a train of cube npcs that
move across it
"""
row_length = 300
npc_spacing = 3
#-----------------------------------------
Functions
#-----------------------------------------
Scene setup methods
def setup_main_scene():
"""
Setup the first scene of the story board
"""
# Lighting and effects
scene.fog = three.FogExp2.new('#000000', 0.02)
def setup_scene_two():
"""
Setup the second scene of the story board
"""
pass
def get_gus_object():
"""
Create and return an object to represent the main character, Gus.
def get_evil_cube_object():
"""
Create and return an object to represent the evil cube
def add_ufo(ufo):
"""
This is a callback to be passed to the OBJLoader for the UFO object.
program_start = time.time()
def periodic():
"""
This is the periodic method. It gets called rapidly to update graphics,
animations, and physics.
"""
delta_time = clock.getDelta()
update_physics(delta_time)
if time.time() - program_start > LOAD_TIME:
npc_row_mixer.update(delta_time)
try:
scene.getObjectByName('ufo').rotation.z += 0.03
except:
pass
controls.update()
renderer.render(scene, camera)
timer.set_timeout(periodic, 1000 / FPS)
def on_load():
gus = get_gus_object()
gus.position.set(6, 15, 2)
gus_body = init_physics_box(gus, 10)
def on_contact(e):
print('CONTACT')
gus_body.addEventListener('collide', on_contact)
#-----------------------------------------
Main code
#-----------------------------------------
setup_main_scene()
loader = three.OBJLoader.new()
loader.load('https://thomasp850.github.io/temporary_hosting/ufo.obj', add_ufo)
timer.set_timeout(on_load, LOAD_TIME * 1000)`
The text was updated successfully, but these errors were encountered: