javascript 更改 Three.js collada 对象的纹理和颜色
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15025319/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Changing texture and color on Three.js collada object
提问by psychok7
I recently got three.js example from the official site working with my collada objects (.dae) using the ColladaLoader.js
.
Now my question is, how do i change the loaded collada object color attribute and add a custom texture?? I tried adding the texture with no luck yet.
我最近从官方网站获得了 Three.js 示例,使用ColladaLoader.js
. 现在我的问题是,如何更改加载的 collada 对象颜色属性并添加自定义纹理?我尝试添加纹理但没有运气。
Here is my code (slightly changed from the original example):
这是我的代码(与原始示例略有不同):
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 );
}
}
采纳答案by psychok7
After many problems, we wrote a small hack in ColladaLoader.js taking the idea from @gaitat witch basically replaces the old path to the textures from the images, passing some new ones in an array, and using regular expressions to parse the xml for the .png or .jpg under images tag. Not sure if there is an easier way but since support was limited we had to come up with a fix somehow
很多问题之后,我们在 ColladaLoader.js 中写了一个小技巧,从@gaitat 女巫的想法基本上替换了从图像到纹理的旧路径,在数组中传递一些新的,并使用正则表达式来解析 xml 以获取图片标签下的 .png 或 .jpg。不确定是否有更简单的方法,但由于支持有限,我们不得不以某种方式提出解决方案
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;
};
回答by yaku
You can override your collada scene materials recursively with this kind of function. It goes through the whole hierarchy and assigns a material.
您可以使用这种功能递归地覆盖您的 collada 场景材料。它遍历整个层次结构并分配材质。
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);
}
}
}
Use it like setMaterial(dae, new THREE.MeshBasicMaterial({color: 0xff0000}));
使用它就像 setMaterial(dae, new THREE.MeshBasicMaterial({color: 0xff0000}));
You could probably adapt that to modify the existing material properties instead of assigning a new one, if needed.
如果需要,您可能可以调整它来修改现有的材料属性,而不是分配一个新的属性。
回答by gaitat
One thing you can do is modify your collada model (dae file) locate the texture reference there and change it to your liking.
您可以做的一件事是修改您的 collada 模型(dae 文件),在那里找到纹理参考并根据您的喜好进行更改。
回答by ddd
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
}