Isometric view in three.js

Hii,
I had created a solution where we can draw a rectangle dynamically in XY and XYZ plane.
i can draw recatangle in xy plane but when i change the plane to xyz then i can not able to draw properly.

HERE are the images.

js webgl - orbit controls2017-12-15 17_01_27-2017-12-15 17_02_20-

Here is the code

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <title>three.js webgl - orbit controls</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <style>
        body {
            color: #000;
            font-family: Monospace;
            font-size: 13px;
            text-align: center;
            font-weight: bold;
            background-color: #fff;
            margin: 0px;
            overflow: hidden;
        }

        #info {
            color: #000;
            position: absolute;
            top: 0px;
            width: 100%;
            padding: 5px;
        }

        a {
            color: red;
        }
    </style>
</head>
<body>
    <div id="container">


    </div>
    <div id="info">
        <input type="button" value="PlaneXY" onclick='changePlaneXY()' />
        <input type="button" value="PlaneXYZ" onclick='changePlaneXYZ()' />
        <input type="button" value="CANCEL" onclick='Cancel()' />
        <a href="http://threejs.org" target="_blank">three.js</a> - orbit controls example
    </div>
  
    <script src="~/THREE/three.js"></script>
    <script src="~/THREE/stats.min.js"></script>
    <script src="~/THREE/OrbitControls.js"></script>
    <script src="~/THREE/Detector.js"></script>
    <script src="~/THREE/jQuery-2.1.3.min.js"></script>
    <script>

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

        var stats;

        var camera, controls, scene, renderer, Rectangle, mouse = new THREE.Vector3(), count = 0;
        var planes =
            {
                XY: 0,
                XZ: 1,
                YZ: 2,
                XYZ: 3,

            }

        var GlobalVariable =
            {
                Gplanes: planes.XY,
                // Gplanes: planes.YZ,

            }

        var ShapeClass = function () {

            this.Name = 'ShapeBaseClass';
            this.geometry = new THREE.BufferGeometry();
            this.gripPoints = [];

            var MAX_POINTS = 500;
            var positions = new Float32Array(MAX_POINTS * 3);
            this.geometry.addAttribute('position', new THREE.BufferAttribute(positions, 3));
            this.material = new THREE.LineBasicMaterial({ color: 'black' });
            //this.Clickstatus = _clickstatus.Default;
            this.geometry.verticesNeedUpdate = true;
            this.geometry.attributes.position.array.dynamic = true;
            this.geometry.computeBoundingSphere();
            this.color;

            Object.defineProperty(this, "Color",
                {

                    get: function () {
                        return this.color;
                    },

                    set: function (color) {

                        this.material.color.set(color);
                        this.color = color;
                    }

                })


            THREE.Line.call(this, this.geometry, this.material);


        }

        ShapeClass.prototype = Object.create(THREE.Line.prototype);

        ShapeClass.prototype.setVertice = function (index, position) {
            var positions = this.geometry.attributes.position.array;
            var pontx = position.x;
            var ponty = position.y;
            if (index != 0) {
                switch (GlobalVariable.Gplanes) {
                    case planes.XY:
                        positions[index * 3 + 0] = position.x;
                        positions[index * 3 + 1] = position.y;
                        positions[index * 3 + 2] = 0;
                        break;
                    case planes.XZ:
                        positions[index * 3 + 0] = position.x;
                        positions[index * 3 + 1] = 0;
                        positions[index * 3 + 2] = position.z;
                        break;
                    case planes.YZ:
                        positions[index * 3 + 0] = 0;
                        positions[index * 3 + 1] = position.y;
                        positions[index * 3 + 2] = position.z;
                        break;
                    case planes.XYZ:
                        positions[index * 3 + 0] = position.x;
                        positions[index * 3 + 1] = position.y;
                        positions[index * 3 + 2] = 0;
                        break;

                    default:
                }

                this.geometry.attributes.position.needsUpdate = true;
                this.geometry.computeBoundingSphere();
            }
        }

        ShapeClass.prototype.updateVertices = function (index, position) {
            var pointsArray = this.geometry.attributes.position.array;

            switch (GlobalVariable.Gplanes) {
                case planes.XY:
                    pointsArray[3 * index + 0] = position.x;
                    pointsArray[3 * index + 1] = position.y;
                    pointsArray[3 * index + 2] = 0;
                    break;
                case planes.XZ:
                    pointsArray[3 * index + 0] = position.x;
                    pointsArray[3 * index + 1] = 0;
                    pointsArray[3 * index + 2] = position.z;
                    break;
                case planes.YZ:
                    pointsArray[3 * index + 0] = 0;
                    pointsArray[3 * index + 1] = position.y;
                    pointsArray[3 * index + 2] = position.z;
                    break;
                case planes.XYZ:
                    pointsArray[3 * index + 0] = position.x;
                    pointsArray[3 * index + 1] = position.y;
                    pointsArray[3 * index + 2] = 0;
                    break;
                default:
                    break;
            }

            this.geometry.attributes.position.needsUpdate = true;
            this.geometry.computeBoundingSphere();
            this.Vertices[index] = { x: position.x, y: position.y, z: position.z };

            //if (this.ShapeName == 'DCircle' || this.ShapeName == 'DArc') {
            //    this.center = getMidpoint(new THREE.Vector3(pointsArray[0], pointsArray[1], 0), new THREE.Vector3(pointsArray[3 * 180 + 0], pointsArray[3 * 180 + 1], 0), 0);
            //}

        }

        var RectangleClass = function (Id) {
            this.Points = [];
            this.shapeType = 'Rectangle';
            this.shapeName = "Rectangle" + Id;
            this.verticecount = 0;
            this.noOfClicks = 2;
            this.firstcornerpt;
            this.secondcornerpt;
            this.Firstentertext = "Specify First Corner:";
            this.Secondentertext = "Specify Second Corner:";
            this.firstText = false;
            this.secondText = false;

            this.FirstPointText = function (_drawingSurface, object) {
                this.firstText = true;

                (GlobalVariable.Gplanes == planes.XY ? object.Points.z = 0 : (GlobalVariable.Gplanes == planes.XZ ? object.Points.y = 0 : (GlobalVariable.Gplanes == planes.YZ ? object.Points.x = 0 : object.Points)));

                this.firstcornerpt = object.Points;

                object.Drawer.mouseDownPosition = object.Points;

                object.Drawer.dObject.Clickstatus = _clickstatus.Firstclick;


                $("#" + _drawingSurface.commandT).text('Specify the Next Corner:');
                return 'First Corner : ' + object.Points.x.toFixed(4) + ', ' + object.Points.y.toFixed(4) + ', ' + object.Points.z.toFixed(4) + '';
            }

            this.SecondPointText = function (_drawingSurface, object) {
                this.secondText = true;
                (GlobalVariable.Gplanes == planes.XY ? object.Points.z = 0 : (GlobalVariable.Gplanes == planes.XZ ? object.Points.y = 0 : (GlobalVariable.Gplanes == planes.YZ ? object.Points.x = 0 : object.Points)));
                object.Drawer.mouseDownPosition = object.Points;
                this.secondcornerpt = object.Points;


                object.Drawer.dObject.Clickstatus = _clickstatus.secondClick;

                $("#" + _drawingSurface.commandT).text('Command:');
                this.MakeRectangle(this.firstcornerpt, this.secondcornerpt);
                return 'Second Corner : ' + object.Points.x.toFixed(4) + ', ' + object.Points.y.toFixed(4) + ', ' + object.Points.z.toFixed(4) + '';
            }


            Object.defineProperty(this, 'Vertices',
                {
                    get: function () {
                        return this.Points;
                    },

                    set: function (position) {
                        var positions = this.geometry.attributes.position.array;

                        this.verticecount = this.Vertices.length;

                        switch (GlobalVariable.Gplanes) {
                            case planes.XY:
                                positions[this.verticecount * 3 + 0] = position.x;
                                positions[this.verticecount * 3 + 1] = position.y;
                                positions[this.verticecount * 3 + 2] = 0;

                                positions[(this.verticecount + 1) * 3 + 0] = position.x;
                                positions[(this.verticecount + 1) * 3 + 1] = position.y;
                                positions[(this.verticecount + 1) * 3 + 2] = 0;
                                break;
                            case planes.XZ:
                                positions[this.verticecount * 3 + 0] = position.x;
                                positions[this.verticecount * 3 + 1] = 0;
                                positions[this.verticecount * 3 + 2] = position.z;

                                positions[(this.verticecount + 1) * 3 + 0] = position.x;
                                positions[(this.verticecount + 1) * 3 + 1] = 0;
                                positions[(this.verticecount + 1) * 3 + 2] = position.z;
                                break;
                            case planes.YZ:
                                positions[this.verticecount * 3 + 0] = 0;
                                positions[this.verticecount * 3 + 1] = position.y;
                                positions[this.verticecount * 3 + 2] = position.z;

                                positions[(this.verticecount + 1) * 3 + 0] = 0;
                                positions[(this.verticecount + 1) * 3 + 1] = position.y;
                                positions[(this.verticecount + 1) * 3 + 2] = position.z;
                                break;
                            case planes.XYZ:
                                positions[this.verticecount * 3 + 0] = position.x;
                                positions[this.verticecount * 3 + 1] = position.y;
                                positions[this.verticecount * 3 + 2] = 0;

                                positions[(this.verticecount + 1) * 3 + 0] = position.x;
                                positions[(this.verticecount + 1) * 3 + 1] = position.y;
                                positions[(this.verticecount + 1) * 3 + 2] = 0;
                                break;

                            default:
                        }


                        this.geometry.setDrawRange(0, this.verticecount + 2);

                        this.geometry.attributes.position.needsUpdate = true;
                        this.geometry.computeBoundingSphere();

                        this.Points.push(new THREE.Vector3(positions[this.verticecount * 3 + 0], positions[this.verticecount * 3 + 1], positions[this.verticecount * 3 + 2]));
                    }
                });


            //this.Clickstatus = _clickstatus.Default;

            this.MakeRectangle = function (Hitpoint, MouseMovePoint) {

                switch (GlobalVariable.Gplanes) {
                    case planes.XY:

                        Hitpoint = new THREE.Vector3(Hitpoint.x, Hitpoint.y, 0);
                        MouseMovePoint = new THREE.Vector3(MouseMovePoint.x, MouseMovePoint.y, 0);

                        break;
                    case planes.XZ:

                        Hitpoint = new THREE.Vector3(Hitpoint.x, Hitpoint.z, 0);
                        MouseMovePoint = new THREE.Vector3(MouseMovePoint.x, MouseMovePoint.z, 0);
                        break;
                    case planes.YZ:

                        Hitpoint = new THREE.Vector3(Hitpoint.y, Hitpoint.z, 0);
                        MouseMovePoint = new THREE.Vector3(MouseMovePoint.y, MouseMovePoint.z, 0);
                        break;
                    case planes.XYZ:
                        // camera.position.set(1000, 1000, 0);
                        // camera.up = new THREE.Vector3(0, 0, 1);
                        Hitpoint = new THREE.Vector3(Hitpoint.x, Hitpoint.y, 0);
                        MouseMovePoint = new THREE.Vector3(MouseMovePoint.x, MouseMovePoint.y, 0);
                        break;
                    default:
                        break;

                }
                //Hitpoint = Math.round(Hitpoint.y) == 0 ? new THREE.Vector3(Hitpoint.x, Hitpoint.z, 0) : new THREE.Vector3(Hitpoint.x, Hitpoint.y, 0);
                //MouseMovePoint = Math.round(MouseMovePoint.y) == 0 ? new THREE.Vector3(MouseMovePoint.x, MouseMovePoint.z, 0) : new THREE.Vector3(MouseMovePoint.x, MouseMovePoint.y, 0);

                var Pointzeroth = new THREE.Vector3();
                var Pointthird = new THREE.Vector3();

                Pointzeroth.x = Hitpoint.x < MouseMovePoint.x ? Hitpoint.x : MouseMovePoint.x;
                Pointzeroth.y = Hitpoint.y > MouseMovePoint.y ? Hitpoint.y : MouseMovePoint.y;
                Pointzeroth.z = 0;

                Pointthird.x = Hitpoint.x > MouseMovePoint.x ? Hitpoint.x : MouseMovePoint.x;
                Pointthird.y = Hitpoint.y < MouseMovePoint.y ? Hitpoint.y : MouseMovePoint.y;
                Pointthird.z = 0;

                switch (GlobalVariable.Gplanes) {
                    case planes.XY:

                        this.updateVertices(0, new THREE.Vector3(Pointzeroth.x, Pointzeroth.y, 0));
                        this.updateVertices(1, new THREE.Vector3(Pointthird.x, Pointzeroth.y, 0));
                        this.updateVertices(2, new THREE.Vector3(Pointthird.x, Pointthird.y, 0));
                        this.updateVertices(3, new THREE.Vector3(Pointzeroth.x, Pointthird.y, 0));
                        this.updateVertices(4, new THREE.Vector3(Pointzeroth.x, Pointzeroth.y, 0));
                        break;
                    case planes.XZ:

                        this.updateVertices(0, new THREE.Vector3(Pointzeroth.x, 0, Pointzeroth.y));
                        this.updateVertices(1, new THREE.Vector3(Pointthird.x, 0, Pointzeroth.y));
                        this.updateVertices(2, new THREE.Vector3(Pointthird.x, 0, Pointthird.y));
                        this.updateVertices(3, new THREE.Vector3(Pointzeroth.x, 0, Pointthird.y));
                        this.updateVertices(4, new THREE.Vector3(Pointzeroth.x, 0, Pointzeroth.y));
                        break;
                    case planes.YZ:

                        this.updateVertices(0, new THREE.Vector3(0, Pointzeroth.x, Pointzeroth.y));
                        this.updateVertices(1, new THREE.Vector3(0, Pointthird.x, Pointzeroth.y));
                        this.updateVertices(2, new THREE.Vector3(0, Pointthird.x, Pointthird.y));
                        this.updateVertices(3, new THREE.Vector3(0, Pointzeroth.x, Pointthird.y));
                        this.updateVertices(4, new THREE.Vector3(0, Pointzeroth.x, Pointzeroth.y));
                        break;
                    case planes.XYZ:
                        this.updateVertices(0, new THREE.Vector3(Pointzeroth.x, Pointzeroth.y, 0));
                        this.updateVertices(1, new THREE.Vector3(Pointthird.x, Pointzeroth.y, 0));
                        this.updateVertices(2, new THREE.Vector3(Pointthird.x, Pointthird.y, 0));
                        this.updateVertices(3, new THREE.Vector3(Pointzeroth.x, Pointthird.y, 0));
                        this.updateVertices(4, new THREE.Vector3(Pointzeroth.x, Pointzeroth.y, 0));
                        camera.lookAt(scene.position);
                        //this.updateVertices(0, new THREE.Vector3(Pointzeroth.x, Pointzeroth.y, 0));
                        //this.updateVertices(1, new THREE.Vector3(Pointthird.x, Pointzeroth.y, 0));
                        //this.updateVertices(2, new THREE.Vector3(Pointthird.x, Pointthird.y, 0));
                        //this.updateVertices(3, new THREE.Vector3(Pointzeroth.x, Pointthird.y, 0));
                        //this.updateVertices(4, new THREE.Vector3(Pointzeroth.x, Pointzeroth.y, 0));

                        //this.updateVertices(0, new THREE.Vector3(Pointzeroth.x, Pointzeroth.y, 100));
                        //this.updateVertices(1, new THREE.Vector3(Pointthird.x, Pointzeroth.y, 100));
                        //this.updateVertices(2, new THREE.Vector3(Pointthird.x, Pointthird.y, 100));
                        //this.updateVertices(3, new THREE.Vector3(Pointzeroth.x, Pointthird.y, 100));
                        //this.updateVertices(4, new THREE.Vector3(Pointzeroth.x, Pointzeroth.y, 100));
                        break;
                    default:
                }
                //this.updateVertices(0, new THREE.Vector3(Pointzeroth.x, Pointzeroth.y, 0));
                //this.updateVertices(1, new THREE.Vector3(Pointthird.x, Pointzeroth.y, 0));
                //this.updateVertices(2, new THREE.Vector3(Pointthird.x, Pointthird.y, 0));
                //this.updateVertices(3, new THREE.Vector3(Pointzeroth.x, Pointthird.y, 0));
                //this.updateVertices(4, new THREE.Vector3(Pointzeroth.x, Pointzeroth.y, 0));

                //this.updateVertices(0, new THREE.Vector3(Pointzeroth.x, 0, Pointzeroth.y));
                //this.updateVertices(1, new THREE.Vector3(Pointthird.x, 0, Pointzeroth.y));
                //this.updateVertices(2, new THREE.Vector3(Pointthird.x, 0, Pointthird.y));
                //this.updateVertices(3, new THREE.Vector3(Pointzeroth.x, 0, Pointthird.y));
                //this.updateVertices(4, new THREE.Vector3(Pointzeroth.x, 0, Pointzeroth.y));

                //this.height = DistanceBetweenTwoPoints(this.Vertices[1], this.Vertices[2]);
                //this.width = DistanceBetweenTwoPoints(this.Vertices[0], this.Vertices[1]);
                this.geometry.setDrawRange(0, 5);
                this.geometry.computeBoundingSphere();

                //this.updateVertices(0, new THREE.Vector3(Hitpoint.x, Hitpoint.y, 0));
                //this.updateVertices(1, new THREE.Vector3(MouseMovePoint.x, Hitpoint.y, 0));
                //this.updateVertices(2, new THREE.Vector3(MouseMovePoint.x, MouseMovePoint.y, 0));
                //this.updateVertices(3, new THREE.Vector3(Hitpoint.x, MouseMovePoint.y, 0));
                //this.updateVertices(4, new THREE.Vector3(Hitpoint.x, Hitpoint.y, 0));
            }
            ShapeClass.call(this);
        }

        RectangleClass.prototype = Object.create(ShapeClass.prototype);
        RectangleClass.prototype.ShapeName = "DRectangle";

        init();
        animate();

        function init() {

            scene = new THREE.Scene();
            scene.fog = new THREE.FogExp2(0xcccccc, 0.002);

            renderer = new THREE.WebGLRenderer();
            renderer.setClearColor(scene.fog.color);
            renderer.setPixelRatio(window.devicePixelRatio);
            renderer.setSize(window.innerWidth, window.innerHeight);

            var container = document.getElementById('container');

            container.addEventListener("mousemove", onMouseMove, false);
            container.addEventListener('mousedown', onMouseDown, false);
            container.addEventListener('mousewheel', onMouseWheel, false);
            container.style.cursor = 'crosshair';

            container.appendChild(renderer.domElement);
           

            //camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);

            camera = new THREE.OrthographicCamera(window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, 1, 10000); //PerspectiveCamera(viewAngle, w / h, near, far)
            camera.position.z = 1000;


            controls = new THREE.OrbitControls(camera, renderer.domElement);
            //controls.addEventListener( 'change', render ); // add this only if there is no animation loop (requestAnimationFrame)

            controls.enableDamping = true;
            controls.dampingFactor = 0.25;
            controls.enableZoom = true;
            controls.enableRotate = false;



            light = new THREE.DirectionalLight(0xffffff);
            light.position.set(1, 1, 1);
            scene.add(light);

            light = new THREE.DirectionalLight(0x002288);
            light.position.set(-1, -1, -1);
            scene.add(light);

            light = new THREE.AmbientLight(0x222222);
            scene.add(light);



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


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

        }

        function onWindowResize() {

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

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

        }

        function animate() {

            requestAnimationFrame(animate);

            controls.update();

            stats.update();

            render();

        }

        function render() {

            renderer.render(scene, camera);
            camera.lookAt(scene.position);
        }

        function onMouseMove(event) {
            mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
            mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
            mouse.z = 0;
            mouse.unproject(camera);
            mouse.z = 0;

            if (Rectangle != undefined)
                Rectangle.MakeRectangle(mousedown, mouse);

            controls.update();

            stats.update();


        }

        function onMouseDown(event) {
            if (event.which == 3) return;
            count++;
            hitpoint = new THREE.Vector3();
            hitpoint.x = (event.clientX / window.innerWidth) * 2 - 1;
            hitpoint.y = -(event.clientY / window.innerHeight) * 2 + 1;
            hitpoint.z = 0;
            hitpoint.unproject(camera);

            hitpoint.z = 0;
            if (count == 1) {

                mousedown = hitpoint;
                Rectangle = new RectangleClass();
                Rectangle.MakeRectangle(hitpoint, mouse);
                scene.add(Rectangle);
            }
            else if (count == 2) {

                Cancel();

            }

            controls.update();

            stats.update();


        }


        function onMouseWheel() {


        }

        function changePlaneXY() {

            camera.position.set(0, 0, 10000);


        }

        function changePlaneXYZ() {

            //camera.position.x = 100;
            //camera.position.y = 100;
            //camera.position.z = 100;
            //controls.enabled = false;
            GlobalVariable.Gplanes = planes.XYZ
            camera.position.set(1000, 1000, 1000);

            camera.up = new THREE.Vector3(0, 0, -1);
            //camera.lookAt(scene.position);
            //  camera.rotation.order = 'YZX';
            //camera.rotation.y = 90 * (Math.PI / 180);
            //camera.rotation.x = 90 * (Math.PI / 180);
            //camera.rotation.z = 0;

            //camera.rotateOnAxis(new THREE.Vector3(0, 0, 1), (120 * (Math.PI / 180)));
            //camera.rotateOnAxis(new THREE.Vector3(0, 1, 0), (120 * (Math.PI / 180)));
            //camera.rotateOnAxis(new THREE.Vector3(1, 0, 0), (45 * (Math.PI / 180)));
            //camera.rotation.x = Math.atan(-1 / Math.sqrt(2));
            //camera.rotation.z = 30 * (Math.PI / 180);
            //camera.updateProjectionMatrix();
            //  controls.update();

            stats.update();

            render();
        }

        function Cancel() {

            Rectangle.geometry.setDrawRange(0, 5);
            Rectangle.geometry.attributes.position.needsUpdate = true;
            Rectangle.geometry.computeBoundingSphere();
            Rectangle = undefined;
            count = 0;
        }




    </script>
</body>
</html>

Thanks & regards
Akshay

Just a small remark.

var positions = this.geometry.attributes.position.array;
. . .
case planes.XY:
    positions[index * 3 + 0] = position.x;
    positions[index * 3 + 1] = position.y;
    positions[index * 3 + 2] = 0;
    break;

It can be simplied to

case planes.XY:
  this.geometry.attributes.position.setXYZ(index, position.x, position.y, 0);
  break;

and so on for the rest of lines where you manage the data in THREE.BufferAttribute().

And about your question, take a look at this SO thread.
There are 2 approaches of how to draw a rectangle on a plane. Also, they use THREE.Raycaster() and its .setFromCamera() method to get points for a rectangle. The difference is that both of approaches was made for rectangles of a usual geometry, not a buffer geometry.

@dev just a remark on formatting - when you are sharing large blocks of code here, you can wrap them in three backticks:

    ``` 
    // your long 
    // piece of
    // code
    ```

Anything you paste between the backticks will have its original formatting preserved.
I’ve updated your post above to use these.

1 Like