📄 object.js
字号:
if(!dojo._hasResource["dojox.gfx3d.object"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dojox.gfx3d.object"] = true;dojo.provide("dojox.gfx3d.object");dojo.require("dojox.gfx");dojo.require("dojox.gfx3d.lighting");dojo.require("dojox.gfx3d.scheduler");dojo.require("dojox.gfx3d.vector");dojo.require("dojox.gfx3d.gradient");// FIXME: why the global "out" var here?var out = function(o, x){ if(arguments.length > 1){ // console.debug("debug:", o); o = x; } var e = {}; for(var i in o){ if(i in e){ continue; } // console.debug("debug:", i, typeof o[i], o[i]); }};dojo.declare("dojox.gfx3d.Object", null, { constructor: function(){ // summary: a Object object, which knows how to map // 3D objects to 2D shapes. // object: Object: an abstract Object object // (see dojox.gfx3d.defaultEdges, // dojox.gfx3d.defaultTriangles, // dojox.gfx3d.defaultQuads // dojox.gfx3d.defaultOrbit // dojox.gfx3d.defaultCube // or dojox.gfx3d.defaultCylinder) this.object = null; // matrix: dojox.gfx3d.matrix: world transform this.matrix = null; // cache: buffer for intermediate result, used late for draw() this.cache = null; // renderer: a reference for the Viewport this.renderer = null; // parent: a reference for parent, Scene or Viewport object this.parent = null; // strokeStyle: Object: a stroke object this.strokeStyle = null; // fillStyle: Object: a fill object or texture object this.fillStyle = null; // shape: dojox.gfx.Shape: an underlying 2D shape this.shape = null; }, setObject: function(newObject){ // summary: sets a Object object // object: Object: an abstract Object object // (see dojox.gfx3d.defaultEdges, // dojox.gfx3d.defaultTriangles, // dojox.gfx3d.defaultQuads // dojox.gfx3d.defaultOrbit // dojox.gfx3d.defaultCube // or dojox.gfx3d.defaultCylinder) this.object = dojox.gfx.makeParameters(this.object, newObject); return this; }, setTransform: function(matrix){ // summary: sets a transformation matrix // matrix: dojox.gfx3d.matrix.Matrix: a matrix or a matrix-like object // (see an argument of dojox.gfx3d.matrix.Matrix // constructor for a list of acceptable arguments) this.matrix = dojox.gfx3d.matrix.clone(matrix ? dojox.gfx3d.matrix.normalize(matrix) : dojox.gfx3d.identity, true); return this; // self }, // apply left & right transformation applyRightTransform: function(matrix){ // summary: multiplies the existing matrix with an argument on right side // (this.matrix * matrix) // matrix: dojox.gfx3d.matrix.Matrix: a matrix or a matrix-like object // (see an argument of dojox.gfx.matrix.Matrix // constructor for a list of acceptable arguments) return matrix ? this.setTransform([this.matrix, matrix]) : this; // self }, applyLeftTransform: function(matrix){ // summary: multiplies the existing matrix with an argument on left side // (matrix * this.matrix) // matrix: dojox.gfx3d.matrix.Matrix: a matrix or a matrix-like object // (see an argument of dojox.gfx.matrix.Matrix // constructor for a list of acceptable arguments) return matrix ? this.setTransform([matrix, this.matrix]) : this; // self }, applyTransform: function(matrix){ // summary: a shortcut for dojox.gfx.Shape.applyRightTransform // matrix: dojox.gfx3d.matrix.Matrix: a matrix or a matrix-like object // (see an argument of dojox.gfx.matrix.Matrix // constructor for a list of acceptable arguments) return matrix ? this.setTransform([this.matrix, matrix]) : this; // self }, setFill: function(fill){ // summary: sets a fill object // (the default implementation is to delegate to // the underlying 2D shape). // fill: Object: a fill object // (see dojox.gfx.defaultLinearGradient, // dojox.gfx.defaultRadialGradient, // dojox.gfx.defaultPattern, // dojo.Color // or dojox.gfx.MODEL) this.fillStyle = fill; return this; }, setStroke: function(stroke){ // summary: sets a stroke object // (the default implementation simply ignores it) // stroke: Object: a stroke object // (see dojox.gfx.defaultStroke) this.strokeStyle = stroke; return this; }, toStdFill: function(lighting, normal){ return (this.fillStyle && typeof this.fillStyle['type'] != "undefined") ? lighting[this.fillStyle.type](normal, this.fillStyle.finish, this.fillStyle.color) : this.fillStyle; }, invalidate: function(){ this.renderer.addTodo(this); }, destroy: function(){ if(this.shape){ var p = this.shape.getParent(); if(p){ p.remove(this.shape); } this.shape = null; } }, // All the 3D objects need to override the following virtual functions: // render, getZOrder, getOutline, draw, redraw if necessary. render: function(camera){ throw "Pure virtual function, not implemented"; }, draw: function(lighting){ throw "Pure virtual function, not implemented"; }, getZOrder: function(){ return 0; }, getOutline: function(){ return null; }});dojo.declare("dojox.gfx3d.Scene", dojox.gfx3d.Object, { // summary: the Scene is just a containter. // note: we have the following assumption: // all objects in the Scene are not overlapped with other objects // outside of the scene. constructor: function(){ // summary: a containter of other 3D objects this.objects= []; this.todos = []; this.schedule = dojox.gfx3d.scheduler.zOrder; this._draw = dojox.gfx3d.drawer.conservative; }, setFill: function(fill){ this.fillStyle = fill; dojo.forEach(this.objects, function(item){ item.setFill(fill); }); return this; }, setStroke: function(stroke){ this.strokeStyle = stroke; dojo.forEach(this.objects, function(item){ item.setStroke(stroke); }); return this; }, render: function(camera, deep){ var m = dojox.gfx3d.matrix.multiply(camera, this.matrix); if(deep){ this.todos = this.objects; } dojo.forEach(this.todos, function(item){ item.render(m, deep); }); }, draw: function(lighting){ this.objects = this.schedule(this.objects); this._draw(this.todos, this.objects, this.renderer); }, addTodo: function(newObject){ // FIXME: use indexOf? if(dojo.every(this.todos, function(item){ return item != newObject; })){ this.todos.push(newObject); this.invalidate(); } }, invalidate: function(){ this.parent.addTodo(this); }, getZOrder: function(){ var zOrder = 0; dojo.forEach(this.objects, function(item){ zOrder += item.getZOrder(); }); return (this.objects.length > 1) ? zOrder / this.objects.length : 0; }});dojo.declare("dojox.gfx3d.Edges", dojox.gfx3d.Object, { constructor: function(){ // summary: a generic edge in 3D viewport this.object = dojo.clone(dojox.gfx3d.defaultEdges); }, setObject: function(newObject, /* String, optional */ style){ // summary: setup the object // newObject: Array of points || Object // style: String, optional this.object = dojox.gfx.makeParameters(this.object, (newObject instanceof Array) ? { points: newObject, style: style } : newObject); return this; }, getZOrder: function(){ var zOrder = 0; dojo.forEach(this.cache, function(item){ zOrder += item.z;} ); return (this.cache.length > 1) ? zOrder / this.cache.length : 0; }, render: function(camera){ var m = dojox.gfx3d.matrix.multiply(camera, this.matrix); this.cache = dojo.map(this.object.points, function(item){ return dojox.gfx3d.matrix.multiplyPoint(m, item); }); }, draw: function(){ var c = this.cache; if(this.shape){ this.shape.setShape("") }else{ this.shape = this.renderer.createPath(); } var p = this.shape.setAbsoluteMode("absolute"); if(this.object.style == "strip" || this.object.style == "loop"){ p.moveTo(c[0].x, c[0].y); dojo.forEach(c.slice(1), function(item){ p.lineTo(item.x, item.y); }); if(this.object.style == "loop"){ p.closePath(); } }else{ for(var i = 0; i < this.cache.length; ){ p.moveTo(c[i].x, c[i].y); i ++; p.lineTo(c[i].x, c[i].y); i ++; } } // FIXME: doe setFill make sense here? p.setStroke(this.strokeStyle); }});dojo.declare("dojox.gfx3d.Orbit", dojox.gfx3d.Object, { constructor: function(){ // summary: a generic edge in 3D viewport this.object = dojo.clone(dojox.gfx3d.defaultOrbit); }, render: function(camera){ var m = dojox.gfx3d.matrix.multiply(camera, this.matrix); var angles = [0, Math.PI/4, Math.PI/3]; var center = dojox.gfx3d.matrix.multiplyPoint(m, this.object.center); var marks = dojo.map(angles, function(item){ return {x: this.center.x + this.radius * Math.cos(item), y: this.center.y + this.radius * Math.sin(item), z: this.center.z}; }, this.object); marks = dojo.map(marks, function(item){ return dojox.gfx3d.matrix.multiplyPoint(m, item); }); var normal = dojox.gfx3d.vector.normalize(marks); marks = dojo.map(marks, function(item){ return dojox.gfx3d.vector.substract(item, center); }); // Use the algorithm here: // http://www.3dsoftware.com/Math/PlaneCurves/EllipseAlgebra/ // After we normalize the marks, the equation is: // a x^2 + 2b xy + cy^2 + f = 0: let a = 1 // so the final equation is: // [ xy, y^2, 1] * [2b, c, f]' = [ -x^2 ]' var A = { xx: marks[0].x * marks[0].y, xy: marks[0].y * marks[0].y, xz: 1, yx: marks[1].x * marks[1].y, yy: marks[1].y * marks[1].y, yz: 1, zx: marks[2].x * marks[2].y, zy: marks[2].y * marks[2].y, zz: 1, dx: 0, dy: 0, dz: 0 }; var b = dojo.map(marks, function(item){ return -Math.pow(item.x, 2); }); // X is 2b, c, f var X = dojox.gfx3d.matrix.multiplyPoint(dojox.gfx3d.matrix.invert(A),b[0], b[1], b[2]); var theta = Math.atan2(X.x, 1 - X.y) / 2; // rotate the marks back to the canonical form var probes = dojo.map(marks, function(item){ return dojox.gfx.matrix.multiplyPoint(dojox.gfx.matrix.rotate(-theta), item.x, item.y); }); // we are solving the equation: Ax = b // A = [x^2, y^2] X = [1/a^2, 1/b^2]', b = [1, 1]' // so rx = Math.sqrt(1/ ( inv(A)[1:] * b ) ); // so ry = Math.sqrt(1/ ( inv(A)[2:] * b ) ); var a = Math.pow(probes[0].x, 2); var b = Math.pow(probes[0].y, 2); var c = Math.pow(probes[1].x, 2); var d = Math.pow(probes[1].y, 2); // the invert matrix is // 1/(ad -bc) [ d, -b; -c, a]; var rx = Math.sqrt( (a*d - b*c)/ (d-b) ); var ry = Math.sqrt( (a*d - b*c)/ (a-c) ); this.cache = {cx: center.x, cy: center.y, rx: rx, ry: ry, theta: theta, normal: normal}; }, draw: function(lighting){ if(this.shape){ this.shape.setShape(this.cache); } else { this.shape = this.renderer.createEllipse(this.cache); } this.shape.applyTransform(dojox.gfx.matrix.rotateAt(this.cache.theta, this.cache.cx, this.cache.cy)) .setStroke(this.strokeStyle) .setFill(this.toStdFill(lighting, this.cache.normal)); }});
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -