基于gl-martix矩阵库和canvas 2d实现3d效果

 

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/gl-matrix@3.0.0/gl-matrix.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/stats.js@0.17.0/build/stats.min.js"></script>
 
</head>

<body>
    <!--
        1.设置three.js渲染器
        2.设置摄像机camera
        3.设置场景scene
        4.设置光源light
        5.设置物体object
    -->
    <script>
        function inherits(childCtor, parentCtor) {
            childCtor.prototype = Object.create(parentCtor.prototype);
            childCtor.prototype.constructor = childCtor;
        }

        function makeFrustum(left, right, bottom, top, near, far) {

            var m, x, y, a, b, c, d;

            m = glMatrix.mat4.create();
            x = 2 * near / (right - left);
            y = 2 * near / (top - bottom);
            a = (right + left) / (right - left);
            b = (top + bottom) / (top - bottom);
            c = - (far + near) / (far - near);
            d = - 2 * far * near / (far - near);

            m.n11 = x; m.n13 = a;
            m.n22 = y; m.n23 = b;
            m.n33 = c; m.n34 = d;
            m.n43 = - 1; m.n44 = 0;

            return m;

        };

        function makePerspective(fov, aspect, near, far) {

            var ymax, ymin, xmin, xmax;

            ymax = near * Math.tan(fov * Math.PI / 360);
            ymin = - ymax;
            xmin = ymin * aspect;
            xmax = ymax * aspect;

            return makeFrustum(xmin, xmax, ymin, ymax, near, far);

        };

        /*
        摄像机:(从外面观看房间内部)
        *生成具有给定边界的透视投影矩阵。
       *为far传递空/未定义/无值将生成无限投影矩阵。
       *
           out	MAT4	mat4 frustum矩阵将被写入
           @param {number} fovy	数	垂直的视野在弧度
           @param {number} aspect	数	宽高比。通常视口宽度/高度
           @param {number} near	数	在截头体附近
           @param {number} far	数	截头锥体的远端,可以是null或无穷大
        */
        function Camera(fov, aspect, near, far) {
            this.position = glMatrix.vec3.fromValues(0, 0, 0);
            this.target = { position: glMatrix.vec3.fromValues(0, 0, 0) };
            //透视投影矩阵
            this.projectionMatrix = glMatrix.mat4.perspective([], fov, aspect, near, far);
            // this.projectionMatrix=makePerspective(fov,aspect,near,far)
            this.up = glMatrix.vec3.fromValues(0, 1, 0);
            this.matrix = glMatrix.mat4.create();

            this.autoUpdateMatrix = true;

            this.updateMatrix = function () {

                this.matrix = glMatrix.mat4.lookAt(this.matrix, this.position, this.target.position, this.up)
                //   this.matrix.lookAt( this.position, this.target.position, this.up );

            };
        }
        /*
        场景:(房间)
        */
        function Scene() {
            this.objects = [];
            this.add = function (object) {

                this.objects.push(object);

            };
        }
        /*
        光源:(房间里面的光)
        */
        function Light() {

        }

        function Color(hex) {
            var _r, _g, _b, _a;
            this.cssRgba = "rgba(0, 0, 0, 1)";

            var _hex;
            this.updateHex = function () {
                _hex = (Math.floor(_a * 255) << 24) | (_r << 16) | (_g << 8) | _b;
            }

            this.updateRGBA = function () {
                _r = _hex >> 16 & 0xff;
                _g = _hex >> 8 & 0xff;
                _b = _hex & 0xff;
                _a = (_hex >> 24 & 0xff) / 255;
            };
            this.setRGBA = function (r, g, b, a) {
                _r = r;
                _g = g;
                _b = b;
                _a = a;
                this.updateHex();
                this.updateStyleString();
            }
            this.setHex = function (hex) {
                _hex = hex;
                this.updateRGBA();
                this.updateStyleString();
            };
            this.updateStyleString = function () {
                this.cssRgba = 'rgba(' + _r + ',' + _g + ',' + _b + ',' + _a + ')';
            };
            this.setHex(hex);
        }
        function FaceColorFillMaterial() {

        }
        function ColorFillMaterial(hex, opacity) {

            this.color = new Color((opacity >= 0 ? (opacity * 0xff) << 24 : 0xff000000) | hex);

        };
        function ColorStrokeMaterial(lineWidth, hex, opacity) {
            this.lineWidth = lineWidth;
            ColorFillMaterial.call(this, hex, opacity)
        }
        function BitmapUVMappingMaterial() {

        }


        /*
        几何
        */
        function Geometry() {

            this.vertices = [];// 顶点
            this.faces = []; // 面
            this.uvs = [];

            this.computeNormals = function () {

                var v, f, vA, vB, vC, cb, ab, normal;

                for (v = 0; v < this.vertices.length; v++) {

                    this.vertices[v].normal.set(0, 0, 0);

                }

                for (f = 0; f < this.faces.length; f++) {

                    vA = this.vertices[this.faces[f].a];
                    vB = this.vertices[this.faces[f].b];
                    vC = this.vertices[this.faces[f].c];

                    cb = new THREE.Vector3();
                    ab = new THREE.Vector3();
                    normal = new THREE.Vector3();

                    cb.sub(vC.position, vB.position);
                    ab.sub(vA.position, vB.position);
                    cb.cross(ab);

                    if (!cb.isZero()) {

                        cb.normalize();

                    }

                    this.faces[f].normal = cb;

                    vA.normal.addSelf(normal);
                    vB.normal.addSelf(normal);
                    vC.normal.addSelf(normal);

                    if (this.faces[f] instanceof THREE.Face4) {

                        this.vertices[this.faces[f].d].normal.addSelf(normal);

                    }

                }

            };
        }

        /*
        @material 材料
        */
        function Object3D(material) {

            this.position = glMatrix.vec3.create();
            this.rotation = glMatrix.vec3.create();
            this.scale = glMatrix.vec3.fromValues(1, 1, 1);

            this.matrix = glMatrix.mat4.create();
            this.screen = glMatrix.vec3.create();

            this.material = material instanceof Array ? material : [material];
            this.overdraw = false;

            this.autoUpdateMatrix = true;

            this.updateMatrix = function () {

                glMatrix.mat4.identity(this.matrix);
                glMatrix.mat4.mul(this.matrix, this.matrix, glMatrix.mat4.translate([],glMatrix.mat4.create(),this.position));
                glMatrix.mat4.mul(this.matrix, this.matrix, glMatrix.mat4.rotateX([], glMatrix.mat4.create(), this.rotation[0]));
                glMatrix.mat4.mul(this.matrix, this.matrix, glMatrix.mat4.rotateY([], glMatrix.mat4.create(), this.rotation[1]));
                glMatrix.mat4.mul(this.matrix, this.matrix, glMatrix.mat4.rotateZ([], glMatrix.mat4.create(), this.rotation[2]));
                glMatrix.mat4.mul(this.matrix, this.matrix, glMatrix.mat4.scale([], glMatrix.mat4.create(), glMatrix.vec3.fromValues(this.scale[0], this.scale[1], this.scale[2])));

            };
        }
        function Mesh(geometry, material) {

            Object3D.call(this, material);
            this.geometry = geometry;
            this.doubleSided = false;

        };
        inherits(Mesh, Object3D);


        function Vertex(position, normal) {
            this.position = position || glMatrix.vec3.create();
            this.normal = normal || glMatrix.vec3.create();
            this.screen = glMatrix.vec3.create();
            this.__visible = true;
        }


        function Face3(a, b, c, normal, color) {

            this.a = a;
            this.b = b;
            this.c = c;

            this.normal = normal || glMatrix.vec3.create();
            this.screen = glMatrix.vec3.create();

            this.color = color || new Color(0x000000);



        };
        function Face4(a, b, c, d, normal, color) {

            this.a = a;
            this.b = b;
            this.c = c;
            this.d = d;

            this.normal = normal || glMatrix.vec3.create();
            this.screen = glMatrix.vec3.create();
            this.color = color || new Color(0x000000);


        };
        function RenderableFace3() {
            this.v1 = glMatrix.vec2.create();
            this.v2 = glMatrix.vec2.create();
            this.v3 = glMatrix.vec2.create();
            this.z = null;

            this.color = null;
            this.material = null;
        }
        function RenderableFace4() {
            this.v1 = glMatrix.vec2.create();
            this.v2 = glMatrix.vec2.create();
            this.v3 = glMatrix.vec2.create();
            this.v4 = glMatrix.vec2.create();

            this.z = null;

            this.color = null;
            this.material = null;
        }
        function Renderer() {
            var vector4 = new glMatrix.vec4.create();
            var matrix = new glMatrix.mat4.create();
            var face4Pool = [], face3Pool = [];
            this.renderList = null;
            function painterSort(a, b) {
                return b.z - a.z;
            }

            // 投影
            this.project = function (scene, camera) {
                this.renderList = [];
                if (camera.autoUpdateMatrix) {

                    camera.updateMatrix();

                }
                var objects = scene.objects, len = objects.length;
                var mesh, vertex, face;
                var i, j, verticesLength, facesLength;
                var v1, v2, v3, v4, face4count = 0, face3count = 0;
                for (i = 0; i < len; i++) {
                    object = objects[i];
                    if (object.autoUpdateMatrix) {

                        object.updateMatrix();

                    }
                    if (object instanceof Mesh) {

                        glMatrix.mat4.multiply(matrix, camera.matrix, object.matrix);

                        verticesLength = object.geometry.vertices.length;

                        for (j = 0; j < verticesLength; j++) {
                            vertex = object.geometry.vertices[j];
                            glMatrix.vec3.copy(vertex.screen, vertex.position)
                            glMatrix.vec3.transformMat4(vertex.screen, vertex.screen, matrix)
                            glMatrix.vec3.transformMat4(vertex.screen, vertex.screen, camera.projectionMatrix)
                            vertex.__visible = vertex.screen[2] > 0 && vertex.screen[2] < 1;
                            //  console.log(vertex.screen[2])
                            //console.log(vertex.screen[2] )
                        }

                        facesLength = object.geometry.faces.length;

                        for (j = 0; j < facesLength; j++) {

                            face = object.geometry.faces[j];

                            // TODO: Use normals for culling... maybe not?

                            if (face instanceof Face3) {

                                v1 = object.geometry.vertices[face.a];
                                v2 = object.geometry.vertices[face.b];
                                v3 = object.geometry.vertices[face.c];

                                if (v1.__visible && v2.__visible && v3.__visible && (object.doubleSided ||
                                    (v3.screen[0] - v1.screen[0]) * (v2.screen[1] - v1.screen[1]) -
                                    (v3.screen[1] - v1.screen[1]) * (v2.screen[0] - v1.screen[0]) > 0)) {

                                    face.screen[2] = Math.max(v1.screen[2], Math.max(v2.screen[2], v3.screen[2]));

                                    if (!face3Pool[face3count]) {

                                        face3Pool[face3count] = new RenderableFace3();

                                    }
                                    glMatrix.vec2.copy(face3Pool[face3count].v1, v1.screen);
                                    glMatrix.vec2.copy(face3Pool[face3count].v2, v2.screen)
                                    glMatrix.vec2.copy(face3Pool[face3count].v3, v3.screen);
                                    face3Pool[face3count].z = face.screen[2];
                                    // face3Pool[face3count].v1.x = v1.screen.x;
                                    // face3Pool[face3count].v1.y = v1.screen.y;
                                    // face3Pool[face3count].v2.x = v2.screen.x;
                                    // face3Pool[face3count].v2.y = v2.screen.y;
                                    // face3Pool[face3count].v3.x = v3.screen.x;
                                    // face3Pool[face3count].v3.y = v3.screen.y;
                                    // face3Pool[face3count].z = face.screen.z;

                                    face3Pool[face3count].material = object.material;
                                    face3Pool[face3count].overdraw = object.overdraw;
                                    face3Pool[face3count].uvs = object.geometry.uvs[j];
                                    face3Pool[face3count].color = face.color;

                                    this.renderList.push(face3Pool[face3count]);

                                    face3count++;
                                }

                            }
                            else if (face instanceof Face4) {


                                v1 = object.geometry.vertices[face.a];
                                v2 = object.geometry.vertices[face.b];
                                v3 = object.geometry.vertices[face.c];
                                v4 = object.geometry.vertices[face.d];

                                if (v1.__visible && v2.__visible && v3.__visible && v4.__visible && (object.doubleSided ||
                                    ((v4.screen[0] - v1.screen[0]) * (v2.screen[1] - v1.screen[1]) -
                                        (v4.screen[1] - v1.screen[1]) * (v2.screen[0] - v1.screen[0]) > 0 ||
                                        (v2.screen[0] - v3.screen[0]) * (v4.screen[1] - v3.screen[1]) -
                                        (v2.screen[1] - v3.screen[1]) * (v4.screen[0] - v3.screen[0]) > 0))) {
                                    //     console.log('vertices')
                                    face.screen[2] = Math.max(v1.screen[2], Math.max(v2.screen[2], Math.max(v3.screen[2], v4.screen[2])));

                                    if (!face4Pool[face4count]) {

                                        face4Pool[face4count] = new RenderableFace4();

                                    }

                                    glMatrix.vec2.copy(face4Pool[face4count].v1, v1.screen);
                                    glMatrix.vec2.copy(face4Pool[face4count].v2, v2.screen)
                                    glMatrix.vec2.copy(face4Pool[face4count].v3, v3.screen);
                                    glMatrix.vec2.copy(face4Pool[face4count].v4, v4.screen);
                                    face4Pool[face4count].z = face.screen[2];
                                    // face4Pool[face4count].v1[0] = v1.screen[0];
                                    // face4Pool[face4count].v1[1] = v1.screen[1];
                                    // face4Pool[face4count].v2[0] = v2.screen[0];
                                    // face4Pool[face4count].v2[1] = v2.screen[1];
                                    // face4Pool[face4count].v3[0] = v3.screen[0];
                                    // face4Pool[face4count].v3.y = v3.screen[1];
                                    // face4Pool[face4count].v4.x = v4.screen[0];
                                    // face4Pool[face4count].v4.y = v4.screen[1];
                                    // face4Pool[face4count].z = face.screen[2];

                                    face4Pool[face4count].material = object.material;
                                    face4Pool[face4count].overdraw = object.overdraw;
                                    face4Pool[face4count].uvs = object.geometry.uvs[j];
                                    face4Pool[face4count].color = face.color;

                                    this.renderList.push(face4Pool[face4count]);

                                    face4count++;

                                }
                            }
                        }

                    }

                }
                this.renderList.sort(painterSort)
            }

        }

        function Rectangle(x1, y1, x2, y2) {

            var _x1 = x1, _y1 = y1,
                _x2 = x2, _y2 = y2,
                _width = _x2 - _x1, _height = _y2 - _y1,
                _isEmpty = false;

            function resize() {

                _width = _x2 - _x1;
                _height = _y2 - _y1;

            }

            this.getX = function () {

                return _x1;

            };

            this.getY = function () {

                return _y1;

            };

            this.getWidth = function () {

                return _width;

            };

            this.getHeight = function () {

                return _height;

            };

            this.getX1 = function () {

                return _x1;

            };

            this.getY1 = function () {

                return _y1;

            };

            this.getX2 = function () {

                return _x2;

            };

            this.getY2 = function () {

                return _y2;

            };

            this.set = function (x1, y1, x2, y2) {

                _isEmpty = false;

                _x1 = x1; _y1 = y1;
                _x2 = x2; _y2 = y2;

                resize();

            };

            this.addPoint = function (x, y) {

                if (_isEmpty) {

                    _isEmpty = false;
                    _x1 = x; _y1 = y;
                    _x2 = x; _y2 = y;

                } else {

                    _x1 = Math.min(_x1, x);
                    _y1 = Math.min(_y1, y);
                    _x2 = Math.max(_x2, x);
                    _y2 = Math.max(_y2, y);

                }

                resize();

            };

            this.addRectangle = function (r) {

                if (_isEmpty) {

                    _isEmpty = false;
                    _x1 = r.getX1(); _y1 = r.getY1();
                    _x2 = r.getX2(); _y2 = r.getY2();

                } else {

                    _x1 = Math.min(_x1, r.getX1());
                    _y1 = Math.min(_y1, r.getY1());
                    _x2 = Math.max(_x2, r.getX2());
                    _y2 = Math.max(_y2, r.getY2());

                }

                resize();

            };

            this.inflate = function (v) {

                _x1 -= v; _y1 -= v;
                _x2 += v; _y2 += v;

                resize();

            };

            this.minSelf = function (r) {

                _x1 = Math.max(_x1, r.getX1());
                _y1 = Math.max(_y1, r.getY1());
                _x2 = Math.min(_x2, r.getX2());
                _y2 = Math.min(_y2, r.getY2());

                resize();

            };

            /*
            this.containsPoint = function (x, y) {
            
                return x > _x1 && x < _x2 && y > _y1 && y < _y2;
            
            }
            */

            this.instersects = function (r) {

                return Math.min(_x2, r.getX2()) - Math.max(_x1, r.getX1()) > 0 && Math.min(_y2, r.getY2()) - Math.max(_y1, r.getY1()) > 0;

            };

            this.empty = function () {

                _isEmpty = true;

                _x1 = 0; _y1 = 0;
                _x2 = 0; _y2 = 0;

                resize();

            };



        };

        function SVGRenderer() {

            this.render = function (scene, camera) {

            }
        }
        function CanvasRenderer() {
            Renderer.call(this);
            var _viewport = document.createElement("canvas"),
                _context = _viewport.getContext("2d"),
                _width, _height, _widthHalf, _heightHalf, _widthHeightHalf = glMatrix.vec2.create();
            _clipRect = new Rectangle(),
                _clearRect = new Rectangle(0, 0, 0, 0),
                _bboxRect = new Rectangle(),
                _vector2 = glMatrix.vec2.create();

            this.domElement = _viewport;
            this.autoClear = true;

            this.setSize = function (width, height) {

                _width = width; _height = height;
                _widthHalf = _width / 2; _heightHalf = _height / 2;

                _viewport.width = _width;
                _viewport.height = _height;

                _context.setTransform(1, 0, 0, 1, _widthHalf, _heightHalf);

                _clipRect.set(- _widthHalf, - _heightHalf, _widthHalf, _heightHalf);
                glMatrix.vec2.set(_widthHeightHalf, _widthHalf, _heightHalf)
            };

            this.clear = function () {

                _clearRect.inflate(1);
                _clearRect.minSelf(_clipRect);
                _context.clearRect(_clearRect.getX(), _clearRect.getY(), _clearRect.getWidth(), _clearRect.getHeight());
                _clearRect.empty();

            };
            this.render = function (scene, camera) {
                this.project(scene, camera);
                if (this.autoClear) {
                    this.clear();
                }
                var element, materialLength, elementsLength = this.renderList.length;
                var v1x, v2x, v3x, v4x, v1y, v2y, v3y, v4y;
                var i;
                for (i = 0; i < elementsLength; i++) {
                    element = this.renderList[i];
                    materialLength = element.material.length;
                    _bboxRect.empty();
                    _context.beginPath();
                    if (element instanceof RenderableFace3) {

                        glMatrix.vec2.mul(element.v1, element.v1, _widthHeightHalf);
                        glMatrix.vec2.mul(element.v2, element.v2, _widthHeightHalf)
                        glMatrix.vec2.mul(element.v3, element.v3, _widthHeightHalf)
                        // element.v1.x *= _widthHalf; element.v1.y *= _heightHalf;
                        // element.v2.x *= _widthHalf; element.v2.y *= _heightHalf;
                        // element.v3.x *= _widthHalf; element.v3.y *= _heightHalf;

                        if (element.overdraw) {

                            expand(element.v1, element.v2);
                            expand(element.v2, element.v3);
                            expand(element.v3, element.v1);

                        }
                        v1x = element.v1[0]; v1y = element.v1[1];
                        v2x = element.v2[0]; v2y = element.v2[1];
                        v3x = element.v3[0]; v3y = element.v3[1];
                        // v1x = element.v1.x; v1y = element.v1.y;
                        // v2x = element.v2.x; v2y = element.v2.y;
                        // v3x = element.v3.x; v3y = element.v3.y;

                        _bboxRect.addPoint(v1x, v1y);
                        _bboxRect.addPoint(v2x, v2y);
                        _bboxRect.addPoint(v3x, v3y);

                        if (!_clipRect.instersects(_bboxRect)) {

                            continue;

                        }

                        _context.moveTo(v1x, v1y);
                        _context.lineTo(v2x, v2y);
                        _context.lineTo(v3x, v3y);
                        _context.lineTo(v1x, v1y);

                    }
                    else if (element instanceof RenderableFace4) {

                        glMatrix.vec2.mul(element.v1, element.v1, _widthHeightHalf);
                        glMatrix.vec2.mul(element.v2, element.v2, _widthHeightHalf)
                        glMatrix.vec2.mul(element.v3, element.v3, _widthHeightHalf)
                        glMatrix.vec2.mul(element.v4, element.v4, _widthHeightHalf)
                        // element.v1.x *= _widthHalf; element.v1.y *= _heightHalf;
                        // element.v2.x *= _widthHalf; element.v2.y *= _heightHalf;
                        // element.v3.x *= _widthHalf; element.v3.y *= _heightHalf;
                        // element.v4.x *= _widthHalf; element.v4.y *= _heightHalf;

                        if (element.overdraw) {

                            expand(element.v1, element.v2);
                            expand(element.v2, element.v3);
                            expand(element.v3, element.v4);
                            expand(element.v4, element.v1);

                        }

                        v1x = element.v1[0]; v1y = element.v1[1];
                        v2x = element.v2[0]; v2y = element.v2[1];
                        v3x = element.v3[0]; v3y = element.v3[1];
                        v4x = element.v4[0]; v4y = element.v4[1];

                        _bboxRect.addPoint(v1x, v1y);
                        _bboxRect.addPoint(v2x, v2y);
                        _bboxRect.addPoint(v3x, v3y);
                        _bboxRect.addPoint(v4x, v4y);

                        if (!_clipRect.instersects(_bboxRect)) {

                            continue;

                        }

                        _context.moveTo(v1x, v1y);
                        _context.lineTo(v2x, v2y);
                        _context.lineTo(v3x, v3y);
                        _context.lineTo(v4x, v4y);
                        _context.lineTo(v1x, v1y);

                    }

                    _context.closePath();
                    for (j = 0; j < materialLength; j++) {

                        material = element.material[j];

                        if (material instanceof ColorFillMaterial) {

                            _context.fillStyle = material.color.cssRgba;
                            _context.fill();

                        } else if (material instanceof FaceColorFillMaterial) {
                            _context.fillStyle = element.color.cssRgba;
                            _context.fill();
                        } else if (material instanceof ColorStrokeMaterial) {

                            _context.lineWidth = material.lineWidth;
                            _context.lineJoin = "round";
                            _context.lineCap = "round";

                            _context.strokeStyle = material.color.__styleString;
                            _context.stroke();

                            _bboxRect.inflate(_context.lineWidth);

                        } else if (material instanceof BitmapUVMappingMaterial) {

                            bitmap = material.bitmap;
                            bitmapWidth = bitmap.width;
                            bitmapHeight = bitmap.height;

                            uv1.copy(element.uvs[0]); uv2.copy(element.uvs[1]); uv3.copy(element.uvs[2]);
                            suv1.copy(uv1); suv2.copy(uv2); suv3.copy(uv3);

                            suv1.x *= bitmapWidth; suv1.y *= bitmapHeight;
                            suv2.x *= bitmapWidth; suv2.y *= bitmapHeight;
                            suv3.x *= bitmapWidth; suv3.y *= bitmapHeight;

                            if (element.overdraw) {

                                expand(suv1, suv2);
                                expand(suv2, suv3);
                                expand(suv3, suv1);

                                suv1.x = (uv1.x === 0) ? 1 : (uv1.x === 1) ? suv1.x - 1 : suv1.x;
                                suv1.y = (uv1.y === 0) ? 1 : (uv1.y === 1) ? suv1.y - 1 : suv1.y;

                                suv2.x = (uv2.x === 0) ? 1 : (uv2.x === 1) ? suv2.x - 1 : suv2.x;
                                suv2.y = (uv2.y === 0) ? 1 : (uv2.y === 1) ? suv2.y - 1 : suv2.y;

                                suv3.x = (uv3.x === 0) ? 1 : (uv3.x === 1) ? suv3.x - 1 : suv3.x;
                                suv3.y = (uv3.y === 0) ? 1 : (uv3.y === 1) ? suv3.y - 1 : suv3.y;

                            }

                            suv1x = suv1.x; suv1y = suv1.y;
                            suv2x = suv2.x; suv2y = suv2.y;
                            suv3x = suv3.x; suv3y = suv3.y;

                            // Textured triangle drawing by Thatcher Ulrich.
                            // http://tulrich.com/geekstuff/canvas/jsgl.js

                            _context.save();
                            _context.clip();

                            denom = suv1x * (suv3y - suv2y) - suv2x * suv3y + suv3x * suv2y + (suv2x - suv3x) * suv1y;

                            m11 = - (suv1y * (v3x - v2x) - suv2y * v3x + suv3y * v2x + (suv2y - suv3y) * v1x) / denom;
                            m12 = (suv2y * v3y + suv1y * (v2y - v3y) - suv3y * v2y + (suv3y - suv2y) * v1y) / denom;
                            m21 = (suv1x * (v3x - v2x) - suv2x * v3x + suv3x * v2x + (suv2x - suv3x) * v1x) / denom;
                            m22 = - (suv2x * v3y + suv1x * (v2y - v3y) - suv3x * v2y + (suv3x - suv2x) * v1y) / denom;
                            dx = (suv1x * (suv3y * v2x - suv2y * v3x) + suv1y * (suv2x * v3x - suv3x * v2x) + (suv3x * suv2y - suv2x * suv3y) * v1x) / denom;
                            dy = (suv1x * (suv3y * v2y - suv2y * v3y) + suv1y * (suv2x * v3y - suv3x * v2y) + (suv3x * suv2y - suv2x * suv3y) * v1y) / denom;

                            _context.transform(m11, m12, m21, m22, dx, dy);

                            _context.drawImage(bitmap, 0, 0);
                            _context.restore();

                        }

                        _clearRect.addRectangle(_bboxRect);
                    }
                }
            }
            function expand(a, b) {
                glMatrix.vec2.sub(_vector2, b, a)
                glMatrix.vec2.normalize$4(_vector2, _vector2);
                glMatrix.vec2.add(b, b, _vector2);
                glMatrix.vec2.sub(a, a, _vector2);
            }
        }
        inherits(CanvasRenderer, Renderer)




        var Cube = function (width, height, depth) {

            Geometry.call(this);

            var scope = this,
                width_half = width / 2,
                height_half = height / 2,
                depth_half = depth / 2;

            v(width_half, height_half, -depth_half);
            v(width_half, -height_half, -depth_half);
            v(-width_half, -height_half, -depth_half);
            v(-width_half, height_half, -depth_half);
            v(width_half, height_half, depth_half);
            v(width_half, -height_half, depth_half);
            v(-width_half, -height_half, depth_half);
            v(-width_half, height_half, depth_half);

            f4(0, 1, 2, 3);
            f4(4, 7, 6, 5);
            f4(0, 4, 5, 1);
            f4(1, 5, 6, 2);
            f4(2, 6, 7, 3);
            f4(4, 0, 3, 7);
            // 添加顶点
            function v(x, y, z) {
                scope.vertices.push(new Vertex(new glMatrix.vec3.fromValues(x, y, z)));
            }
            // 添加面
            function f4(a, b, c, d) {
                scope.faces.push(new Face4(a, b, c, d));
            }
        }
        inherits(Cube, Geometry);

        var Plane = function (width, height, segments_width, segments_height) {

            Geometry.call(this);

            var scope = this,
                width_half = width / 2,
                height_half = height / 2,
                gridX = segments_width || 1,
                gridY = segments_height || 1,
                gridX1 = gridX + 1,
                gridY1 = gridY + 1,
                segment_width = width / gridX,
                segment_height = height / gridY;


            for (var iy = 0; iy < gridY1; iy++) {

                for (var ix = 0; ix < gridX1; ix++) {

                    var x = ix * segment_width - width_half;
                    var y = iy * segment_height - height_half;

                    this.vertices.push(new Vertex(new glMatrix.vec3.fromValues(x, - y, 0)));

                }

            }

            for (iy = 0; iy < gridY; iy++) {

                for (ix = 0; ix < gridX; ix++) {

                    var a = ix + gridX1 * iy;
                    var b = ix + gridX1 * (iy + 1);
                    var c = (ix + 1) + gridX1 * iy;

                    this.faces.push(new Face3(a, b, c));
                    this.uvs.push([
                        glMatrix.vec2.fromValues(ix / gridX, iy / gridY),
                        glMatrix.vec2.fromValues(ix / gridX, (iy + 1) / gridY),
                        glMatrix.vec2.fromValues((ix + 1) / gridX, iy / gridY)
                    ]);

                    a = (ix + 1) + gridX1 * (iy + 1);
                    b = (ix + 1) + gridX1 * iy;
                    c = ix + gridX1 * (iy + 1);

                    this.faces.push(new Face3(a, b, c));
                    this.uvs.push([
                        glMatrix.vec2.fromValues((ix + 1) / gridX, (iy + 1) / gridY),
                        glMatrix.vec2.fromValues((ix + 1) / gridX, iy / gridY),
                        glMatrix.vec2.fromValues(ix / gridX, (iy + 1) / gridY)
                    ]);

                }

            }

        }
        inherits(Plane, Geometry)
        function show() {
            var width = window.innerWidth;
            var height = window.innerWidth;
            var renderer = new CanvasRenderer();
            var camera = new Camera(70 / 180 * Math.PI, width / height, 0.0001, 10000);
            camera.position[1] = 150;
            camera.position[2] = 500;
            camera.target.position[1] = 150;
            var scene = new Scene();

            var cubeGeometry = new Cube(200, 200, 200);//创建立方体(正方体)
            for (var i = 0; i < cubeGeometry.faces.length; i++) {
                cubeGeometry.faces[i].color.setRGBA(Math.floor(Math.random() * 128), Math.floor(Math.random() * 128 + 128), Math.floor(Math.random() * 128 + 128), 255);
            }

            var cube = new Mesh(cubeGeometry, new FaceColorFillMaterial(0xff0000, 1));
            cube.position[1] = 150;

            scene.add(cube);

            var plane = new Mesh(new Plane(200, 200), new ColorFillMaterial(0xdddddd, 1));
            plane.rotation[0] = -90 * (Math.PI / 180);
             plane.position[1]=300;
            scene.add(plane);

            renderer.setSize(width, height);
            d3.select('body').append('div').append(function () {
                return renderer.domElement;
            })
            // renderer.render(scene, camera);


            var targetRotation = 0;
            var targetRotationOnMouseDown = 0;
            var mouseX = 0;
            var mouseXOnMouseDown = 0;
            var windowHalfX = width / 2;
            var windowHalfY = height / 2;
            var stats = new Stats();
            stats.showPanel(0); // 0: fps, 1: ms, 2: mb, 3+: custom
            stats.domElement.style.position = 'fixed';
            stats.domElement.style.top = '0px';
            document.body.appendChild(stats.domElement);

            document.addEventListener('mousedown', onDocumentMouseDown, false);
            document.addEventListener('touchstart', onDocumentTouchStart, false);
            document.addEventListener('touchmove', onDocumentTouchMove, false);



            function onDocumentMouseDown(event) {
                event.preventDefault();
                document.addEventListener('mousemove', onDocumentMouseMove, false);
                document.addEventListener('mouseup', onDocumentMouseUp, false);
                document.addEventListener('mouseout', onDocumentMouseOut, false);
                mouseXOnMouseDown = event.clientX - windowHalfX;
                targetRotationOnMouseDown = targetRotation;
            }
            function onDocumentMouseMove(event) {
                mouseX = event.clientX - windowHalfX;
                targetRotation = targetRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.02;
            }
            function onDocumentMouseUp(event) {
                document.removeEventListener('mousemove', onDocumentMouseMove, false);
                document.removeEventListener('mouseup', onDocumentMouseUp, false);
                document.removeEventListener('mouseout', onDocumentMouseOut, false);
            }
            function onDocumentMouseOut(event) {
                document.removeEventListener('mousemove', onDocumentMouseMove, false);
                document.removeEventListener('mouseup', onDocumentMouseUp, false);
                document.removeEventListener('mouseout', onDocumentMouseOut, false);
            }
            function onDocumentTouchStart(event) {
                if (event.touches.length == 1) {
                    event.preventDefault();
                    mouseXOnMouseDown = event.touches[0].pageX - windowHalfX;
                    targetRotationOnMouseDown = targetRotation;
                }
            }
            function onDocumentTouchMove(event) {
                if (event.touches.length == 1) {
                    event.preventDefault();
                    mouseX = event.touches[0].pageX - windowHalfX;
                    targetRotation = targetRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.05;
                }
            }
            //
            function loop() {
              //  cube.rotation[1] += 0.1;
                 plane.rotation[2] = cube.rotation[1] += (targetRotation - cube.rotation[1]) * 0.05;
                renderer.render(scene, camera);
                stats.update();
            }
            d3.timer(loop)
        }
        show();
    </script>
</body>

</html>

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值