2013-02-22 15 views
8

Niedawno otrzymałem przykład z pliku three.js z oficjalnej strony pracującej z moimi obiektami collada (.dae) przy użyciu ColladaLoader.js. Teraz moje pytanie brzmi: jak mogę zmienić załadowany atrybut koloru obiektu collada i dodać niestandardową teksturę ?? Próbowałem dodać teksturę bez szczęścia.Zmiana tekstury i koloru na obiekcie colladura Three.js

Tu jest mój kodu (nieco zmieniony z oryginalnego przykład):

function load_model(el) { 

      if (! Detector.webgl) Detector.addGetWebGLMessage(); 

      var container, stats; 

      var camera, scene, renderer, objects; 
      var particleLight, pointLight; 
      var dae, skin; 

      var loader = new THREE.ColladaLoader(); 
      loader.options.convertUpAxis = true; 
      loader.load('/site_media/models/model.dae', function (collada) { 
       dae = collada.scene; 
       skin = collada.skins[ 0 ]; 

       dae.scale.x = dae.scale.y = dae.scale.z = 0.90; 
       dae.updateMatrix(); 

       init(el); 
       animate(); 

      }); 

      function init(el) { 

       container = document.createElement('div'); 
       el.append(container); 

       camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 1, 2000); 
       camera.position.set(2, 2, 3); 

       scene = new THREE.Scene(); 


       scene.add(dae); 

       particleLight = new THREE.Mesh(new THREE.SphereGeometry(4, 8, 8), new THREE.MeshBasicMaterial({ color: 0xffffff })); 
       scene.add(particleLight); 

       // Lights 

       scene.add(new THREE.AmbientLight(0xcccccc)); 

       var directionalLight = new THREE.DirectionalLight(/*Math.random() * 0xffffff*/0xeeeeee); 
       directionalLight.position.x = Math.random() - 0.5; 
       directionalLight.position.y = Math.random() - 0.5; 
       directionalLight.position.z = Math.random() - 0.5; 
       directionalLight.position.normalize(); 
       scene.add(directionalLight); 

       // pointLight = new THREE.PointLight(0xffffff, 4); 
       // pointLight.position = particleLight.position; 
       // scene.add(pointLight); 

       renderer = new THREE.WebGLRenderer(); 
       renderer.setSize(window.innerWidth/2, window.innerHeight/2); 


       container.appendChild(renderer.domElement); 

       stats = new Stats(); 
       stats.domElement.style.position = 'absolute'; 
       stats.domElement.style.top = '0px'; 
       container.appendChild(stats.domElement); 

       // 

       window.addEventListener('resize', onWindowResize, false); 

      } 

      function onWindowResize() { 

       camera.aspect = window.innerWidth/window.innerHeight; 
       camera.updateProjectionMatrix(); 

       renderer.setSize(window.innerWidth/2, window.innerHeight/2); 

      } 

      // 

      var t = 0; 
      var clock = new THREE.Clock(); 

      function animate() { 

       var delta = clock.getDelta(); 

       requestAnimationFrame(animate); 

       if (t > 1) t = 0; 

       if (skin) { 

        // guess this can be done smarter... 

        // (Indeed, there are way more frames than needed and interpolation is not used at all 
        // could be something like - one morph per each skinning pose keyframe, or even less, 
        // animation could be resampled, morphing interpolation handles sparse keyframes quite well. 
        // Simple animation cycles like this look ok with 10-15 frames instead of 100 ;) 

        for (var i = 0; i < skin.morphTargetInfluences.length; i++) { 

         skin.morphTargetInfluences[ i ] = 0; 

        } 

        skin.morphTargetInfluences[ Math.floor(t * 30) ] = 1; 

        t += delta; 

       } 

       render(); 
       stats.update(); 

      } 

      function render() { 

       var timer = Date.now() * 0.0005; 

       camera.position.x = Math.cos(timer) * 10; 
       camera.position.y = 2; 
       camera.position.z = Math.sin(timer) * 10; 

       camera.lookAt(scene.position); 

       particleLight.position.x = Math.sin(timer * 4) * 3009; 
       particleLight.position.y = Math.cos(timer * 5) * 4000; 
       particleLight.position.z = Math.cos(timer * 4) * 3009; 

       renderer.render(scene, camera); 

      } 


} 
+0

Możliwa duplikat [Jak skonfigurować materiały w Three.js podczas ładowania Collada (DAE) modele ?] (http://stackoverflow.com/questions/8281681/how-to-setup-materials-in-three-js-when-loading-collada-dae-models) –

Odpowiedz

2

Po wielu problemach napisaliśmy mały hack w ColladaLoader.js, podając ideę z @gaitat w zasadzie zastępuje starą ścieżkę do tekstur z obrazów, przekazując kilka nowych w tablicy i używając wyrażeń regularnych do przeanalizuj xml dla tagu .png lub .jpg under images. Nie wiem, czy istnieje prostszy sposób, ale ponieważ było ograniczone wsparcie musieliśmy wymyślić fix jakoś

function parse(doc, imageReplace, callBack, url) { 

    COLLADA = doc; 
    callBack = callBack || readyCallbackFunc; 

    if (url !== undefined) { 

     var parts = url.split('/'); 
     parts.pop(); 
     baseUrl = (parts.length < 1 ? '.' : parts.join('/')) + '/'; 

    } 

    parseAsset(); 
    setUpConversion(); 
    images = parseLib("//dae:library_images/dae:image", _Image, "image"); 

    for(var i in imageReplace) { 
     var iR = imageReplace[i]; 

     for(var i in images) { 
      var image = images[i]; 

      var patt=new RegExp('[a-zA-Z0-9\-\_]*\/'+iR.name,'g'); 

      //if(image.id==iR.id) 
      if(patt.test(image.init_from)) 
       image.init_from = iR.new_image; 
     }//for 
    } 

    materials = parseLib("//dae:library_materials/dae:material", Material, "material"); 
    effects = parseLib("//dae:library_effects/dae:effect", Effect, "effect"); 
    geometries = parseLib("//dae:library_geometries/dae:geometry", Geometry, "geometry"); 
    cameras = parseLib(".//dae:library_cameras/dae:camera", Camera, "camera"); 
    controllers = parseLib("//dae:library_controllers/dae:controller", Controller, "controller"); 
    animations = parseLib("//dae:library_animations/dae:animation", Animation, "animation"); 
    visualScenes = parseLib(".//dae:library_visual_scenes/dae:visual_scene", VisualScene, "visual_scene"); 

    morphs = []; 
    skins = []; 

    daeScene = parseScene(); 
    scene = new THREE.Object3D(); 

    for (var i = 0; i < daeScene.nodes.length; i ++) { 

     scene.add(createSceneGraph(daeScene.nodes[ i ])); 

    } 

// unit conversion 
scene.position.multiplyScalar(colladaUnit); 
scene.scale.multiplyScalar(colladaUnit); 

    createAnimations(); 

    var result = { 

     scene: scene, 
     morphs: morphs, 
     skins: skins, 
     animations: animData, 
     dae: { 
      images: images, 
      materials: materials, 
      cameras: cameras, 
      effects: effects, 
      geometries: geometries, 
      controllers: controllers, 
      animations: animations, 
      visualScenes: visualScenes, 
      scene: daeScene 
     } 

    }; 

    if (callBack) { 

     callBack(result); 

    } 

    return result; 

}; 
+0

Możesz zaakceptować własną odpowiedź. – WestLangley

1

Jedną rzeczą, jaką można zrobić, to zmodyfikować swój model Collada (dae plik) zlokalizować odniesienia tekstury tam i zmienić go do swoich potrzeb.

+0

kinda potrzebują dynamicznego rozwiązania – psychok7

8

Możesz zastąpić rekursywnie materiały ze sceny collada za pomocą tego rodzaju funkcji. Przechodzi przez całą hierarchię i przypisuje materiał.

var setMaterial = function(node, material) { 
    node.material = material; 
    if (node.children) { 
    for (var i = 0; i < node.children.length; i++) { 
     setMaterial(node.children[i], material); 
    } 
    } 
} 

Używaj go jak setMaterial(dae, new THREE.MeshBasicMaterial({color: 0xff0000}));

Prawdopodobnie mógł przystosować że zmodyfikować istniejące właściwości materiału zamiast przypisywania nowego, jeśli to konieczne.

+0

gdzie powinienem dodać ten kod? – psychok7

+0

Powinieneś wywołać funkcję wewnątrz loader.load, powołaj nowe materiały po załadowaniu collada. Właściwie możesz to zrobić w dowolnym momencie po załadowaniu collada, jeśli chcesz dynamicznie zmieniać materiały. A sama funkcja może być wszędzie. – yaku

+0

tak, działa to dla koloru. czy to działa również na teksturę? jeśli tak, w jaki sposób? – psychok7

0
if (url !== undefined) { 
    var parts = url.split('/'); 
    parts.pop(); 
    baseUrl = (parts.length < 1 ? '.' : parts.join('/')) + '/'; 

} 

parseAsset(); 
setUpConversion(); 
images = parseLib("//dae:library_images/dae:image", _Image, "image"); 

for(var i in imageReplace) { 
    var iR = imageReplace[i]; 

    for(var i in images) { 
     var image = images[i]; 

     var patt=new RegExp('[a-zA-Z0-9\-\_]*\/'+iR.name,'g'); 

     //if(image.id==iR.id) 
     if(patt.test(image.init_from)) 
      image.init_from = iR.new_image; 
    }//for 
}