scenejs_on_rails 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -5
- data/app/controllers/scenejs_controller.rb +53 -0
- data/app/views/scenejs/get_scenejs_data.html.erb +3 -0
- data/lib/scenejs_on_rails.rb +1 -1
- data/lib/scenejs_on_rails/rails.rb +5 -0
- data/lib/scenejs_on_rails/version.rb +1 -1
- data/vendor/assets/javascripts/scenejs.js +17307 -0
- data/vendor/assets/javascripts/scenejs_extras/gui.js +478 -0
- data/vendor/assets/javascripts/scenejs_extras/gui/README.md +4 -0
- data/vendor/assets/javascripts/scenejs_extras/gui/dat.gui.min.js +94 -0
- data/vendor/assets/javascripts/scenejs_extras/gui/gui.js +385 -0
- data/vendor/assets/javascripts/scenejs_lib/cityBuilder.js +457 -0
- data/vendor/assets/javascripts/scenejs_lib/dat.gui.min.js +94 -0
- data/vendor/assets/javascripts/scenejs_lib/gl-matrix-min.js +28 -0
- data/vendor/assets/javascripts/scenejs_lib/gl-matrix.js +4078 -0
- data/vendor/assets/javascripts/scenejs_lib/require.js +36 -0
- data/vendor/assets/javascripts/scenejs_lib/requireConfig.js +18 -0
- data/vendor/assets/javascripts/scenejs_lib/requireWrapperEnd.js +1 -0
- data/vendor/assets/javascripts/scenejs_lib/requireWrapperStart.js +2 -0
- data/vendor/assets/javascripts/scenejs_lib/stats.min.js +6 -0
- data/vendor/assets/javascripts/scenejs_lib/sylvester.js +1 -0
- data/vendor/assets/javascripts/scenejs_lib/webgl-debug-utils.js +839 -0
- data/vendor/assets/javascripts/scenejs_plugins/geometry/boundary.js +59 -0
- data/vendor/assets/javascripts/scenejs_plugins/geometry/box.js +72 -0
- data/vendor/assets/javascripts/scenejs_plugins/geometry/plane.js +126 -0
- data/vendor/assets/javascripts/scenejs_plugins/geometry/quad.js +37 -0
- data/vendor/assets/javascripts/scenejs_plugins/geometry/skybox.js +86 -0
- data/vendor/assets/javascripts/scenejs_plugins/geometry/sphere.js +82 -0
- data/vendor/assets/javascripts/scenejs_plugins/geometry/teapot.js +5853 -0
- data/vendor/assets/javascripts/scenejs_plugins/geometry/torus.js +139 -0
- data/vendor/assets/javascripts/scenejs_plugins/geometry/vectorText.js +1499 -0
- data/vendor/assets/javascripts/scenejs_plugins/geometry/wobblyBox.js +44 -0
- data/vendor/assets/javascripts/scenejs_plugins/lib/canvas2image.js +198 -0
- data/vendor/assets/javascripts/scenejs_plugins/lib/frustum/frustumCullEngine.js +810 -0
- data/vendor/assets/javascripts/scenejs_plugins/lib/frustum/frustumCullSystem.js +185 -0
- data/vendor/assets/javascripts/scenejs_plugins/lib/frustum/frustumCullSystemPool.js +174 -0
- data/vendor/assets/javascripts/scenejs_plugins/lib/frustum/frustumCullWorker.js +142 -0
- data/vendor/assets/javascripts/scenejs_plugins/lib/gl-matrix-min.js +28 -0
- data/vendor/assets/javascripts/scenejs_plugins/lib/jquery-1.8.3.min.js +2 -0
- data/vendor/assets/javascripts/scenejs_plugins/lib/k3d.js +1029 -0
- data/vendor/assets/javascripts/scenejs_plugins/lib/physics/jiglib.all.min.js +3 -0
- data/vendor/assets/javascripts/scenejs_plugins/lib/physics/physics.js +223 -0
- data/vendor/assets/javascripts/scenejs_plugins/lib/physics/worker.js +330 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/alpha/orbitTracking.js +295 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/alpha/orbitTrackingTarget.js +43 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/backgrounds/gradient.js +148 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/cameras/orbit.js +172 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/cameras/pickFlyOrbit.js +409 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/canvas/capture.js +107 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/demos/color.js +30 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/demos/redTeapot.js +52 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/demos/spinningTeapot.js +43 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/effects/crt.js +36 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/effects/fog.js +159 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/effects/snowyPeaks.js +50 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/effects/wobble.js +42 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/effects/xray.js +126 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/frustum/body.js +112 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/frustum/cull.js +42 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/frustum/lod.js +125 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/heightmaps/custom.js +185 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/import/3ds.js +91 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/import/md2.js +139 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/import/obj.js +100 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/objects/buildings/building.js +352 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/objects/buildings/building/HighRiseGlass.jpg +0 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/objects/buildings/building/HighRiseGlassSpecular.jpg +0 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/objects/buildings/building/highrise-windows.jpg +0 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/objects/buildings/building/pixelcity_windows7.jpg +0 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/objects/buildings/city.js +26 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/objects/plants/ghostTree.js +387 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/objects/space/planets/earth.js +168 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/objects/space/planets/earth/earth-lights.gif +0 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/objects/space/planets/earth/earth-specular.gif +0 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/objects/space/planets/earth/earth-specular.jpg +0 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/objects/space/planets/earth/earth.jpg +0 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/objects/space/planets/earth/earthbump.jpg +0 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/objects/space/planets/earth/earthclouds.jpg +0 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/objects/toys/drinkingBird.js +632 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/objects/vehicles/tank.js +77670 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/objects/vehicles/tank.js~ +77636 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/physics/body.js +85 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/physics/box.js +30 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/physics/material.js +35 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/physics/plane.js +47 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/physics/sphere.js +32 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/physics/system.js +44 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/physics/teapot.js +29 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/prims/boundary.js +73 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/prims/box.js +87 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/prims/cylinder.js +186 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/prims/grid.js +47 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/prims/plane.js +137 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/prims/quad.js +43 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/prims/sphere.js +107 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/prims/teapot.js +5846 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/prims/torus.js +149 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/prims/vectorText.js +1508 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/clouds.js +19 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/cloudySea.js +19 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/custom.js +150 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/grimmNight.js +19 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/interstellarClouds.js +19 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/miramarClouds.js +19 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/stormyDays.js +19 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/textures/clouds.jpg +0 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/textures/cloudySea.jpg +0 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/textures/grimmNight.jpg +0 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/textures/interstellarClouds.jpg +0 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/textures/miramarClouds.jpg +0 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/textures/stormyDays.jpg +0 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/textures/violentDays.jpg +0 -0
- data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/violentDays.js +19 -0
- data/vendor/assets/javascripts/scenejs_plugins/texture/image.js +67 -0
- data/vendor/assets/javascripts/scenejs_plugins/texture/video.js +105 -0
- metadata +113 -1
@@ -0,0 +1,44 @@
|
|
1
|
+
SceneJS.Plugins.addPlugin(
|
2
|
+
|
3
|
+
"geometry",
|
4
|
+
|
5
|
+
"wobblyBox",
|
6
|
+
|
7
|
+
new (function () {
|
8
|
+
|
9
|
+
this.getSource = function () {
|
10
|
+
var publish;
|
11
|
+
return {
|
12
|
+
subscribe:function (fn) {
|
13
|
+
publish = fn;
|
14
|
+
},
|
15
|
+
configure:function (cfg) {
|
16
|
+
publish(build(cfg));
|
17
|
+
}
|
18
|
+
};
|
19
|
+
};
|
20
|
+
|
21
|
+
function build (cfg) {
|
22
|
+
var randomFactor = cfg.randomFactor;
|
23
|
+
return {
|
24
|
+
primitive:"triangles", // Geometry only uses this on create, ignores on update
|
25
|
+
positions:new Float32Array(randomize([ 5, 5, 5, -5, 5, 5, -5, -5, 5, 5, -5, 5, 5, 5, 5, 5, -5, 5, 5, -5, -5, 5, 5, -5, 5, 5, 5, 5, 5, -5, -5, 5, -5, -5, 5, 5, -5, 5, 5, -5, 5, -5, -5, -5, -5, -5, -5, 5, -5, -5, -5, 5, -5, -5, 5, -5, 5, -5, -5, 5, 5, -5, -5, -5, -5, -5, -5, 5, -5, 5, 5, -5], randomFactor)),
|
26
|
+
normals:new Float32Array(randomize([ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1], randomFactor)),
|
27
|
+
uv:new Float32Array(randomize([ 5, 5, 0, 5, 0, 0, 5, 0, 0, 5, 0, 0, 5, 0, 5, 5, 5, 0, 5, 5, 0, 5, 0, 0, 5, 5, 0, 5, 0, 0, 5, 0, 0, 0, 5, 0, 5, 5, 0, 5, 0, 0, 5, 0, 5, 5, 0, 5], randomFactor)),
|
28
|
+
uv2:null,
|
29
|
+
indices:new Uint16Array([ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23])
|
30
|
+
};
|
31
|
+
}
|
32
|
+
|
33
|
+
function randomize (arry, randomFactor) {
|
34
|
+
if (randomFactor == 0) {
|
35
|
+
return arry;
|
36
|
+
}
|
37
|
+
var halfRandomFactor = randomFactor / 2.0;
|
38
|
+
for (var i = 0, len = arry.length; i < len; i++) {
|
39
|
+
arry[i] += (Math.random() * randomFactor) - halfRandomFactor;
|
40
|
+
}
|
41
|
+
return arry;
|
42
|
+
}
|
43
|
+
|
44
|
+
})());
|
@@ -0,0 +1,198 @@
|
|
1
|
+
/*
|
2
|
+
* Canvas2Image v0.1
|
3
|
+
* Copyright (c) 2008 Jacob Seidelin, cupboy@gmail.com
|
4
|
+
* MIT License [http://www.opensource.org/licenses/mit-license.php]
|
5
|
+
*/
|
6
|
+
|
7
|
+
var Canvas2Image = (function() {
|
8
|
+
// check if we have canvas support
|
9
|
+
var oCanvas = document.createElement("canvas"),
|
10
|
+
sc = String.fromCharCode,
|
11
|
+
strDownloadMime = "image/octet-stream",
|
12
|
+
bReplaceDownloadMime = false;
|
13
|
+
|
14
|
+
// no canvas, bail out.
|
15
|
+
if (!oCanvas.getContext) {
|
16
|
+
return {
|
17
|
+
saveAsBMP : function(){},
|
18
|
+
saveAsPNG : function(){},
|
19
|
+
saveAsJPEG : function(){}
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
var bHasImageData = !!(oCanvas.getContext("2d").getImageData),
|
24
|
+
bHasDataURL = !!(oCanvas.toDataURL),
|
25
|
+
bHasBase64 = !!(window.btoa);
|
26
|
+
|
27
|
+
// ok, we're good
|
28
|
+
var readCanvasData = function(oCanvas) {
|
29
|
+
var iWidth = parseInt(oCanvas.width),
|
30
|
+
iHeight = parseInt(oCanvas.height);
|
31
|
+
return oCanvas.getContext("2d").getImageData(0,0,iWidth,iHeight);
|
32
|
+
}
|
33
|
+
|
34
|
+
// base64 encodes either a string or an array of charcodes
|
35
|
+
var encodeData = function(data) {
|
36
|
+
var i, aData, strData = "";
|
37
|
+
|
38
|
+
if (typeof data == "string") {
|
39
|
+
strData = data;
|
40
|
+
} else {
|
41
|
+
aData = data;
|
42
|
+
for (i = 0; i < aData.length; i++) {
|
43
|
+
strData += sc(aData[i]);
|
44
|
+
}
|
45
|
+
}
|
46
|
+
return btoa(strData);
|
47
|
+
}
|
48
|
+
|
49
|
+
// creates a base64 encoded string containing BMP data takes an imagedata object as argument
|
50
|
+
var createBMP = function(oData) {
|
51
|
+
var strHeader = '',
|
52
|
+
iWidth = oData.width,
|
53
|
+
iHeight = oData.height;
|
54
|
+
|
55
|
+
strHeader += 'BM';
|
56
|
+
|
57
|
+
var iFileSize = iWidth*iHeight*4 + 54; // total header size = 54 bytes
|
58
|
+
strHeader += sc(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
|
59
|
+
strHeader += sc(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
|
60
|
+
strHeader += sc(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
|
61
|
+
strHeader += sc(iFileSize % 256);
|
62
|
+
|
63
|
+
strHeader += sc(0, 0, 0, 0, 54, 0, 0, 0); // data offset
|
64
|
+
strHeader += sc(40, 0, 0, 0); // info header size
|
65
|
+
|
66
|
+
var iImageWidth = iWidth;
|
67
|
+
strHeader += sc(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
|
68
|
+
strHeader += sc(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
|
69
|
+
strHeader += sc(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
|
70
|
+
strHeader += sc(iImageWidth % 256);
|
71
|
+
|
72
|
+
var iImageHeight = iHeight;
|
73
|
+
strHeader += sc(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
|
74
|
+
strHeader += sc(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
|
75
|
+
strHeader += sc(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
|
76
|
+
strHeader += sc(iImageHeight % 256);
|
77
|
+
|
78
|
+
strHeader += sc(1, 0, 32, 0); // num of planes & num of bits per pixel
|
79
|
+
strHeader += sc(0, 0, 0, 0); // compression = none
|
80
|
+
|
81
|
+
var iDataSize = iWidth*iHeight*4;
|
82
|
+
strHeader += sc(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
|
83
|
+
strHeader += sc(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
|
84
|
+
strHeader += sc(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
|
85
|
+
strHeader += sc(iDataSize % 256);
|
86
|
+
|
87
|
+
strHeader += sc(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // these bytes are not used
|
88
|
+
|
89
|
+
var aImgData = oData.data,
|
90
|
+
strPixelData = "",
|
91
|
+
c, x, y = iHeight,
|
92
|
+
iOffsetX, iOffsetY, strPixelRow;
|
93
|
+
|
94
|
+
do {
|
95
|
+
iOffsetY = iWidth*(y-1)*4;
|
96
|
+
strPixelRow = "";
|
97
|
+
for (x = 0; x < iWidth; x++) {
|
98
|
+
iOffsetX = 4*x;
|
99
|
+
strPixelRow += sc(
|
100
|
+
aImgData[iOffsetY + iOffsetX + 2], // B
|
101
|
+
aImgData[iOffsetY + iOffsetX + 1], // G
|
102
|
+
aImgData[iOffsetY + iOffsetX], // R
|
103
|
+
aImgData[iOffsetY + iOffsetX + 3] // A
|
104
|
+
);
|
105
|
+
}
|
106
|
+
strPixelData += strPixelRow;
|
107
|
+
} while (--y);
|
108
|
+
|
109
|
+
return encodeData(strHeader + strPixelData);
|
110
|
+
}
|
111
|
+
|
112
|
+
// sends the generated file to the client
|
113
|
+
var saveFile = function(strData) {
|
114
|
+
if (!window.open(strData)) {
|
115
|
+
document.location.href = strData;
|
116
|
+
}
|
117
|
+
}
|
118
|
+
|
119
|
+
var makeDataURI = function(strData, strMime) {
|
120
|
+
return "data:" + strMime + ";base64," + strData;
|
121
|
+
}
|
122
|
+
|
123
|
+
// generates a <img> object containing the imagedata
|
124
|
+
var makeImageObject = function(strSource) {
|
125
|
+
var oImgElement = document.createElement("img");
|
126
|
+
oImgElement.src = strSource;
|
127
|
+
return oImgElement;
|
128
|
+
}
|
129
|
+
|
130
|
+
var scaleCanvas = function(oCanvas, iWidth, iHeight) {
|
131
|
+
if (iWidth && iHeight) {
|
132
|
+
var oSaveCanvas = document.createElement("canvas");
|
133
|
+
|
134
|
+
oSaveCanvas.width = iWidth;
|
135
|
+
oSaveCanvas.height = iHeight;
|
136
|
+
oSaveCanvas.style.width = iWidth+"px";
|
137
|
+
oSaveCanvas.style.height = iHeight+"px";
|
138
|
+
|
139
|
+
var oSaveCtx = oSaveCanvas.getContext("2d");
|
140
|
+
|
141
|
+
oSaveCtx.drawImage(oCanvas, 0, 0, oCanvas.width, oCanvas.height, 0, 0, iWidth, iWidth);
|
142
|
+
|
143
|
+
return oSaveCanvas;
|
144
|
+
}
|
145
|
+
return oCanvas;
|
146
|
+
}
|
147
|
+
|
148
|
+
return {
|
149
|
+
saveAsPNG : function(oCanvas, bReturnImg, iWidth, iHeight) {
|
150
|
+
if (!bHasDataURL) return false;
|
151
|
+
|
152
|
+
var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight),
|
153
|
+
strMime = "image/png",
|
154
|
+
strData = oScaledCanvas.toDataURL(strMime);
|
155
|
+
|
156
|
+
if (bReturnImg) {
|
157
|
+
return makeImageObject(strData);
|
158
|
+
} else {
|
159
|
+
saveFile(bReplaceDownloadMime ? strData.replace(strMime, strDownloadMime) : strData);
|
160
|
+
}
|
161
|
+
return true;
|
162
|
+
},
|
163
|
+
|
164
|
+
saveAsJPEG : function(oCanvas, bReturnImg, iWidth, iHeight) {
|
165
|
+
if (!bHasDataURL) return false;
|
166
|
+
|
167
|
+
var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight),
|
168
|
+
strMime = "image/jpeg",
|
169
|
+
strData = oScaledCanvas.toDataURL(strMime);
|
170
|
+
|
171
|
+
// check if browser actually supports jpeg by looking for the mime type in the data uri. if not, return false
|
172
|
+
if (strData.indexOf(strMime) != 5) return false;
|
173
|
+
|
174
|
+
if (bReturnImg) {
|
175
|
+
return makeImageObject(strData);
|
176
|
+
} else {
|
177
|
+
saveFile(bReplaceDownloadMime ? strData.replace(strMime, strDownloadMime) : strData);
|
178
|
+
}
|
179
|
+
return true;
|
180
|
+
},
|
181
|
+
|
182
|
+
saveAsBMP : function(oCanvas, bReturnImg, iWidth, iHeight) {
|
183
|
+
if (!(bHasDataURL && bHasImageData && bHasBase64)) return false;
|
184
|
+
|
185
|
+
var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight),
|
186
|
+
strMime = "image/bmp",
|
187
|
+
oData = readCanvasData(oScaledCanvas),
|
188
|
+
strImgData = createBMP(oData);
|
189
|
+
|
190
|
+
if (bReturnImg) {
|
191
|
+
return makeImageObject(makeDataURI(strImgData, strMime));
|
192
|
+
} else {
|
193
|
+
saveFile(makeDataURI(strImgData, strMime));
|
194
|
+
}
|
195
|
+
return true;
|
196
|
+
}
|
197
|
+
};
|
198
|
+
})();
|
@@ -0,0 +1,810 @@
|
|
1
|
+
//
|
2
|
+
// 3D frustum culling engine
|
3
|
+
//
|
4
|
+
// Has a view matrix, projection matrix, viewport and
|
5
|
+
//
|
6
|
+
// This file is supposed to be loaded into a Web Worker, so everything's global
|
7
|
+
// and we're not bothering with name spaces etc.
|
8
|
+
//
|
9
|
+
|
10
|
+
var OUTSIDE_FRUSTUM = 0;
|
11
|
+
var INTERSECT_FRUSTUM = 1;
|
12
|
+
var INSIDE_FRUSTUM = 2;
|
13
|
+
|
14
|
+
/**
|
15
|
+
* A frustum culling engine
|
16
|
+
* @param cfg
|
17
|
+
* @constructor
|
18
|
+
*/
|
19
|
+
function Engine(cfg) {
|
20
|
+
|
21
|
+
// The current view matrix
|
22
|
+
this._viewMat = identityMat4();
|
23
|
+
|
24
|
+
// Current projection matrix
|
25
|
+
this._projMat = identityMat4();
|
26
|
+
|
27
|
+
// Current viewport
|
28
|
+
this._viewport = [0, 0, 1, 1];
|
29
|
+
|
30
|
+
// Culling frustum constructed from matrices and viewport
|
31
|
+
this._frustum = null;
|
32
|
+
|
33
|
+
// Set when matrices or viewport reconfigured, causes frustum lazy-rebuild on next integration
|
34
|
+
this._frustumDirty = true;
|
35
|
+
|
36
|
+
// Body map, holds bodies by ID
|
37
|
+
this._bodies = {};
|
38
|
+
|
39
|
+
// Bodies in array for efficient iteration
|
40
|
+
this._bodyList = [];
|
41
|
+
this._numBodies = 0;
|
42
|
+
|
43
|
+
// Set when body map updated, causes body list lazy-rebuild on next integration
|
44
|
+
this._bodyListDirty = false;
|
45
|
+
|
46
|
+
// Output array containing updated bodies after each integration
|
47
|
+
this._updatedBodies = [];
|
48
|
+
|
49
|
+
if (cfg) {
|
50
|
+
this.setConfigs(cfg);
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
54
|
+
/**
|
55
|
+
* Configures the engine
|
56
|
+
* @param cfg
|
57
|
+
* @param {Array(16)} [cfg.viewMat] View matrix
|
58
|
+
* @param {Array(16)} [cfg.projMat] Projection matrix
|
59
|
+
* @param {Array(4)} [cfg.viewport] Viewport
|
60
|
+
*/
|
61
|
+
Engine.prototype.setConfigs = function (cfg) {
|
62
|
+
// Configure view matrix
|
63
|
+
if (cfg.viewMat) {
|
64
|
+
this._viewMat = cfg.viewMat;
|
65
|
+
this._frustumDirty = true;
|
66
|
+
}
|
67
|
+
// Configure projection matrix
|
68
|
+
if (cfg.projMat) {
|
69
|
+
this._projMat = cfg.projMat;
|
70
|
+
this._frustumDirty = true;
|
71
|
+
}
|
72
|
+
// Configure viewport
|
73
|
+
if (cfg.viewport) {
|
74
|
+
this._viewport = cfg.viewport;
|
75
|
+
this._frustumDirty = true;
|
76
|
+
}
|
77
|
+
};
|
78
|
+
|
79
|
+
/**
|
80
|
+
* Adds a body to the engine
|
81
|
+
* @param {Number} bodyId Unique body ID
|
82
|
+
* @param {*} cfg Body properties
|
83
|
+
*/
|
84
|
+
Engine.prototype.addBody = function (bodyId, cfg) {
|
85
|
+
if (this._bodies[bodyId]) {
|
86
|
+
throw "Body with this ID already added: " + bodyId;
|
87
|
+
}
|
88
|
+
this._bodies[bodyId] = new Body(bodyId, cfg);
|
89
|
+
this._bodyListDirty = true;
|
90
|
+
};
|
91
|
+
|
92
|
+
/**
|
93
|
+
* Updates a body
|
94
|
+
* @param {Number} bodyId Unique body ID
|
95
|
+
* @param {*} cfg New values for body properties
|
96
|
+
*/
|
97
|
+
Engine.prototype.updateBody = function (bodyId, cfg) {
|
98
|
+
var body = this._bodies[bodyId];
|
99
|
+
if (!body) {
|
100
|
+
throw "Body with this ID not found: " + bodyId;
|
101
|
+
}
|
102
|
+
body.update(cfg);
|
103
|
+
};
|
104
|
+
|
105
|
+
/**
|
106
|
+
* Removes a body that was added with {@link #addBody}
|
107
|
+
* @param {Number} bodyId ID of body
|
108
|
+
*/
|
109
|
+
Engine.prototype.removeBody = function (bodyId) {
|
110
|
+
delete this._bodies[bodyId];
|
111
|
+
this._bodyListDirty = true;
|
112
|
+
};
|
113
|
+
|
114
|
+
/**
|
115
|
+
* Finds updates in frustum intersection status for bodies,
|
116
|
+
* Returns an array of ststus updates for the bodies in a callback
|
117
|
+
* @param {Function(Array,Number)} callback Returns array of {@link Body}s that have changed status,
|
118
|
+
* plus length of the array
|
119
|
+
*/
|
120
|
+
Engine.prototype.integrate = function (callback) {
|
121
|
+
// Lazy-rebuilds frustum after engine reconfiguration
|
122
|
+
if (this._frustumDirty) {
|
123
|
+
this._rebuildFrustum();
|
124
|
+
}
|
125
|
+
// Lazy-rebuilds body list after body map updated
|
126
|
+
if (this._bodyListDirty) {
|
127
|
+
this._rebuildBodyList();
|
128
|
+
}
|
129
|
+
var numUpdatedBodies = 0;
|
130
|
+
var body;
|
131
|
+
var intersect;
|
132
|
+
var canvasSize;
|
133
|
+
|
134
|
+
for (var i = 0; i < this._numBodies; i++) {
|
135
|
+
body = this._bodyList[i];
|
136
|
+
intersect = -1;
|
137
|
+
canvasSize = -1;
|
138
|
+
if (body.frustumCull) {
|
139
|
+
// Frustum cull this body
|
140
|
+
intersect = this._frustum.textAxisBoxIntersection(body);
|
141
|
+
if (body.detailCull) {
|
142
|
+
// And detail cull
|
143
|
+
switch (intersect) {
|
144
|
+
case INTERSECT_FRUSTUM:
|
145
|
+
case INSIDE_FRUSTUM:
|
146
|
+
body.projBox.fromPoints(body.viewBox);
|
147
|
+
canvasSize = this._frustum.getProjectedSize(body.projBox);
|
148
|
+
break;
|
149
|
+
}
|
150
|
+
}
|
151
|
+
} else {
|
152
|
+
// Just detail cull
|
153
|
+
body.projBox.fromPoints(body.viewBox);
|
154
|
+
canvasSize = this._frustum.getProjectedSize(body.projBox);
|
155
|
+
}
|
156
|
+
|
157
|
+
if (intersect !== body.intersect || canvasSize != body.canvasSize) {
|
158
|
+
body.intersect = intersect;
|
159
|
+
body.canvasSize = canvasSize;
|
160
|
+
this._updatedBodies[numUpdatedBodies++] = body;
|
161
|
+
}
|
162
|
+
}
|
163
|
+
callback(this._updatedBodies, numUpdatedBodies);
|
164
|
+
};
|
165
|
+
|
166
|
+
/**
|
167
|
+
* Rebuilds culling frustum from matrices and viewport
|
168
|
+
*/
|
169
|
+
Engine.prototype._rebuildFrustum = function () {
|
170
|
+
this._frustum = new Frustum(this._viewMat, this._projMat, this._viewport);
|
171
|
+
this._frustumDirty = false;
|
172
|
+
};
|
173
|
+
|
174
|
+
/**
|
175
|
+
* Rebuilds body list from body map
|
176
|
+
*/
|
177
|
+
Engine.prototype._rebuildBodyList = function () {
|
178
|
+
this._numBodies = 0;
|
179
|
+
for (var bodyId in this._bodies) {
|
180
|
+
if (this._bodies.hasOwnProperty(bodyId)) {
|
181
|
+
this._bodyList[this._numBodies++] = this._bodies[bodyId];
|
182
|
+
}
|
183
|
+
}
|
184
|
+
this._bodyListDirty = false;
|
185
|
+
};
|
186
|
+
|
187
|
+
/**
|
188
|
+
* A body in the frustum culling engine
|
189
|
+
* @param {Number} bodyId Body ID, unique within the engine
|
190
|
+
* @param {*} cfg Body properties
|
191
|
+
* @param {*} [cfg.box] Axis-aligned world-space bounding box
|
192
|
+
* @param {Array(3)} [cfg.box.min] Axis-aligned bounding box minimum extents
|
193
|
+
* @param {Array(3)} [cfg.box.max] Axis-aligned bounding box maximum extents
|
194
|
+
* @constructor
|
195
|
+
*/
|
196
|
+
function Body(bodyId, cfg) {
|
197
|
+
|
198
|
+
/**
|
199
|
+
* Unique ID within engine
|
200
|
+
* @type {*}
|
201
|
+
*/
|
202
|
+
this.bodyId = bodyId;
|
203
|
+
|
204
|
+
/**
|
205
|
+
* World-space extents
|
206
|
+
*/
|
207
|
+
this.min = cfg.min;
|
208
|
+
this.max = cfg.max;
|
209
|
+
|
210
|
+
/**
|
211
|
+
* True when frustum culling is to be performed for this body
|
212
|
+
*/
|
213
|
+
this.frustumCull = cfg.frustumCull != undefined ? cfg.frustumCull : true;
|
214
|
+
|
215
|
+
/**
|
216
|
+
* True when projected canvas size is to be determined for this body
|
217
|
+
*/
|
218
|
+
this.detailCull = cfg.detailCull != undefined ? cfg.detailCull : true;
|
219
|
+
|
220
|
+
/**
|
221
|
+
* View-space extents
|
222
|
+
*/
|
223
|
+
this.viewBox = [
|
224
|
+
[this.min[0], this.min[1], this.min[2]],
|
225
|
+
[this.max[0], this.min[1], this.min[2]],
|
226
|
+
[this.max[0], this.max[1], this.min[2]],
|
227
|
+
[this.min[0], this.max[1], this.min[2]],
|
228
|
+
[this.min[0], this.min[1], this.max[2]],
|
229
|
+
[this.max[0], this.min[1], this.max[2]],
|
230
|
+
[this.max[0], this.max[1], this.max[2]],
|
231
|
+
[this.min[0], this.max[1], this.max[2]]
|
232
|
+
];
|
233
|
+
|
234
|
+
/**
|
235
|
+
* Projection-space extents
|
236
|
+
*/
|
237
|
+
this.projBox = new Box3();
|
238
|
+
|
239
|
+
/**
|
240
|
+
* Intersection status
|
241
|
+
* @type {Number}
|
242
|
+
*/
|
243
|
+
this.intersect = null;
|
244
|
+
|
245
|
+
/**
|
246
|
+
* Projected size
|
247
|
+
* @type {Number}
|
248
|
+
*/
|
249
|
+
this.canvasSize = null;
|
250
|
+
}
|
251
|
+
|
252
|
+
Body.prototype.update = function (cfg) {
|
253
|
+
// if (cfg.min || cfg.max) {
|
254
|
+
// if (cfg.min) {
|
255
|
+
// this.min = cfg.min;
|
256
|
+
// this.viewBox[0][0] = this.min[0];
|
257
|
+
// this.viewBox[0][1] = this.min[1];
|
258
|
+
// this.viewBox[0][2] = this.min[2];
|
259
|
+
//
|
260
|
+
// [this.max[0], this.min[1], this.min[2]],
|
261
|
+
// [this.max[0], this.max[1], this.min[2]],
|
262
|
+
// [this.min[0], this.max[1], this.min[2]],
|
263
|
+
// [this.min[0], this.min[1], this.max[2]],
|
264
|
+
// [this.max[0], this.min[1], this.max[2]],
|
265
|
+
// [this.max[0], this.max[1], this.max[2]],
|
266
|
+
// [this.min[0], this.max[1], this.max[2]]
|
267
|
+
// }
|
268
|
+
// if (cfg.max) {
|
269
|
+
// this.max = cfg.max;
|
270
|
+
// }
|
271
|
+
// this.viewBox[0][0]
|
272
|
+
// [this.min[0], this.min[1], this.min[2]],
|
273
|
+
// [this.max[0], this.min[1], this.min[2]],
|
274
|
+
// [this.max[0], this.max[1], this.min[2]],
|
275
|
+
// [this.min[0], this.max[1], this.min[2]],
|
276
|
+
// [this.min[0], this.min[1], this.max[2]],
|
277
|
+
// [this.max[0], this.min[1], this.max[2]],
|
278
|
+
// [this.max[0], this.max[1], this.max[2]],
|
279
|
+
// [this.min[0], this.max[1], this.max[2]]
|
280
|
+
// ]
|
281
|
+
// ;
|
282
|
+
//
|
283
|
+
// }
|
284
|
+
};
|
285
|
+
|
286
|
+
function Frustum(viewMat, projMat, viewport) {
|
287
|
+
|
288
|
+
var m = mat4();
|
289
|
+
|
290
|
+
mulMat4(projMat, viewMat, m);
|
291
|
+
|
292
|
+
// cache m indexes
|
293
|
+
var m0 = m[0], m1 = m[1], m2 = m[2], m3 = m[3];
|
294
|
+
var m4 = m[4], m5 = m[5], m6 = m[6], m7 = m[7];
|
295
|
+
var m8 = m[8], m9 = m[9], m10 = m[10], m11 = m[11];
|
296
|
+
var m12 = m[12], m13 = m[13], m14 = m[14], m15 = m[15];
|
297
|
+
|
298
|
+
//var q = [ m[3], m[7], m[11] ]; just reuse m indexes instead of making new var
|
299
|
+
var planes = [
|
300
|
+
new FrustumPlane(m3 - m0, m7 - m4, m11 - m8, m15 - m12),
|
301
|
+
new FrustumPlane(m3 + m0, m7 + m4, m11 + m8, m15 + m12),
|
302
|
+
new FrustumPlane(m3 - m1, m7 - m5, m11 - m9, m15 - m13),
|
303
|
+
new FrustumPlane(m3 + m1, m7 + m5, m11 + m9, m15 + m13),
|
304
|
+
new FrustumPlane(m3 - m2, m7 - m6, m11 - m10, m15 - m14),
|
305
|
+
new FrustumPlane(m3 + m2, m7 + m6, m11 + m10, m15 + m14)
|
306
|
+
];
|
307
|
+
|
308
|
+
// Resources for LOD
|
309
|
+
|
310
|
+
var rotVec = [
|
311
|
+
getColMat4(viewMat, 0),
|
312
|
+
getColMat4(viewMat, 1),
|
313
|
+
getColMat4(viewMat, 2)
|
314
|
+
];
|
315
|
+
|
316
|
+
var scaleVec = [
|
317
|
+
lenVec4(rotVec[0]),
|
318
|
+
lenVec4(rotVec[1]),
|
319
|
+
lenVec4(rotVec[2])
|
320
|
+
];
|
321
|
+
|
322
|
+
var scaleVecRcp = rcpVec3(scaleVec);
|
323
|
+
var sMat = scalingMat4v(scaleVec);
|
324
|
+
var sMatInv = scalingMat4v(scaleVecRcp);
|
325
|
+
|
326
|
+
mulVec4Scalar(rotVec[0], scaleVecRcp[0]);
|
327
|
+
mulVec4Scalar(rotVec[1], scaleVecRcp[1]);
|
328
|
+
mulVec4Scalar(rotVec[2], scaleVecRcp[2]);
|
329
|
+
|
330
|
+
var rotMatInverse = identityMat4();
|
331
|
+
|
332
|
+
setRowMat4(rotMatInverse, 0, rotVec[0]);
|
333
|
+
setRowMat4(rotMatInverse, 1, rotVec[1]);
|
334
|
+
setRowMat4(rotMatInverse, 2, rotVec[2]);
|
335
|
+
|
336
|
+
if (!this.matrix) {
|
337
|
+
this.matrix = mat4();
|
338
|
+
}
|
339
|
+
|
340
|
+
mulMat4(projMat, viewMat, this.matrix);
|
341
|
+
|
342
|
+
if (!this.billboardMatrix) {
|
343
|
+
this.billboardMatrix = mat4();
|
344
|
+
}
|
345
|
+
|
346
|
+
mulMat4(sMatInv, mulMat4(rotMatInverse, sMat), this.billboardMatrix);
|
347
|
+
this.viewport = viewport.slice(0, 4);
|
348
|
+
|
349
|
+
this.textAxisBoxIntersection = function (box) {
|
350
|
+
var ret = INSIDE_FRUSTUM;
|
351
|
+
var bminmax = [ box.min, box.max ];
|
352
|
+
var plane = null;
|
353
|
+
for (var i = 0; i < 6; ++i) {
|
354
|
+
plane = planes[i];
|
355
|
+
if (((plane.normal[0] * bminmax[plane.testVertex[0]][0]) +
|
356
|
+
(plane.normal[1] * bminmax[plane.testVertex[1]][1]) +
|
357
|
+
(plane.normal[2] * bminmax[plane.testVertex[2]][2]) +
|
358
|
+
(plane.offset)) < 0.0) {
|
359
|
+
return OUTSIDE_FRUSTUM;
|
360
|
+
}
|
361
|
+
if (((plane.normal[0] * bminmax[1 - plane.testVertex[0]][0]) +
|
362
|
+
(plane.normal[1] * bminmax[1 - plane.testVertex[1]][1]) +
|
363
|
+
(plane.normal[2] * bminmax[1 - plane.testVertex[2]][2]) +
|
364
|
+
(plane.offset)) < 0.0) {
|
365
|
+
ret = INTERSECT_FRUSTUM;
|
366
|
+
}
|
367
|
+
}
|
368
|
+
return ret;
|
369
|
+
};
|
370
|
+
|
371
|
+
this.getProjectedSize = function (box) {
|
372
|
+
var diagVec = mat4();
|
373
|
+
subVec3(box.max, box.min, diagVec);
|
374
|
+
|
375
|
+
var diagSize = lenVec3(diagVec);
|
376
|
+
|
377
|
+
var size = Math.abs(diagSize);
|
378
|
+
|
379
|
+
var p0 = [
|
380
|
+
(box.min[0] + box.max[0]) * 0.5,
|
381
|
+
(box.min[1] + box.max[1]) * 0.5,
|
382
|
+
(box.min[2] + box.max[2]) * 0.5,
|
383
|
+
0.0];
|
384
|
+
|
385
|
+
var halfSize = size * 0.5;
|
386
|
+
var p1 = [ -halfSize, 0.0, 0.0, 1.0 ];
|
387
|
+
var p2 = [ halfSize, 0.0, 0.0, 1.0 ];
|
388
|
+
|
389
|
+
p1 = mulMat4v4(this.billboardMatrix, p1);
|
390
|
+
p1 = addVec4(p1, p0);
|
391
|
+
p1 = projectVec4(mulMat4v4(this.matrix, p1));
|
392
|
+
|
393
|
+
p2 = mulMat4v4(this.billboardMatrix, p2);
|
394
|
+
p2 = addVec4(p2, p0);
|
395
|
+
p2 = projectVec4(mulMat4v4(this.matrix, p2));
|
396
|
+
|
397
|
+
return viewport[2] * Math.abs(p2[0] - p1[0]);
|
398
|
+
};
|
399
|
+
|
400
|
+
|
401
|
+
this.getProjectedState = function (modelviewBox) {
|
402
|
+
var viewviewBox = transformPoints3(this.matrix, modelviewBox);
|
403
|
+
|
404
|
+
//var canvasBox = {
|
405
|
+
// min: [10000000, 10000000 ],
|
406
|
+
// max: [-10000000, -10000000]
|
407
|
+
//};
|
408
|
+
// separate variables instead of indexing an array
|
409
|
+
var canvasBoxMin0 = 10000000, canvasBoxMin1 = 10000000;
|
410
|
+
var canvasBoxMax0 = -10000000, canvasBoxMax1 = -10000000;
|
411
|
+
|
412
|
+
var v, x, y;
|
413
|
+
|
414
|
+
var arrLen = viewviewBox.length;
|
415
|
+
for (var i = 0; i < arrLen; ++i) {
|
416
|
+
v = projectVec4(viewviewBox[i]);
|
417
|
+
x = v[0];
|
418
|
+
y = v[1];
|
419
|
+
|
420
|
+
if (x < -0.5) {
|
421
|
+
x = -0.5;
|
422
|
+
}
|
423
|
+
|
424
|
+
if (y < -0.5) {
|
425
|
+
y = -0.5;
|
426
|
+
}
|
427
|
+
|
428
|
+
if (x > 0.5) {
|
429
|
+
x = 0.5;
|
430
|
+
}
|
431
|
+
|
432
|
+
if (y > 0.5) {
|
433
|
+
y = 0.5;
|
434
|
+
}
|
435
|
+
|
436
|
+
|
437
|
+
if (x < canvasBoxMin0) {
|
438
|
+
canvasBoxMin0 = x;
|
439
|
+
}
|
440
|
+
if (y < canvasBoxMin1) {
|
441
|
+
canvasBoxMin1 = y;
|
442
|
+
}
|
443
|
+
if (x > canvasBoxMax0) {
|
444
|
+
canvasBoxMax0 = x;
|
445
|
+
}
|
446
|
+
if (y > canvasBoxMax1) {
|
447
|
+
canvasBoxMax1 = y;
|
448
|
+
}
|
449
|
+
}
|
450
|
+
|
451
|
+
canvasBoxMin0 += 0.5;
|
452
|
+
canvasBoxMin1 += 0.5;
|
453
|
+
canvasBoxMax0 += 0.5;
|
454
|
+
canvasBoxMax1 += 0.5;
|
455
|
+
|
456
|
+
// cache viewport indexes
|
457
|
+
var viewport2 = viewport[2], viewport3 = viewport[3];
|
458
|
+
|
459
|
+
canvasBoxMin0 = (canvasBoxMin0 * (viewport2 + 15));
|
460
|
+
canvasBoxMin1 = (canvasBoxMin1 * (viewport3 + 15));
|
461
|
+
canvasBoxMax0 = (canvasBoxMax0 * (viewport2 + 15));
|
462
|
+
canvasBoxMax1 = (canvasBoxMax1 * (viewport3 + 15));
|
463
|
+
|
464
|
+
var diagCanvasBoxVec = mat4();
|
465
|
+
subVec2([canvasBoxMax0, canvasBoxMax1], [canvasBoxMin0, canvasBoxMin1], diagCanvasBoxVec);
|
466
|
+
var diagCanvasBoxSize = lenVec2(diagCanvasBoxVec);
|
467
|
+
|
468
|
+
if (canvasBoxMin0 < 0) {
|
469
|
+
canvasBoxMin0 = 0;
|
470
|
+
}
|
471
|
+
if (canvasBoxMax0 > viewport2) {
|
472
|
+
canvasBoxMax0 = viewport2;
|
473
|
+
}
|
474
|
+
|
475
|
+
if (canvasBoxMin1 < 0) {
|
476
|
+
canvasBoxMin1 = 0;
|
477
|
+
}
|
478
|
+
if (canvasBoxMax1 > viewport3) {
|
479
|
+
canvasBoxMax1 = viewport3;
|
480
|
+
}
|
481
|
+
return diagCanvasBoxSize;
|
482
|
+
// return {
|
483
|
+
// canvasBox:{
|
484
|
+
// min:[canvasBoxMin0, canvasBoxMin1 ],
|
485
|
+
// max:[canvasBoxMax0, canvasBoxMax1 ]
|
486
|
+
// },
|
487
|
+
// canvasSize:diagCanvasBoxSize
|
488
|
+
// };
|
489
|
+
};
|
490
|
+
}
|
491
|
+
|
492
|
+
function mat4() {
|
493
|
+
return new Array(16);
|
494
|
+
}
|
495
|
+
|
496
|
+
function mulMat4(a, b, dest) {
|
497
|
+
|
498
|
+
if (!dest) {
|
499
|
+
dest = a;
|
500
|
+
}
|
501
|
+
|
502
|
+
// Cache the matrix values (makes for huge speed increases!)
|
503
|
+
var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3];
|
504
|
+
var a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7];
|
505
|
+
var a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11];
|
506
|
+
var a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
|
507
|
+
|
508
|
+
var b00 = b[0], b01 = b[1], b02 = b[2], b03 = b[3];
|
509
|
+
var b10 = b[4], b11 = b[5], b12 = b[6], b13 = b[7];
|
510
|
+
var b20 = b[8], b21 = b[9], b22 = b[10], b23 = b[11];
|
511
|
+
var b30 = b[12], b31 = b[13], b32 = b[14], b33 = b[15];
|
512
|
+
|
513
|
+
dest[0] = b00 * a00 + b01 * a10 + b02 * a20 + b03 * a30;
|
514
|
+
dest[1] = b00 * a01 + b01 * a11 + b02 * a21 + b03 * a31;
|
515
|
+
dest[2] = b00 * a02 + b01 * a12 + b02 * a22 + b03 * a32;
|
516
|
+
dest[3] = b00 * a03 + b01 * a13 + b02 * a23 + b03 * a33;
|
517
|
+
dest[4] = b10 * a00 + b11 * a10 + b12 * a20 + b13 * a30;
|
518
|
+
dest[5] = b10 * a01 + b11 * a11 + b12 * a21 + b13 * a31;
|
519
|
+
dest[6] = b10 * a02 + b11 * a12 + b12 * a22 + b13 * a32;
|
520
|
+
dest[7] = b10 * a03 + b11 * a13 + b12 * a23 + b13 * a33;
|
521
|
+
dest[8] = b20 * a00 + b21 * a10 + b22 * a20 + b23 * a30;
|
522
|
+
dest[9] = b20 * a01 + b21 * a11 + b22 * a21 + b23 * a31;
|
523
|
+
dest[10] = b20 * a02 + b21 * a12 + b22 * a22 + b23 * a32;
|
524
|
+
dest[11] = b20 * a03 + b21 * a13 + b22 * a23 + b23 * a33;
|
525
|
+
dest[12] = b30 * a00 + b31 * a10 + b32 * a20 + b33 * a30;
|
526
|
+
dest[13] = b30 * a01 + b31 * a11 + b32 * a21 + b33 * a31;
|
527
|
+
dest[14] = b30 * a02 + b31 * a12 + b32 * a22 + b33 * a32;
|
528
|
+
dest[15] = b30 * a03 + b31 * a13 + b32 * a23 + b33 * a33;
|
529
|
+
|
530
|
+
return dest;
|
531
|
+
}
|
532
|
+
|
533
|
+
function FrustumPlane(nx, ny, nz, offset) {
|
534
|
+
var s = 1.0 / Math.sqrt(nx * nx + ny * ny + nz * nz);
|
535
|
+
this.normal = [nx * s, ny * s, nz * s];
|
536
|
+
this.offset = offset * s;
|
537
|
+
this.testVertex = [
|
538
|
+
(this.normal[0] >= 0.0) ? (1) : (0),
|
539
|
+
(this.normal[1] >= 0.0) ? (1) : (0),
|
540
|
+
(this.normal[2] >= 0.0) ? (1) : (0)];
|
541
|
+
}
|
542
|
+
|
543
|
+
function getColMat4(m, c) {
|
544
|
+
var i = c * 4;
|
545
|
+
return [m[i], m[i + 1], m[i + 2], m[i + 3]];
|
546
|
+
}
|
547
|
+
|
548
|
+
function lenVec4(v) {
|
549
|
+
return Math.sqrt(sqLenVec4(v));
|
550
|
+
}
|
551
|
+
|
552
|
+
function sqLenVec4(v) {
|
553
|
+
return dotVec4(v, v);
|
554
|
+
}
|
555
|
+
|
556
|
+
function dotVec4(u, v) {
|
557
|
+
return (u[0] * v[0] + u[1] * v[1] + u[2] * v[2] + u[3] * v[3]);
|
558
|
+
}
|
559
|
+
|
560
|
+
function rcpVec3(v, dest) {
|
561
|
+
return divScalarVec3(1.0, v, dest);
|
562
|
+
}
|
563
|
+
|
564
|
+
function divScalarVec3(s, v, dest) {
|
565
|
+
if (!dest) {
|
566
|
+
dest = v;
|
567
|
+
}
|
568
|
+
dest[0] = s / v[0];
|
569
|
+
dest[1] = s / v[1];
|
570
|
+
dest[2] = s / v[2];
|
571
|
+
return dest;
|
572
|
+
}
|
573
|
+
|
574
|
+
function scalingMat4v(v) {
|
575
|
+
var m = identityMat4();
|
576
|
+
m[0] = v[0];
|
577
|
+
m[5] = v[1];
|
578
|
+
m[10] = v[2];
|
579
|
+
return m;
|
580
|
+
}
|
581
|
+
|
582
|
+
function identityMat4() {
|
583
|
+
return diagonalMat4v([1.0, 1.0, 1.0, 1.0]);
|
584
|
+
}
|
585
|
+
|
586
|
+
function diagonalMat4v(v) {
|
587
|
+
return [
|
588
|
+
v[0], 0.0, 0.0, 0.0,
|
589
|
+
0.0, v[1], 0.0, 0.0,
|
590
|
+
0.0, 0.0, v[2], 0.0,
|
591
|
+
0.0, 0.0, 0.0, v[3]
|
592
|
+
];
|
593
|
+
}
|
594
|
+
|
595
|
+
function mulVec4Scalar(v, s, dest) {
|
596
|
+
if (!dest) {
|
597
|
+
dest = v;
|
598
|
+
}
|
599
|
+
dest[0] = v[0] * s;
|
600
|
+
dest[1] = v[1] * s;
|
601
|
+
dest[2] = v[2] * s;
|
602
|
+
dest[3] = v[3] * s;
|
603
|
+
return dest;
|
604
|
+
}
|
605
|
+
|
606
|
+
function setRowMat4(m, r, v) {
|
607
|
+
m[r] = v[0];
|
608
|
+
m[r + 4] = v[1];
|
609
|
+
m[r + 8] = v[2];
|
610
|
+
m[r + 12] = v[3];
|
611
|
+
}
|
612
|
+
|
613
|
+
function subVec3(u, v, dest) {
|
614
|
+
if (!dest) {
|
615
|
+
dest = u;
|
616
|
+
}
|
617
|
+
dest[0] = u[0] - v[0];
|
618
|
+
dest[1] = u[1] - v[1];
|
619
|
+
dest[2] = u[2] - v[2];
|
620
|
+
return dest;
|
621
|
+
}
|
622
|
+
|
623
|
+
function lenVec3(v) {
|
624
|
+
return Math.sqrt(sqLenVec3(v));
|
625
|
+
}
|
626
|
+
|
627
|
+
function mulMat4v4(m, v) {
|
628
|
+
var v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3];
|
629
|
+
|
630
|
+
return [
|
631
|
+
m[0] * v0 + m[4] * v1 + m[8] * v2 + m[12] * v3,
|
632
|
+
m[1] * v0 + m[5] * v1 + m[9] * v2 + m[13] * v3,
|
633
|
+
m[2] * v0 + m[6] * v1 + m[10] * v2 + m[14] * v3,
|
634
|
+
m[3] * v0 + m[7] * v1 + m[11] * v2 + m[15] * v3
|
635
|
+
];
|
636
|
+
}
|
637
|
+
|
638
|
+
function sqLenVec3(v) {
|
639
|
+
return dotVector3(v, v);
|
640
|
+
}
|
641
|
+
|
642
|
+
function dotVector3(u, v) {
|
643
|
+
return (u[0] * v[0] + u[1] * v[1] + u[2] * v[2]);
|
644
|
+
}
|
645
|
+
|
646
|
+
function addVec4(u, v, dest) {
|
647
|
+
if (!dest) {
|
648
|
+
dest = u;
|
649
|
+
}
|
650
|
+
dest[0] = u[0] + v[0];
|
651
|
+
dest[1] = u[1] + v[1];
|
652
|
+
dest[2] = u[2] + v[2];
|
653
|
+
dest[3] = u[3] + v[3];
|
654
|
+
return dest;
|
655
|
+
}
|
656
|
+
|
657
|
+
function projectVec4(v) {
|
658
|
+
var f = 1.0 / v[3];
|
659
|
+
return [v[0] * f, v[1] * f, v[2] * f, 1.0];
|
660
|
+
}
|
661
|
+
|
662
|
+
function transformPoints3(m, points) {
|
663
|
+
var result = new Array(points.length);
|
664
|
+
var len = points.length;
|
665
|
+
var p0, p1, p2;
|
666
|
+
var pi;
|
667
|
+
// cache values
|
668
|
+
var m0 = m[0], m1 = m[1], m2 = m[2], m3 = m[3];
|
669
|
+
var m4 = m[4], m5 = m[5], m6 = m[6], m7 = m[7];
|
670
|
+
var m8 = m[8], m9 = m[9], m10 = m[10], m11 = m[11];
|
671
|
+
var m12 = m[12], m13 = m[13], m14 = m[14], m15 = m[15];
|
672
|
+
for (var i = 0; i < len; ++i) {
|
673
|
+
// cache values
|
674
|
+
pi = points[i];
|
675
|
+
p0 = pi[0];
|
676
|
+
p1 = pi[1];
|
677
|
+
p2 = pi[2];
|
678
|
+
result[i] = [
|
679
|
+
(m0 * p0) + (m4 * p1) + (m8 * p2) + m12,
|
680
|
+
(m1 * p0) + (m5 * p1) + (m9 * p2) + m13,
|
681
|
+
(m2 * p0) + (m6 * p1) + (m10 * p2) + m14,
|
682
|
+
(m3 * p0) + (m7 * p1) + (m11 * p2) + m15
|
683
|
+
];
|
684
|
+
}
|
685
|
+
return result;
|
686
|
+
}
|
687
|
+
|
688
|
+
//function subVec2(u, v, dest) {
|
689
|
+
// if (!dest) {
|
690
|
+
// dest = u;
|
691
|
+
// }
|
692
|
+
// dest[0] = u[0] - v[0];
|
693
|
+
// dest[1] = u[1] - v[1];
|
694
|
+
// return dest;
|
695
|
+
//}
|
696
|
+
//
|
697
|
+
//function lenVec2(v) {
|
698
|
+
// return Math.sqrt(sqLenVec2(v));
|
699
|
+
//}
|
700
|
+
|
701
|
+
function sqLenVec2(v) {
|
702
|
+
return dotVector2(v, v);
|
703
|
+
}
|
704
|
+
|
705
|
+
function dotVector2(u, v) {
|
706
|
+
return (u[0] * v[0] + u[1] * v[1]);
|
707
|
+
}
|
708
|
+
|
709
|
+
var MAX_DOUBLE = Number.POSITIVE_INFINITY;
|
710
|
+
var MIN_DOUBLE = Number.NEGATIVE_INFINITY;
|
711
|
+
|
712
|
+
function Box3(min, max) {
|
713
|
+
|
714
|
+
this.min = min || [ MAX_DOUBLE, MAX_DOUBLE, MAX_DOUBLE ];
|
715
|
+
this.max = max || [ MIN_DOUBLE, MIN_DOUBLE, MIN_DOUBLE ];
|
716
|
+
|
717
|
+
this.init = function (min, max) {
|
718
|
+
this.min[0] = min[0];
|
719
|
+
this.min[1] = min[1];
|
720
|
+
this.min[2] = min[2];
|
721
|
+
this.max[0] = max[0];
|
722
|
+
this.max[1] = max[1];
|
723
|
+
this.max[2] = max[2];
|
724
|
+
return this;
|
725
|
+
};
|
726
|
+
|
727
|
+
this.fromPoints = function (points) {
|
728
|
+
var pointsLength = points.length;
|
729
|
+
for (var i = 0; i < pointsLength; ++i) {
|
730
|
+
// var points_i3 = points[i][3];
|
731
|
+
var points_i3 = 1;
|
732
|
+
var pDiv0 = points[i][0] / points_i3;
|
733
|
+
var pDiv1 = points[i][1] / points_i3;
|
734
|
+
var pDiv2 = points[i][2] / points_i3;
|
735
|
+
|
736
|
+
if (pDiv0 < this.min[0]) {
|
737
|
+
this.min[0] = pDiv0;
|
738
|
+
}
|
739
|
+
if (pDiv1 < this.min[1]) {
|
740
|
+
this.min[1] = pDiv1;
|
741
|
+
}
|
742
|
+
if (pDiv2 < this.min[2]) {
|
743
|
+
this.min[2] = pDiv2;
|
744
|
+
}
|
745
|
+
if (pDiv0 > this.max[0]) {
|
746
|
+
this.max[0] = pDiv0;
|
747
|
+
}
|
748
|
+
if (pDiv1 > this.max[1]) {
|
749
|
+
this.max[1] = pDiv1;
|
750
|
+
}
|
751
|
+
if (pDiv2 > this.max[2]) {
|
752
|
+
this.max[2] = pDiv2;
|
753
|
+
}
|
754
|
+
}
|
755
|
+
return this;
|
756
|
+
};
|
757
|
+
|
758
|
+
this.isEmpty = function () {
|
759
|
+
return (
|
760
|
+
(this.min[0] >= this.max[0]) &&
|
761
|
+
(this.min[1] >= this.max[1]) &&
|
762
|
+
(this.min[2] >= this.max[2])
|
763
|
+
);
|
764
|
+
};
|
765
|
+
|
766
|
+
this.getCenter = function () {
|
767
|
+
return [
|
768
|
+
(this.max[0] + this.min[0]) / 2.0,
|
769
|
+
(this.max[1] + this.min[1]) / 2.0,
|
770
|
+
(this.max[2] + this.min[2]) / 2.0
|
771
|
+
];
|
772
|
+
};
|
773
|
+
|
774
|
+
this.getSize = function () {
|
775
|
+
return [
|
776
|
+
(this.max[0] - this.min[0]),
|
777
|
+
(this.max[1] - this.min[1]),
|
778
|
+
(this.max[2] - this.min[2])
|
779
|
+
];
|
780
|
+
};
|
781
|
+
|
782
|
+
this.getFacesAreas = function () {
|
783
|
+
var s = this.size;
|
784
|
+
return [
|
785
|
+
(s[1] * s[2]),
|
786
|
+
(s[0] * s[2]),
|
787
|
+
(s[0] * s[1])
|
788
|
+
];
|
789
|
+
};
|
790
|
+
|
791
|
+
this.getSurfaceArea = function () {
|
792
|
+
var a = this.getFacesAreas();
|
793
|
+
return ((a[0] + a[1] + a[2]) * 2.0);
|
794
|
+
};
|
795
|
+
|
796
|
+
this.getVolume = function () {
|
797
|
+
var s = this.size;
|
798
|
+
return (s[0] * s[1] * s[2]);
|
799
|
+
};
|
800
|
+
|
801
|
+
this.getOffset = function (half_delta) {
|
802
|
+
this.min[0] -= half_delta;
|
803
|
+
this.min[1] -= half_delta;
|
804
|
+
this.min[2] -= half_delta;
|
805
|
+
this.max[0] += half_delta;
|
806
|
+
this.max[1] += half_delta;
|
807
|
+
this.max[2] += half_delta;
|
808
|
+
return this;
|
809
|
+
};
|
810
|
+
}
|