• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

Objekt um seine eigene Achse rotieren lassen (three.js)

ullidrachenfels

New member
Ich hab ein Problem, ein Objekt in three.js um seine eigene Achse rotieren zu lassen.
Zwar gibt es hier eine Erklärung: https://github.com/mrdoob/three.js/issues/910
und auch hier: https://gist.github.com/clavis-magna/4138387
Leider bin ich ich da zu schlecht, um daraus wirklich eine Lösung für mein Problem zu erkennen.
Hier mein Quelltext:
HTML:
<!DOCTYPE html>
<html lang="de">
	<head>
		<title>Planeten - Erde</title>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
		<link href="css/style.css" rel="stylesheet">
	</head>

	<body class="ship">
<div class="details">
		<div id="info">
			<p>Erde</p>
		</div>
			
		<script src="http://cdnjs.cloudflare.com/ajax/libs/three.js/r68/three.min.js"></script>

		<script src="js/loaders/OBJLoader.js"></script>

		<script src="js/Detector.js"></script>
		<script src="js/libs/stats.min.js"></script>

		<script>

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

			var container, stats;

			var camera, scene, renderer;
			var particleLight, pointLight;
			
			var windowHalfX = window.innerWidth / 1;
			var windowHalfY = window.innerHeight / 1;
			
			var clock = new THREE.Clock();
			var morphs = [];

			
			init();
			animate();

			
			function init() {

				container = document.createElement( 'div' );
				document.body.appendChild( container );
				scene = new THREE.Scene();
				camera = new THREE.PerspectiveCamera(25, window.innerWidth / window.innerHeight, 2, 2000 );
				camera.position.set( 2, 4, 5 );
				
				//var rotation = 6;

				scene.add( camera );

				// scene

				var ambient = new THREE.AmbientLight( 0x101030 );
				scene.add( ambient );

				var directionalLight = new THREE.DirectionalLight( 0xffeedd );
				directionalLight.position.set( 2, 0, 2 );
				scene.add( directionalLight );

				var axisHelper = new THREE.AxisHelper(800); // 500 is size
				this.scene.add(axisHelper);
				
				// texture

				var manager = new THREE.LoadingManager();
				manager.onProgress = function ( item, loaded, total ) {

					console.log( item, loaded, total );

				};

				
				var loader = new THREE.ImageLoader( manager );
				loader.load( 'images/3d/textures/EARTH.JPG', function ( image ) {

					texture.image = image;
					texture.needsUpdate = true;


				} );
				
				// model
				var texture = new THREE.Texture();


				var loader = new THREE.OBJLoader( manager );
				loader.load( 'images/3d/universe-m.obj', function ( object ) {

					object.traverse( function ( child ) {

						if ( child instanceof THREE.Mesh ) {

							child.material.map = texture;

						}

					} );

					object.scale.x = object.scale.y = object.scale.z = 0.025;
					object.position.x = -1;
					obj = object;
					scene.add( obj );
					
				} );

				//

				renderer = new THREE.WebGLRenderer();
				renderer.setSize(800, 600);
				container.appendChild( renderer.domElement );

				//

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

			}
			//

			function onWindowResize( event ) {

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

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

			}

			//

			function animate(){
				
			// note: three.js includes requestAnimationFrame shim
				requestAnimationFrame( animate );
				var delta = clock.getDelta();

				// animate Collada model

				THREE.AnimationHandler.update( delta );

				if ( morphs.length ) {

					for ( var i = 0; i < morphs.length; i ++ )
						morphs[ i ].updateAnimation( 2000 * delta );

				}

				render();
				}
 
			function render(){
				
				var timer = Date.now() * 0.0001;

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

				camera.lookAt( scene.position );
			renderer.render( scene, camera );
			}
			
		</script>
</div>
		
	</body>
</html>
Im Moment dreht sich mein Objekt um die Welt-Achse und nicht um die eigene.
Vielleicht hat sich ja schonmal jemand mit dem Problem beschäftigt.
Würde mich über jede Hilfe freuen.

Gruß,

Ulli
 
Zuletzt bearbeitet von einem Moderator:
Hallo Ulli,

leider ist three.js sehr komplex, so das ich dir da nicht sonderlich weit helfen kann.

Ich habe aber mal ein einfaches, funktionierendes Beispiel rausgesucht:

Code:
<body>
  <h1>Liquid Three.js Cube</h1>
  <p>Change the browser's window size.</p>
  <script src="https://rawgithub.com/mrdoob/three.js/master/build/three.js"></script> <!-- Get the latest version of the Three.js library. -->
  <script>
    var scene = new THREE.Scene(); // Create a Three.js scene object.
    var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); // Define the perspective camera's attributes.

    var renderer = window.WebGLRenderingContext ? new THREE.WebGLRenderer() : new THREE.CanvasRenderer(); // Fallback to canvas renderer, if necessary.
    renderer.setSize(window.innerWidth, window.innerHeight); // Set the size of the WebGL viewport.
    document.body.appendChild(renderer.domElement); // Append the WebGL viewport to the DOM.

    var geometry = new THREE.CubeGeometry(20, 20, 20); // Create a 20 by 20 by 20 cube.
    var material = new THREE.MeshBasicMaterial({ color: 0x0000FF }); // Skin the cube with 100% blue.
    var cube = new THREE.Mesh(geometry, material); // Create a mesh based on the specified geometry (cube) and material (blue skin).
    scene.add(cube); // Add the cube at (0, 0, 0).

    camera.position.z = 50; // Move the camera away from the origin, down the positive z-axis.

    var render = function () {
      cube.rotation.x += 0.01; // Rotate the sphere by a small amount about the x- and y-axes.
      cube.rotation.y += 0.01;

      renderer.render(scene, camera); // Each time we change the position of the cube object, we must re-render it.
      requestAnimationFrame(render); // Call the render() function up to 60 times per second (i.e., up to 60 animation frames per second).
    };

    render(); // Start the rendering of the animation frames.
  </script>
</body>

ansonsten findest du weiterführende Infos dazu hier: Einfache 3D-Grafiken mit "Three.js" (Windows)

Eine gute Doku (aber auf englisch) zu three.js findet man hier: three.js - documentation

Dort findest du unterthree.js - examples auch einige Beispiele.


Hoffe, es hilft irgendwie weiter, ansonsten musst du bitte etwas Gedult haben, bis die Experten, hesst oder kkapsner online kommen.
 
Jo, erstmal vielen Dank. Die Doku und die Beispiele kenne ich schon alle. Und die Doku ist übrigens anerkanntermaßen nicht gut.
Was die Beispiele anbetrifft, da gibt es jede Menge Objekte die scheinbar um die eigene Achse rotieren.
Das liegt aber glaube ich nur daran, das die Größe des Canvas und des Objektes quasi übereinstimmen.
Nimmt man den selben Code mit meinem Objekt, rotiert mein Objekt erkennbar um die Weltachse und nicht um die Objektachse.
Einfachste Lösung wäre natürlich, mein Objekt anzupassen. Allerdings müsste dann auch die Funktion Resize raus, und die brauche ich.
Von daher muss ich eine Lösung finden, wie man das Objekt um seine eigene Achse rotieren lässt.
Da ich aber eher aus dem PHP-Bereich komme, fällt mir das doch einigermaßen schwer.

Von daher übe ich mich in Gedult.........:D

Gruß,

Ulli
 
Du drehst in deinem Code ja auch nicht das Objekt, sondern fährst die Kamera durch die Gegend. Wenn du dein Objekt drehen willst, musst du dessen Ausrichtung in der render()-Funktion ändern und nicht camera.

Da ich aber von Three.js keine Ahnung hab', kann ich dir nicht sagen wie das genau geht. Vom Prinzip her müsstest du die Koordinaten aller Vertices deines Objektes erst mal in das zentrale Koordinatensystem des Objektes transformieren, dann eine Drehmatrix anwenden, wieder in das Koordinatensystem der "Welt" rücktransformieren und dann wieder in das Objekt reinschreiben.
 
Also es gibt eine Lösung und so sieht sie aus:

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

			var container, stats;
			var camera, scene, renderer, objects;
			var particleLight, pointLight;
			var dae;

			// Collada model

			var loader = new THREE.ColladaLoader();
			loader.options.convertUpAxis = true;
			loader.load( 'models/erde.dae', function ( collada ) {

				dae = collada.scene;


				dae.scale.x = dae.scale.y = dae.scale.z = 0.005;
				dae.position.x = 1;
				dae.position.y = 3;
				dae.updateMatrix();
				scene = new THREE.Scene(); // initiiert die Szene
  				scene.add(dae);
				init();
				animate();

			} );

			function init() {

				container = document.createElement( 'div' );
				document.body.appendChild( container );
				container.className = 'canvas';

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

				scene = new THREE.Scene();
				scene.fog = new THREE.FogExp2( 0x000000, 0.1000 );

				scene.add( dae );

				scene.add( new THREE.AmbientLight( 0xffffff, 1 ) );

				pointLight = new THREE.PointLight( 0xff4400, 0.1, 10 );
				pointLight.position.set( 50, 50, 50 );
				scene.add( pointLight );

				// Renderer

				renderer = new THREE.WebGLRenderer({antialias	: true});
				//renderer.setSize( window.innerWidth, window.innerHeight );
				renderer.setSize( 800, 600 );
				container.appendChild( renderer.domElement );

				// Stats

				stats = new Stats();
				container.appendChild( stats.domElement );

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

			}


			function onWindowResize( event ) {

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

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

			}


			function animate() {

				requestAnimationFrame( animate );

				dae.rotation.y += 0.0005;
				render();
				stats.update();

			}



			function render() {

				renderer.render( scene, camera );

			}

Gefunden in einem älteren C'T Artikel.
Danke für alle Tips.

Gruß,

Ulli
 
Schön, dass es jetzt geht, aber so wirklich optimal ist der Code nicht. Alleine schon die ganzen globalen Variablen... und scene wird zwei mal initialisiert.

Und so wie ich das sehe, drehst du auch nicht dein Objekt, sondern "nur" die Subscene... aber wenn es so aussieht, wie du es gerne hättest...
 
Jo, danke für den Hinweis. Da sieht man das ich keine Ahnung habe.

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

			// Collada model

			var loader = new THREE.ColladaLoader();
			loader.options.convertUpAxis = true;
			loader.load( 'models/earth.dae', function ( collada ) {
		
				dae = collada.scene;


				dae.scale.x = dae.scale.y = dae.scale.z = 0.005;
				dae.position.x = 1;
				dae.position.y = 3;
				dae.updateMatrix();
				scene = new THREE.Scene(); // initiiert die Szene
  				scene.add(dae);

				init();
				animate();

			} );
			
			
			function init() {

				container = document.createElement( 'div' );
				document.body.appendChild( container );
				container.className = 'canvas';

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

				scene.fog = new THREE.FogExp2( 0x000000, 0.3000 );
				scene.add( new THREE.AmbientLight( 0xffffff, 0.1 ) );

				pointLight = new THREE.PointLight( 0xff4400, 0.1, 1 );
				pointLight.position.set( 10, 10, 10 );
				scene.add( pointLight );

				// Renderer

				renderer = new THREE.WebGLRenderer({antialias	: true});
				renderer.setSize( 800, 600 );
				container.appendChild( renderer.domElement );
				renderer.shadowMapEnabled	= true;

				// Stats

				stats = new Stats();
				container.appendChild( stats.domElement );

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

			}


			function onWindowResize( event ) {

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

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

			}


			function animate() {

				requestAnimationFrame( animate );

				dae.rotation.y += 0.0005;
				render();
				stats.update();

			}


			function render() {

				renderer.render( scene, camera );

			}
So sieht es jetzt aus. Hoffe so ist es korrekt.
Allerdings, was die Rotation anbetrifft, so dreht sich nach meinem Verständnis (dae.rotation.y), was ja genau dem Objekt entspricht.
Vielen Dank nochmal an alle.

Gruß,

Ulli
 
Wie schon gesagt, die ganzen globalen Variablen sind nicht gut.
Aber wenn alles so läuft, wie du es gerne hättest, ist ja dein Problem gelöst - ob jetzt eine Subscene oder wirklich das Objekt gedreht wird ist im Grunde genommen egal.

PS: Ich würde vielleicht die render() Funktion entfernen, da da ja nur eine Anweisung drin ist.
 
Ich meine nicht, dass du die Funktion komplett entfernen sollst, sondern die eine Codezeile, die drin steht, anstelle des Aufrufs (ist ja nur eine Stelle) von render() hinschreiben.
 
Okay, ich hab 2 Funktionen:
HTML:
function animate() {

				requestAnimationFrame( animate );

				dae.rotation.y += 0.0005;
				render();
				stats.update();
			}

und
HTML:
function render() {

				renderer.render( scene, camera );

			}
In animate wird render aufgerufen.
Und in render passiert nicht mehr, als das der WebGLRenderer aufgerufen wird mit ( scene, camera ).
Wenn ich die Zeile: renderer.render( scene, camera );
in die animate packe statt des aufrufs: render();
dann funktioniert das.
Ich nehme an, das meinstest Du?

Gruß,

Ulli
 
Zurück
Oben