Chris Perry
Chris Perry

Reputation: 35

Rotate object with random matrix (Three.js)

I am trying to create a die in Three.js that will randomly rotate on click however I am having trouble getting the axis values to update on click. This is where I am at so far.

<style type="text/css" media="screen">
    html, body, canvas {
        margin: 0;
        padding: 0;
        background: #4e6171;
        color: black;
    }
    canvas {
        width: 100%;
        height: 100%;
    }
</style>

<body onload="animateScene();">
  <div id="container"></div>
  <script type="text/javascript" src="js/three.min.js"></script>
  <script type="text/javascript" src="js/Detector.js"></script>
  <script type="text/javascript">
    if (!Detector.webgl) Detector.addGetWebGLMessage();
  </script>
  <script type="text/javascript" src="js/TrackballControls.js"></script>
  <script type="text/javascript" src="js/setup.js"></script>


<script type="text/javascript">

function animateScene() {
    var objectX = Math.floor(Math.random() * 20);
    var objectY = Math.floor(Math.random() * 20);
    var objectZ = Math.floor(Math.random() * 20);


    var radius = 30;
    radius *= 1;

    var material = new THREE.MeshBasicMaterial({
        color: 0xe2e2e2,
        transparent: true,
        opacity: 1
    });

    var geometry = new THREE.IcosahedronGeometry(radius, 0);
    var object = new THREE.Mesh(geometry, material);
    var edges = new THREE.EdgesHelper(object, 0xffffff);

    edges.material.linewidth = 2;

    scene.add(object);
    scene.add(edges);
    scene.add(new THREE.AxisHelper(100));

    object.rotation.x = objectX;
    object.rotation.y = objectY;
    object.rotation.z = objectZ;

    controls.enabled = false;

};

</script>
<button class="button" onclick="object.updateMatrix();">Generate</button>
</body>

I would like to be able to click the object and have it animate a rotation with the newly updated random axis coordinates. Currently I am getting an "object is undefined" error.

I was unable to get a fiddle working but here is a link.

Any help is appreciated, thanks.

Upvotes: 1

Views: 1822

Answers (2)

Chris Perry
Chris Perry

Reputation: 35

UPDATE

So I had a breakthrough last night and was able to get exactly what i'm looking for. I ended up creating another function within the scene that generates new x and y values and then updates the matrix. I handled the animation with tween.js. Also I bound the click event inside of the animateScene function as apposed to an onClick outside.

Big Thanks to Tim for the guidance on this one.

<body onload="animateScene();">
<div id="container"></div>
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
<script type="text/javascript" src="js/three.min.js"></script>
<script type="text/javascript" src="js/tween.min.js"></script>
<script type="text/javascript" src="js/Detector.js"></script>
<script type="text/javascript">
    if (!Detector.webgl) Detector.addGetWebGLMessage();
</script>
<script type="text/javascript" src="js/TrackballControls.js"></script>
<script type="text/javascript" src="js/setup.js"></script>
<script type="text/javascript">

    var object

    function animateScene() {


        var radius = 30;
        radius *= 1;

        var material = new THREE.MeshBasicMaterial({
            color: 0xe2e2e2,
            transparent: true,
            opacity: 1
        });

        var geometry = new THREE.IcosahedronGeometry(radius, 0);
        var object = new THREE.Mesh(geometry, material);
        var edges = new THREE.EdgesHelper(object, 0xffffff);

        edges.material.linewidth = 2;

        scene.add(object);
        scene.add(edges);
        scene.add(new THREE.AxisHelper(100));

        controls.enabled = false;


        function rollDice() {

            var x = Math.floor(Math.random() * (14 - 7) + 7);
            var y = Math.floor(Math.random() * (14 - 7) + 7);


           var tween = new TWEEN.Tween(object.rotation)
              .to({ x, y }, 500)
              .start();

           animate();

           function animate() {
              requestAnimationFrame(animate);
              TWEEN.update();

           }

        }

        $( "#click" ).click(rollDice);

    }



</script>
<button class="button" id="click">Generate</button>
</body>

Upvotes: 0

Tim
Tim

Reputation: 88

There are two problems here that I see:

  1. Your "object" variable is defined within the scope of the animateScene() function, and that is why you are getting the "object is undefined" error. You could define object (with "var object") outside of the function, and then it would be in the global scope, or you could attach the onClick callback within the animateScene function.
  2. Even if you fixed the scoping problem, the object would not rotate, since you only set the rotation once, in animateScene(). You would instead need to generate new random values for X, Y, and Z, and then call object.updateMatrix().

Hope that helps!

Upvotes: 0

Related Questions