#29 ✓resolved
lindsay.kay (at xeolabs)

SceneJS.loadCollada not reusing loaded asset - keeps reloading

Reported by lindsay.kay (at xeolabs) | April 20th, 2010 @ 10:53 AM | in V0.7.3

Comments and changes to this ticket

  • lindsay.kay (at xeolabs)
  • lindsay.kay (at xeolabs)

    lindsay.kay (at xeolabs) April 21st, 2010 @ 12:41 AM

    Cause

    In V0.7.2, when two or more SceneJS.load (or SceneJS.loadCollada) nodes refer to the same URL, then the first one one loads that content into the scene graph and caches the content's subgraph against the URL. Then subsequent scene SceneJS.load nodes with the same URL will just reuse that subgraph - an application of the FlyWeight pattern.

    This test, with four references to the same asset, should render three ducks in a row:

    
     SceneJS.translate({x: -200},
       SceneJS.loadCollada({
          uri: "http://www.scenejs.org/library/v0.7/assets/examples/collada-duck/duck.dae"
          })),
     SceneJS.translate({x: 0},                                                     
       SceneJS.loadCollada({
          uri: "http://www.scenejs.org/library/v0.7/assets/examples/collada-duck/duck.dae"
          showBoundingBoxes: true
          })),
     SceneJS.translate({x: 200},
       SceneJS.loadCollada({
          uri: "http://www.scenejs.org/library/v0.7/assets/examples/collada-duck/duck.dae" 
          }))
    

    However, it actually renders all three ducks on top of each other, all at X==(-200.O).

    When I designed this asset Flyweight-style reuse, I forgot that nodes are actually statefull when they memoise things. In this case the modelling transform nodes within the subgraph for the duck asset are memoising their matrices. When the subgraph first renders for first instance, it creates it's modelling matrices once and for all, then since the wrapping translate transform is static, it assumes it appears only once in the scene (it has no way of knowing that it appears three more times) and never recomputes the matrices.

    Solution

    Abandon the Flyweight pattern for loaded subgraphs and always reload a new subgraph for each repeated URL. This is not so bad with respect to scene processing efficiency, because reuse is still happening efficiently on the next level down, among cached geometry buffers and textures. It does force a reload/reparse for each of the instances - imagine the penalty for 500 chairs on the deck of a cruise ship; a load/parse for each. This can be mitigated by introducing the ability to instance "symbols" (like instances of COLLADA library components) like below:

    
     SceneJS.symbol({name: "duck"},
         SceneJS.translate(function(data) { 
               return { x: data.get("x") };
           },
           SceneJS.loadCollada({
               uri: "http://www.scenejs.org/library/v0.7/assets/examples/collada-duck/duck.dae"      
               }))),
    
     SceneJS.withdata({ x: -100) },
         SceneJS.instance({name: "duck" })),
    
     SceneJS.withdata({ x: -100) },
         SceneJS.instance({name: "duck" })),
    
     SceneJS.withdata({ x: 100) },
         SceneJS.instance({name: "duck" })))
    

    This requires new symbol and instance nodes, which is actually something I was had intended anyway.

  • lindsay.kay (at xeolabs)

    lindsay.kay (at xeolabs) April 21st, 2010 @ 02:13 AM

    • State changed from “open” to “resolved”

    Regression Test

    Should see four ducks, two with bounding boxes:

    http://www.scenejs.org/ide.html?url=http://www.scenejs.org/library/...

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile ยป

SceneJS provides easy access to WebGL through a simple and declarative JavaScript API. The SceneJS API is functional, which enables its scene definitions to be really compact and expressive, while hooking into other JavaScript code just that little bit more smoothly.

Shared Ticket Bins

People watching this ticket

Pages