1

I've trying to draw the square wall by getting mouse clicks coordinates and extrude it. I've picking up the mouse coordinates by clicking at the scene.

var onDocumentMouseDown = function ( event ) 
    {
        //update the mouse variable
        mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
            mouse.y = -( event.clientY / window.innerHeight ) * 2 + 1;
        var vector = new THREE.Vector3(mouse.x, mouse.y, 0.5);
        vector.unproject( camera );
        var dir = vector.sub( camera.position ).normalize();
        var distance = - camera.position.z / dir.z;
        var pos = camera.position.clone().add( dir.multiplyScalar( distance));
        console.log('mouse_x ' + pos.x + ' mouse_y ' + pos.y);
        if (clickCount <= 3){
            coord[clickCount] = {'x' : pos.x, 'y' : pos.y};
            clickCount ++;
        } else {
        //make new wall and stop function
            newshape = new THREE.Shape();
            shape.moveTo(coord['0'].x ,coord['0'].y);
            shape.lineTo(coord['0'].x, coord['1'].y);
            shape.lineTo(coord['2'].x, +coord['2'].y);
            shape.lineTo(coord['3'].x, coord['3'].y);
            shape.lineTo(coord['0'].x, coord['0'].y);
            var newextrudeSettings = {
            //*******/
            };
        }

And when I've recived four coordinates, three.js throw the error:

Uncaught TypeError: Cannot read property 'length' of null at Object.triangulateShape (three.js:26140) at ExtrudeGeometry.addShape (three.js:26330) at ExtrudeGeometry.addShapeList (three.js:26235) at new ExtrudeGeometry (three.js:26211) at HTMLDocument.onDocumentMouseDown (script.js:116)

6
  • shape.lineTo(coord['0'].x, coord['1'].y);shouldn't it be as shape.lineTo(coord['1'].x, coord['1'].y);? and why not to use indices of elements as integers instead of strings: coord['0'].x -> coord[0].x, for example? Commented Mar 14, 2017 at 6:43
  • and what does +coord['2'].y mean? Commented Mar 14, 2017 at 10:39
  • coord -> is object of coords. coord['0'].x and coord['0'].y its first clicks coord. coord['0'] is name of fist item of object -- > shouldn't it be as shape.lineTo(coord['1'].x, coord['1'].y); Mayby, but in my other code it stell draw the rectangle wall Commented Mar 14, 2017 at 12:25
  • Yes, I got it. Can you make a jsfiddle or codepen example. I can't recreate your error. Though, I use THREE.Raycaster() and a plane to find points of intersection and build a THREE.ExtrudeGeometry(), so everything works totally fine in my code. Commented Mar 14, 2017 at 12:38
  • Yep, As soon as possible. I've recive the points of intersection, but when I trying to buil rectangle with shape.lineTo and ExtrudeGeometry it throw that error. jsfiddle, I'll make jsfiddle a little bit later. GIT from yesterday github.com/wwwork/three.js Commented Mar 14, 2017 at 15:28

1 Answer 1

1

To find points of intersection I prefer to use THREE.Raycaster() (though I've never used THREE.Projector() for this purpose).

This is the result of my code: enter image description here

I hope I got your conception. Thus, all the stuff you need is here:

var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var intersects;
var controlPoints = [];
var clickCount = 0;

function onMouseDown(event) {
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
  raycaster.setFromCamera(mouse, camera);
  intersects = raycaster.intersectObjects(objects); // objects is an array which contains just the mesh of the plane
  if (intersects.length > 0) { 
    if (clickCount <= 3) { // I took your idea of 4 clicks
      controlPoints[clickCount] = intersects[0].point.clone(); // add a control point to the array

      // visualization of a control point
      var cp = new THREE.Mesh(new THREE.SphereGeometry(0.125, 16, 12), new THREE.MeshBasicMaterial({color: "red"}));
      cp.position.copy(intersects[0].point);
      scene.add(cp);

      clickCount++;
    } else { // on the fifth click we'll create our wall
      shape = new THREE.Shape();
      shape.moveTo(controlPoints[0].x, -controlPoints[0].z);
      shape.lineTo(controlPoints[1].x, -controlPoints[1].z);
      shape.lineTo(controlPoints[2].x, -controlPoints[2].z);
      shape.lineTo(controlPoints[3].x, -controlPoints[3].z);
      shape.lineTo(controlPoints[0].x, -controlPoints[0].z);
      var extrudeSettings = {
        steps: 1,
        amount: 2,
        bevelEnabled: false
      };
      var extrudeGeom = new THREE.ExtrudeGeometry(shape, extrudeSettings);
      extrudeGeom.rotateX(-Math.PI / 2);
      var wall = new THREE.Mesh(extrudeGeom, new THREE.MeshStandardMaterial({
        color: "gray"
      }));
      scene.add(wall);
      controlPoints = []; // we clear the array of control points
      clickCount = 0; // and reset the counter of clicks
    };
  };
};

jsfiddle example. 4 clicks for setting control points, the fifth click creates a wall, and so on.

Sign up to request clarification or add additional context in comments.

2 Comments

I've seen that I've done the mistake. I've use variable of previously created shapes. And it works with THREE.Vector2() and THREE.Vector3 thanks. god bless you!
You're welcome) Mark the answer as accepted, please, if it solved your problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.