         # get the best-possible THREE.js renderer (once and for all)
         # based on Detector.js's webgl detection
         try
-            if window.WebGLRenderingContext
+            if @WebGLRenderingContext
                 canvas = document.createElement 'canvas'
                 if canvas.getContext('webgl') or canvas.getContext('experimental-webgl')
                     dynamic_renderer_type = 'webgl'

###############################################################################

if not document?
    document = window.document

math3d = (window.math3d ?= {})
        
trunc = (s, max_length) ->
    if not s?
        return s
    if not max_length?
        max_length = 1024
    if s.length > max_length
        s.slice(0, max_length-3) + "..."
    else
        s

# Returns a new object with properties determined by those of obj1 and
# obj2.  The properties in obj1 *must* all also appear in obj2.  If an
# obj2 property has value "defaults.required", then it must appear in
# obj1.  For each property P of obj2 not specified in obj1, the
# corresponding value obj1[P] is set (all in a new copy of obj1) to
# be obj2[P].
defaults = (obj1, obj2, allow_extra) ->
    if not obj1?
        obj1 = {}
    error = ->
        try
            s = "(obj1=#{trunc(JSON.stringify(obj1),1024)}, obj2=#{trunc(JSON.stringify(obj2),1024)})"
            #console.log s
            return s
        catch error
            return ""
    if typeof(obj1) isnt 'object'
        # We put explicit traces before the errors in this function,
        # since otherwise they can be very hard to debug.
        console.trace()
        throw "defaults -- TypeError: function takes inputs as an object #{error()}"
    r = {}
    for prop, val of obj2
        if obj1.hasOwnProperty(prop) and obj1[prop]?
            if obj2[prop] is defaults.required and not obj1[prop]?
                console.trace()
                throw "defaults -- TypeError: property '#{prop}' must be specified: #{error()}"
            r[prop] = obj1[prop]
        else if obj2[prop]?  # only record not undefined properties
            if obj2[prop] is defaults.required
                console.trace()
                throw "defaults -- TypeError: property '#{prop}' must be specified: #{error()}"
            else
                r[prop] = obj2[prop]
    if not allow_extra
        for prop, val of obj1
            if not obj2.hasOwnProperty prop
                console.trace()
                throw "defaults -- TypeError: got an unexpected argument '#{prop}' #{error()}"
    return r

# WARNING -- don't accidentally use this as a default:
required = defaults.required = "__!!!!!!this is a required property!!!!!!__"

component_to_hex = (c) ->
    hex = c.toString 16
    if hex.length is 1
        "0" + hex
    else
        hex

rgb_to_hex = (r, g, b) -> "#" + component_to_hex(r) + component_to_hex(g) + component_to_hex(b)

_loading_threejs_callbacks = []

math3d.threejs_src = "http://cdnjs.cloudflare.com/ajax/libs/three.js/r68/three.min.js"
math3d.orbitcontrols_src = "OrbitControls.js"

remove_element = (element) ->
    if element is null
        return
    if (parent = element.parentElement) is null
        return
    parent.removeChild element

loadScript = (script_src, callback) ->
    run_callback = true

    script = document.createElement 'script'
    script.type = 'text/javascript'
    script.async = true
    script.src = script_src

    script.onload = ->
            remove_element script

        else
            f()

    render_scene: (force = false) ->
        if @renderer_type is 'static'
            console.log 'render static -- todo'
