Skip to content

Commit 281c00c

Browse files
author
Jason Grout
committed
Initial pass at rendering system for scene graphs. Requires changes in Sage.
1 parent 409061b commit 281c00c

File tree

6 files changed

+194
-99
lines changed

6 files changed

+194
-99
lines changed

graphics.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ def add(self, graphics3d, **kwds):
9898
kwds = graphics3d._process_viewing_options(kwds)
9999
self._frame = kwds.get('frame',False)
100100
self._graphics.append(graphics3d)
101-
self.send('add', {'obj':graphics3d_to_jsonable(graphics3d),
101+
obj = graphics3d_to_jsonable(graphics3d)
102+
self.send('add', {'obj': obj,
102103
'wireframe':jsonable(kwds.get('wireframe'))})
103104
self.set_frame(draw = self._frame) # update the frame
104105
def render_scene(self, force=True):
@@ -156,6 +157,9 @@ def jsonable(x):
156157
return x
157158

158159
def graphics3d_to_jsonable(p):
160+
return p.scenetree_json()
161+
162+
def old_graphics3d_to_jsonable(p):
159163

160164
obj_list = []
161165

handlers.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
}
2424
except ImportError:
2525
trait_names = {}
26-
from misc import json_default, Timer, Config
26+
from misc import sage_json, Timer, Config
2727
config = Config()
2828
import logging
2929
logger = logging.getLogger('sagecell')
@@ -481,8 +481,8 @@ def _json_msg(self, msg):
481481
"""
482482
# can't encode buffers, so let's get rid of them if they exist
483483
msg.pop("buffers", None)
484-
# json_default handles things like encoding dates
485-
return jsonapi.dumps(msg, default=json_default)
484+
# sage_json handles things like encoding dates and sage types
485+
return jsonapi.dumps(msg, default=sage_json)
486486

487487
def _on_zmq_reply(self, msg_list):
488488
try:

misc.py

+9-2
Original file line numberDiff line numberDiff line change
@@ -184,11 +184,18 @@ def reset_kernel_timeout(timeout):
184184
def javascript(code):
185185
sys._sage_.display_message({'application/javascript': code, 'text/plain': 'javascript code'})
186186

187-
def json_default(obj):
187+
188+
def sage_json(obj):
189+
import sage.all
188190
if isinstance(obj, datetime):
189191
return obj.isoformat()
192+
elif isinstance(obj, sage.rings.integer.Integer):
193+
return int(obj)
194+
elif isinstance(obj, (sage.rings.real_mpfr.RealLiteral, sage.rings.real_mpfr.RealNumber, sage.rings.real_double.RealDoubleElement)):
195+
return float(obj)
190196
else:
191-
raise TypeError, 'Object of type %s with value of %s is not JSON serializable' % (type(obj), repr(obj))
197+
raise TypeError("Object of type %s with value of %s is not JSON serializable" % (type(obj), repr(obj)))
198+
192199
##########################################
193200
## Unit Testing Misc Functions
194201
##########################################

receiver.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import zmq
33
from zmq import ssh
44
import sys
5-
from misc import Timer
5+
from misc import Timer, sage_json
66

77
class Receiver(object):
88
def __init__(self, filename, ip, tmp_dir):
@@ -266,6 +266,11 @@ def send_message(stream, msg_type, content, parent, **kwargs):
266266
ka.kernel.session.send(stream, msg_type, content=content, parent=parent, **kwargs)
267267
_sage_.send_message = send_message
268268

269+
# Enable Sage types to be sent via session messages
270+
import zmq
271+
from zmq.utils import jsonapi
272+
ka.kernel.session.pack = lambda x: jsonapi.dumps(x, default=sage_json)
273+
269274
sys._sage_ = _sage_
270275
user_ns = ka.kernel.shell.user_module.__dict__
271276
#ka.kernel.shell.user_ns = ka.kernel.shell.Completer.namespace = user_ns

static/3d.coffee

+73-38
Original file line numberDiff line numberDiff line change
@@ -203,18 +203,35 @@ class SalvusThreeJS
203203
@camera.up = new THREE.Vector3(0,0,1)
204204

205205
set_light: (color= 0xffffff) =>
206-
ambient = new THREE.AmbientLight(0x404040)
206+
ambient = new THREE.AmbientLight(0xdddddd)
207207
@scene.add( ambient )
208-
directionalLight = new THREE.DirectionalLight( 0xffffff )
209-
directionalLight.position.set( 100, 100, 100 ).normalize()
208+
directionalLight = new THREE.DirectionalLight(0xffffff, 0.8)
209+
directionalLight.position.set( 1, 1, 1 )
210210
@scene.add( directionalLight )
211-
directionalLight = new THREE.DirectionalLight( 0xffffff )
212-
directionalLight.position.set( -100, -100, -100 ).normalize()
211+
directionalLight = new THREE.DirectionalLight(0xffffff, 0.8)
212+
directionalLight.position.set( -1, -1, -1 )
213213
@scene.add( directionalLight )
214214
@light = new THREE.PointLight(0xffffff)
215215
@light.position.set(0,10,0)
216216

217-
add_text: (opts) =>
217+
make_material: (opts) =>
218+
o = defaults opts,
219+
opacity: 1
220+
ambient: 0x222222
221+
diffuse: 0x222222
222+
specular: 0xffffff
223+
color: required
224+
emmissive: 0x222222
225+
shininess: 100
226+
overdraw: true
227+
polygonOffset: true
228+
polygonOffsetFactor: 1
229+
polygonOffsetUnits: 1
230+
#side: THREE.DoubleSide
231+
o.transparent = o.opacity < 1
232+
return new THREE.MeshPhongMaterial(o)
233+
234+
make_text: (opts) =>
218235
o = defaults opts,
219236
pos : [0,0,0]
220237
text : required
@@ -260,7 +277,6 @@ class SalvusThreeJS
260277
else
261278
@_text.push(sprite)
262279

263-
@scene.add(sprite)
264280
return sprite
265281

266282
add_line : (opts) =>
@@ -273,7 +289,7 @@ class SalvusThreeJS
273289
for a in o.points
274290
geometry.vertices.push(new THREE.Vector3(a[0],a[1],a[2]))
275291
line = new THREE.Line(geometry, new THREE.LineBasicMaterial(color:opts.color, linewidth:o.thickness))
276-
@scene.add(line)
292+
return line
277293

278294
add_point: (opts) =>
279295
o = defaults opts,
@@ -286,9 +302,30 @@ class SalvusThreeJS
286302
geometry = new THREE.SphereGeometry(Math.sqrt(o.size)/50,16,16)
287303
sphere = new THREE.Mesh(geometry, material);
288304
sphere.position.set(o.loc[0], o.loc[1], o.loc[2])
289-
@scene.add(sphere)
305+
return sphere
306+
307+
make_sphere: (opts) =>
308+
o = defaults opts,
309+
radius: 1
310+
position: [0,0,0]
311+
return new THREE.SphereGeometry(o.radius, 20, 20)
290312

291-
add_obj: (myobj, opts)=>
313+
make_group: (opts) =>
314+
o = defaults opts,
315+
matrix : [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
316+
children : required
317+
obj = new THREE.Object3D()
318+
m = o.matrix
319+
obj.matrixAutoUpdate = false # tell three.js to not update the matrix based on position, rotation, etc.
320+
obj.matrix.set(m[0], m[1], m[2], m[3],
321+
m[4], m[5], m[6], m[7],
322+
m[8], m[9], m[10], m[11],
323+
m[12], m[13], m[14], m[15])
324+
obj.add(@make_object(i)) for i in o.children
325+
return obj
326+
327+
######
328+
add_index_face_set: (myobj, opts)=>
292329
vertices = myobj.vertex_geometry
293330
for objects in [0..myobj.face_geometry.length-1]
294331
face3 = myobj.face_geometry[objects].face3
@@ -374,7 +411,8 @@ class SalvusThreeJS
374411
mesh = THREE.SceneUtils.createMultiMaterialObject(geometry, multiMaterial);
375412

376413
mesh.position.set(0,0,0)
377-
@scene.add(mesh)
414+
return mesh
415+
##########
378416

379417
# always call this after adding things to the scene to make sure track
380418
# controls are sorted out, etc. Set draw:false, if you don't want to
@@ -456,7 +494,9 @@ class SalvusThreeJS
456494
return (z*1).toString()
457495

458496
txt = (x,y,z,text) =>
459-
@_frame_labels.push(@add_text(pos:[x,y,z], text:text, fontsize:o.fontsize, color:o.color, constant_size:false))
497+
t = @make_text(pos:[x,y,z], text:text, fontsize:o.fontsize, color:o.color, constant_size:false)
498+
@_frame_labels.push(t)
499+
@scene.add(t)
460500

461501
offset = 0.075
462502
mx = (o.xmin+o.xmax)/2
@@ -488,39 +528,34 @@ class SalvusThreeJS
488528
if o.draw
489529
@render_scene()
490530

531+
make_object: (obj) =>
532+
handlers =
533+
text: @make_text
534+
index_face_set: @make_index_face_set
535+
line: @make_line
536+
point: @make_point
537+
sphere: @make_sphere
538+
type = obj.type
539+
delete obj.type
540+
o = false
541+
if type == 'group'
542+
o = @make_group(obj)
543+
else if type == 'object'
544+
geometry_type = obj.geometry.type
545+
delete obj.geometry.type
546+
geometry = handlers[geometry_type](obj.geometry)
547+
material = @make_material(obj.texture)
548+
o = new THREE.Mesh(geometry, material)
549+
return o
550+
491551
add_3dgraphics_obj: (opts) =>
492552
opts = defaults opts,
493553
obj : required
494554
wireframe : false
495555

496-
for o in opts.obj
497-
switch o.type
498-
when 'text'
499-
@add_text
500-
pos:o.pos
501-
text:o.text
502-
color:o.color
503-
fontsize:o.fontsize
504-
fontface:o.fontface
505-
constant_size:o.constant_size
506-
when 'index_face_set'
507-
@add_obj(o, opts)
508-
if o.mesh and not o.wireframe # draw a wireframe mesh on top of the surface we just drew.
509-
o.color='#000000'
510-
o.wireframe = o.mesh
511-
@add_obj(o, opts)
512-
when 'line'
513-
delete o.type
514-
@add_line(o)
515-
when 'point'
516-
delete o.type
517-
@add_point(o)
518-
else
519-
console.log("ERROR: no renderer for model number = #{o.id}")
520-
return
556+
@scene.add(@make_object(opts.obj))
521557
@render_scene(true)
522558

523-
524559
animate: () =>
525560
if @_animate
526561
@_animation_frame = requestAnimationFrame(@animate)

0 commit comments

Comments
 (0)