├── screenshot.jpg ├── docs ├── assets │ ├── images │ │ └── logo.png │ ├── dependencies │ │ ├── gl-matrix-LICENSE │ │ ├── dat.gui.css │ │ ├── dat.gui-LICENSE │ │ └── dat.gui.min.js │ ├── css │ │ └── index.css │ └── scripts │ │ └── index.js └── index.html ├── source ├── assets │ ├── images │ │ └── logo.png │ ├── css │ │ └── index.css │ └── scripts │ │ └── index.js └── index.html └── README.md /screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lettier/isosurface/HEAD/screenshot.jpg -------------------------------------------------------------------------------- /docs/assets/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lettier/isosurface/HEAD/docs/assets/images/logo.png -------------------------------------------------------------------------------- /source/assets/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lettier/isosurface/HEAD/source/assets/images/logo.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |  2 | 3 | # Isosurface Extraction 4 | 5 | Isosurface extraction using the Marching Cubes algorithm. Uses only pure WebGL. 6 | 7 | Requires [glMatrix](https://github.com/toji/gl-matrix) and [dat.gui](https://github.com/dataarts/dat.gui). 8 | 9 | (C) 2014 David Lettier 10 | [lettier.com](http://www.lettier.com) 11 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 |GUI\'s constructor:\n\n \n\n localStorage on exit.\n\n localStorage will\n override those passed to dat.GUI\'s constructor. This makes it\n easier to work incrementally, but localStorage is fragile,\n and your friends may not see the same values you do.\n\n
";
892 |
893 | document.body.appendChild( logo_box );
894 |
895 | var logo_image = document.getElementById( "logo" );
896 | logo_image_height = logo_image.clientHeight * 0.5;
897 | logo_image_width = logo_image.clientWidth * 0.5;
898 | logo_image.style.height = logo_image_height + "px";
899 | logo_image.style.width = logo_image_width + "px";
900 | logo_box.style.top = window.innerHeight - logo_image_height - 10 + "px";
901 | logo_box.style.left = window.innerWidth - logo_image_width - 10 + "px";
902 |
903 | }
904 |
905 | // Pass to the vertex shader the needed matrices.
906 |
907 | function setMatrixUniforms( )
908 | {
909 |
910 | // Pass the vertex shader the projection matrix and the model-view matrix.
911 |
912 | gl.uniformMatrix4fv( shaderProgram.pMatrixUniform, false, pMatrix );
913 | gl.uniformMatrix4fv( shaderProgram.mvMatrixUniform, false, mvMatrix );
914 |
915 | // Pass the vertex normal matrix to the shader so it can compute the lighting calculations.
916 |
917 | var normalMatrix = mat3.create( );
918 | mat3.normalFromMat4( normalMatrix, mvMatrix );
919 | gl.uniformMatrix3fv( shaderProgram.nMatrixUniform, false, normalMatrix );
920 |
921 | }
922 |
923 | function mvPushMatrix( )
924 | {
925 |
926 | // Save the model view matrix for later use.
927 |
928 | var copy = mat4.create( );
929 | copy = mat4.copy( copy, mvMatrix );
930 | mvMatrixStack.push( copy );
931 |
932 | }
933 |
934 | function mvPopMatrix( )
935 | {
936 |
937 | // Gather the previously pushed model view matrix.
938 |
939 | if ( mvMatrixStack.length === 0 )
940 | {
941 |
942 | console.error( "mvMatrixStack empty." );
943 |
944 | }
945 |
946 | mvMatrix = mvMatrixStack.pop( );
947 | }
948 |
949 | // The function renders the isosurfaces lit with the point light.
950 | // It also animates the rotation of the isosurfaces.
951 |
952 | function drawScene( timestamp )
953 | {
954 |
955 | // Call this function to draw the next frame.
956 |
957 | window.requestAnimationFrame( drawScene );
958 |
959 | // Time based animation instead of frame based animation.
960 |
961 | var time_now = new Date( ).getTime( );
962 |
963 | if ( time_last !== 0 )
964 | {
965 |
966 | var time_delta = ( time_now - time_last ) / 1000.0;
967 |
968 | rotation_radians += rotation_radians_step * time_delta;
969 |
970 | if ( rotation_radians > ( Math.PI * 2 ) ) rotation_radians = 0.0;
971 |
972 | if ( Number(use_lighting) === 1 )
973 | {
974 |
975 | point_light_theta += point_light_theta_step * time_delta;
976 | point_light_phi += point_light_phi_step * time_delta;
977 |
978 | if ( point_light_theta > ( Math.PI * 2 ) ) point_light_theta = 0.0;
979 | if ( point_light_phi > ( Math.PI * 2 ) ) point_light_phi = 0.0;
980 |
981 | point_light_theta1 += point_light_theta_step1 * time_delta;
982 | point_light_phi1 += point_light_phi_step1 * time_delta;
983 |
984 | if ( point_light_theta1 > ( Math.PI * 2 ) ) point_light_theta1 = 0.0;
985 | if ( point_light_phi1 > ( Math.PI * 2 ) ) point_light_phi1 = 0.0;
986 |
987 | }
988 |
989 | }
990 |
991 | time_last = time_now;
992 |
993 | // Set the size of and clear the render window.
994 |
995 | gl.viewport( 0, 0, gl.viewportWidth, gl.viewportHeight );
996 |
997 | gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );
998 |
999 | // Create the projection matrix.
1000 |
1001 | var near = 0.1;
1002 | var far = 50.0;
1003 | var fov_d = 55.0;
1004 | var fov_r = 55 * ( Math.PI / 180.0 );
1005 |
1006 | if ( JSON.parse(perspective_projection) )
1007 | {
1008 |
1009 | // Resulting perspective matrix, FOV in radians, aspect ratio, near, and far clipping plane.
1010 |
1011 | mat4.perspective( pMatrix, fov_r, gl.viewportWidth / gl.viewportHeight, near, far );
1012 |
1013 | // Let the fragment shader know that perspective projection is being used.
1014 |
1015 | gl.uniform1i( shaderProgram.perspectiveProjection, 1 );
1016 |
1017 | }
1018 | else
1019 | {
1020 |
1021 | // The goal is to have the object be about the same size in the window
1022 | // during orthographic project as it is during perspective projection.
1023 |
1024 | var a = gl.viewportWidth / gl.viewportHeight; // Window aspect ratio.
1025 | var h = 2 * ( 25 * Math.tan( fov_r / 2 ) ); // 25 is the absolute distance from the world origin to all of the isosurfaces' local origins.
1026 | var w = h * a; // Knowing the new window height size, get the new window width size based on the aspect ratio.
1027 |
1028 | // The canvas' origin is the upper left corner. To the right is the positive x-axis.
1029 | // Going down is the positive y-axis.
1030 |
1031 | // Any object at the world origin would appear at the upper left hand corner.
1032 | // Shift the origin to the middle of the screen.
1033 |
1034 | // Also, invert the y-axis as WebgL's positive y-axis points up while the canvas' positive
1035 | // y-axis points down the screen.
1036 |
1037 | // (0,O)------------------------(w,0)
1038 | // | |
1039 | // | |
1040 | // | |
1041 | // (0,h)------------------------(w,h)
1042 | //
1043 | // (-(w/2),(h/2))------------------------((w/2),(h/2))
1044 | // | |
1045 | // | (0,0) |
1046 | // | |
1047 | // (-(w/2),-(h/2))------------------------((w/2),-(h/2))
1048 |
1049 | // Resulting perspective matrix, left, right, bottom, top, near, and far clipping plane.
1050 |
1051 | mat4.ortho(
1052 |
1053 | pMatrix,
1054 | -( w / 2 ),
1055 | ( w / 2 ),
1056 | -( h / 2 ),
1057 | ( h / 2 ),
1058 | near,
1059 | far
1060 |
1061 | );
1062 |
1063 | // Let the fragment shader know that orthographic projection is being used.
1064 |
1065 | gl.uniform1i( shaderProgram.perspectiveProjection, 0 );
1066 |
1067 | }
1068 |
1069 | // Render different buffers to screen.
1070 |
1071 | gl.uniform1i( shaderProgram.showDepth, show_depth );
1072 | gl.uniform1i( shaderProgram.showNormals, show_normals );
1073 | gl.uniform1i( shaderProgram.showPosition, show_position );
1074 |
1075 | // Move to the 3D space origin.
1076 |
1077 | mat4.identity( mvMatrix );
1078 |
1079 | // Disable alpha blending.
1080 |
1081 | gl.disable( gl.BLEND );
1082 |
1083 | alpha_blending_enabled = 0;
1084 |
1085 | gl.uniform1i( shaderProgram.alphaBlendingEnabled, alpha_blending_enabled );
1086 |
1087 | if ( Number(use_lighting) === 1 )
1088 | {
1089 |
1090 | // Pass the lighting parameters to the fragment shader.
1091 |
1092 | // Global ambient color.
1093 |
1094 | gl.uniform3f( shaderProgram.ambientColorUniform, base_color[ 0 ], base_color[ 1 ], base_color[ 2 ] );
1095 |
1096 | // Point light 1.
1097 |
1098 | var point_light_position_x = 0 + 13.5 * Math.cos( point_light_theta ) * Math.sin( point_light_phi );
1099 | var point_light_position_y = 0 + 13.5 * Math.sin( point_light_theta ) * Math.sin( point_light_phi );
1100 | var point_light_position_z = -25 + 13.5 * Math.cos( point_light_phi );
1101 |
1102 | gl.uniform3f( shaderProgram.pointLightingColorUniform, lighting_power, lighting_power, lighting_power );
1103 |
1104 | gl.uniform3f( shaderProgram.pointLightingLocationUniform, point_light_position_x, point_light_position_y, point_light_position_z );
1105 |
1106 | // Point light 2.
1107 |
1108 | var point_light_position_x1 = 0 + 8.0 * Math.cos( point_light_theta1 ) * Math.sin( point_light_phi1 );
1109 | var point_light_position_y1 = 0 + 8.0 * Math.sin( point_light_theta1 ) * Math.sin( point_light_phi1 );
1110 | var point_light_position_z1 = -25 + 8.0 * Math.cos( point_light_phi1 );
1111 |
1112 | gl.uniform3f( shaderProgram.ambientColorUniform1, base_color[ 0 ], base_color[ 1 ], base_color[ 2 ] );
1113 |
1114 | gl.uniform3f( shaderProgram.pointLightingColorUniform1, lighting_power, lighting_power, lighting_power );
1115 |
1116 | gl.uniform3f( shaderProgram.pointLightingLocationUniform1, point_light_position_x1, point_light_position_y1, point_light_position_z1 );
1117 |
1118 | // Turn off lighting for a moment so that the point light isosurface is
1119 | // bright simulating that the light is emanating from the surface.
1120 |
1121 | use_lighting = 0;
1122 |
1123 | gl.uniform1i( shaderProgram.useLightingUniform, use_lighting );
1124 |
1125 | // Point light surfaces.
1126 |
1127 | // Save the model view matrix state.
1128 |
1129 | mvPushMatrix( );
1130 |
1131 | // Point light surface 1.
1132 |
1133 | mat4.translate( mvMatrix, mvMatrix, [ point_light_position_x, point_light_position_y, point_light_position_z ] );
1134 |
1135 | gl.bindBuffer( gl.ARRAY_BUFFER, pointLightSphereVertexPositionBuffer );
1136 | gl.vertexAttribPointer( shaderProgram.vertexPositionAttribute, pointLightSphereVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0 );
1137 |
1138 | gl.bindBuffer( gl.ARRAY_BUFFER, pointLightSphereVertexNormalBuffer );
1139 | gl.vertexAttribPointer( shaderProgram.vertexNormalAttribute, pointLightSphereVertexNormalBuffer.itemSize, gl.FLOAT, false, 0, 0 );
1140 |
1141 | gl.bindBuffer( gl.ARRAY_BUFFER, pointLightSphereVertexColorBuffer );
1142 | gl.vertexAttribPointer( shaderProgram.vertexColorAttribute, pointLightSphereVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0 );
1143 |
1144 | setMatrixUniforms( );
1145 |
1146 | gl.drawArrays( gl.TRIANGLES, 0, pointLightSphereVertexPositionBuffer.numItems );
1147 |
1148 | mvPopMatrix( );
1149 |
1150 | // Save the model view matrix state.
1151 |
1152 | mvPushMatrix( );
1153 |
1154 | // Point light surface 2.
1155 |
1156 | mat4.translate( mvMatrix, mvMatrix, [ point_light_position_x1, point_light_position_y1, point_light_position_z1 ] );
1157 |
1158 | gl.bindBuffer( gl.ARRAY_BUFFER, pointLightSphereVertexPositionBuffer );
1159 | gl.vertexAttribPointer( shaderProgram.vertexPositionAttribute, pointLightSphereVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0 );
1160 |
1161 | gl.bindBuffer( gl.ARRAY_BUFFER, pointLightSphereVertexNormalBuffer );
1162 | gl.vertexAttribPointer( shaderProgram.vertexNormalAttribute, pointLightSphereVertexNormalBuffer.itemSize, gl.FLOAT, false, 0, 0 );
1163 |
1164 | gl.bindBuffer( gl.ARRAY_BUFFER, pointLightSphereVertexColorBuffer );
1165 | gl.vertexAttribPointer( shaderProgram.vertexColorAttribute, pointLightSphereVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0 );
1166 |
1167 | setMatrixUniforms( );
1168 |
1169 | gl.drawArrays( gl.TRIANGLES, 0, pointLightSphereVertexPositionBuffer.numItems );
1170 |
1171 | mvPopMatrix( );
1172 |
1173 | use_lighting = 1;
1174 |
1175 | }
1176 |
1177 | // Move down the negative z-axis by 25 units.
1178 |
1179 | mat4.translate( mvMatrix, mvMatrix, [ 0.0, 0.0, -25.0 ] );
1180 |
1181 | // Save the model view matrix state.
1182 |
1183 | mvPushMatrix( );
1184 |
1185 | // Use lighting if enabled.
1186 |
1187 | gl.uniform1i( shaderProgram.useLightingUniform, Number(use_lighting) );
1188 |
1189 | // If normal map is enabled.
1190 |
1191 | gl.uniform1i( shaderProgram.normalMapEnabled, normal_map );
1192 |
1193 | // Second isosurface.
1194 |
1195 | // Scale up the surface in all dimensions.
1196 |
1197 | mat4.scale( mvMatrix, mvMatrix, [ 5.0, 5.0, 5.0 ] );
1198 |
1199 | // Rotate around the y-axis.
1200 |
1201 | mat4.rotate( mvMatrix, mvMatrix, -rotation_radians, [ 0, 1, 0 ] );
1202 |
1203 | gl.bindBuffer( gl.ARRAY_BUFFER, isosurface1VertexPositionBuffer );
1204 | gl.vertexAttribPointer( shaderProgram.vertexPositionAttribute, isosurface1VertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0 );
1205 |
1206 | gl.bindBuffer( gl.ARRAY_BUFFER, isosurface1VertexNormalBuffer );
1207 | gl.vertexAttribPointer( shaderProgram.vertexNormalAttribute, isosurface1VertexNormalBuffer.itemSize, gl.FLOAT, false, 0, 0 );
1208 |
1209 | gl.bindBuffer( gl.ARRAY_BUFFER, isosurface1VertexColorBuffer );
1210 | gl.vertexAttribPointer( shaderProgram.vertexColorAttribute, isosurface1VertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0 );
1211 |
1212 | setMatrixUniforms( );
1213 |
1214 | if ( Number(use_wireframe) === 0 )
1215 | {
1216 |
1217 | gl.drawArrays( gl.TRIANGLES, 0, isosurface1VertexPositionBuffer.numItems );
1218 |
1219 | }
1220 | else
1221 | {
1222 |
1223 | gl.drawArrays( gl.LINES, 0, isosurface1VertexPositionBuffer.numItems );
1224 |
1225 | }
1226 |
1227 | // Restore the model view matrix state.
1228 |
1229 | mvPopMatrix( );
1230 |
1231 | // Enable alpha blending.
1232 |
1233 | gl.blendFunc( gl.ONE, gl.ONE_MINUS_SRC_ALPHA );
1234 |
1235 | gl.enable( gl.BLEND );
1236 |
1237 | alpha_blending_enabled = 1;
1238 |
1239 | gl.uniform1i( shaderProgram.alphaBlendingEnabled, alpha_blending_enabled );
1240 |
1241 | // Save the current model view matrix for later use.
1242 |
1243 | mvPushMatrix( );
1244 |
1245 | // First isosurface.
1246 |
1247 | mat4.scale( mvMatrix, mvMatrix, [ 11.0, 11.0, 11.0 ] );
1248 |
1249 | // Rotate the model view matrix thereby rotating the isosurface.
1250 |
1251 | mat4.rotate( mvMatrix, mvMatrix, rotation_radians, [ 1, 1, 0 ] );
1252 |
1253 | // Pass to the vertex shader the isosurface data.
1254 |
1255 | gl.bindBuffer( gl.ARRAY_BUFFER, isosurfaceVertexPositionBuffer );
1256 | gl.vertexAttribPointer( shaderProgram.vertexPositionAttribute, isosurfaceVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0 );
1257 |
1258 | gl.bindBuffer( gl.ARRAY_BUFFER, isosurfaceVertexNormalBuffer );
1259 | gl.vertexAttribPointer( shaderProgram.vertexNormalAttribute, isosurfaceVertexNormalBuffer.itemSize, gl.FLOAT, false, 0, 0 );
1260 |
1261 | gl.bindBuffer( gl.ARRAY_BUFFER, isosurfaceVertexColorBuffer );
1262 | gl.vertexAttribPointer( shaderProgram.vertexColorAttribute, isosurfaceVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0 );
1263 |
1264 | setMatrixUniforms( );
1265 |
1266 | // Render the isosurface to the screen.
1267 |
1268 | if ( Number(use_wireframe) === 0 )
1269 | {
1270 |
1271 | gl.drawArrays( gl.TRIANGLES, 0, isosurfaceVertexPositionBuffer.numItems );
1272 |
1273 | }
1274 | else
1275 | {
1276 |
1277 | gl.drawArrays( gl.LINES, 0, isosurfaceVertexPositionBuffer.numItems );
1278 |
1279 | }
1280 |
1281 | // Get back the old model view matrix.
1282 |
1283 | mvPopMatrix( );
1284 |
1285 | }
1286 |
1287 | function resize_contents( )
1288 | {
1289 |
1290 | // The browser window has been re-sized so re-size the render window and onscreen elements.
1291 |
1292 | var logo_image = document.getElementById( "logo" );
1293 | logo_image_height = logo_image.clientHeight;
1294 | logo_image_width = logo_image.clientWidth;
1295 |
1296 | var logo_box = document.getElementById( "logo_box" );
1297 | logo_box.style.top = window.innerHeight - logo_image_height - 10 + "px";
1298 | logo_box.style.left = window.innerWidth - logo_image_width - 10 + "px";
1299 |
1300 | var canvas = document.getElementById( "webgl_canvas" );
1301 | canvas.width = window.innerWidth;
1302 | canvas.height = window.innerHeight;
1303 |
1304 | gl.viewportWidth = canvas.width;
1305 | gl.viewportHeight = canvas.height;
1306 |
1307 | }
1308 |
1309 | function webGLStart( )
1310 | {
1311 |
1312 | // Create and add the canvas that will be "painted" on or rather rendered to by WebGL.
1313 |
1314 | var canvas = document.createElement( "canvas" );
1315 | canvas.id = "webgl_canvas";
1316 | canvas.width = window.innerWidth;
1317 | canvas.height = window.innerHeight;
1318 | document.body.appendChild( canvas );
1319 |
1320 | // Vertex shader GLSL code.
1321 |
1322 | var vertex_shader = document.createElement( "script" );
1323 | vertex_shader.id = "shader-vs";
1324 | vertex_shader.type = "x-shader/x-vertex";
1325 | vertex_shader.innerHTML = "precision mediump float;";
1326 | vertex_shader.innerHTML += "attribute vec3 aVertexPosition;";
1327 | vertex_shader.innerHTML += "attribute vec3 aVertexNormal;";
1328 | vertex_shader.innerHTML += "attribute vec4 aVertexColor;";
1329 | vertex_shader.innerHTML += "uniform mat4 uMVMatrix;";
1330 | vertex_shader.innerHTML += "uniform mat4 uPMatrix;";
1331 | vertex_shader.innerHTML += "uniform mat3 uNMatrix;";
1332 | vertex_shader.innerHTML += "varying vec4 vPosition;";
1333 | vertex_shader.innerHTML += "varying vec4 vDiffuseColor;";
1334 | vertex_shader.innerHTML += "varying vec3 vTransformedNormal;";
1335 | vertex_shader.innerHTML += "void main( void ) {";
1336 | vertex_shader.innerHTML += " vDiffuseColor = aVertexColor;";
1337 | vertex_shader.innerHTML += " vTransformedNormal = uNMatrix * aVertexNormal;";
1338 | vertex_shader.innerHTML += " vPosition = uMVMatrix * vec4( aVertexPosition, 1.0 );";
1339 | vertex_shader.innerHTML += " gl_Position = uPMatrix * vPosition;";
1340 | vertex_shader.innerHTML += "}";
1341 | document.body.appendChild( vertex_shader );
1342 |
1343 | // Fragment shader GLSL code.
1344 |
1345 | var fragment_shader = document.createElement( "script" );
1346 | fragment_shader.id = "shader-fs";
1347 | fragment_shader.type = "x-shader/x-fragment";
1348 | fragment_shader.innerHTML = "precision mediump float;";
1349 | fragment_shader.innerHTML += "uniform mat4 uPMatrix;";
1350 | fragment_shader.innerHTML += "uniform bool uUseLighting;";
1351 | fragment_shader.innerHTML += "uniform bool uAlphaBlendingEnabled;";
1352 | fragment_shader.innerHTML += "uniform bool uShowDepth;";
1353 | fragment_shader.innerHTML += "uniform bool uShowNormals;";
1354 | fragment_shader.innerHTML += "uniform bool uShowPosition;";
1355 | fragment_shader.innerHTML += "uniform bool uPerspectiveProjection;";
1356 | fragment_shader.innerHTML += "uniform bool uNormalMap;";
1357 | fragment_shader.innerHTML += "uniform vec3 uAmbientColor;";
1358 | fragment_shader.innerHTML += "uniform vec3 uPointLightingLocation;";
1359 | fragment_shader.innerHTML += "uniform vec3 uPointLightingColor;";
1360 | fragment_shader.innerHTML += "uniform vec3 uPointLightingLocation1;";
1361 | fragment_shader.innerHTML += "uniform vec3 uPointLightingColor1;";
1362 | fragment_shader.innerHTML += "varying vec4 vPosition;";
1363 | fragment_shader.innerHTML += "varying vec3 vTransformedNormal;";
1364 | fragment_shader.innerHTML += "varying vec4 vDiffuseColor;";
1365 | fragment_shader.innerHTML += "void main( void ) {";
1366 | fragment_shader.innerHTML += " vec3 uAmbientColor = pow(uAmbientColor, vec3(2.2));";
1367 | fragment_shader.innerHTML += " vec4 vDiffuseColor = vDiffuseColor;";
1368 | fragment_shader.innerHTML += " vDiffuseColor.rgb = pow(vDiffuseColor.rgb, vec3(2.2));";
1369 | fragment_shader.innerHTML += " vec3 uPointLightingColor = pow(uPointLightingColor, vec3(2.2));";
1370 | fragment_shader.innerHTML += " vec3 uPointLightingColor1 = pow(uPointLightingColor1, vec3(2.2));";
1371 | fragment_shader.innerHTML += " vec4 fog_color = vec4( " + base_color[ 0 ] + ", " + base_color[ 1 ] + ", " + base_color[ 2 ] + ", 1.0 );";
1372 | fragment_shader.innerHTML += " fog_color.rgb = pow(fog_color.rgb, vec3(2.2));";
1373 | fragment_shader.innerHTML += " vec3 ambient = vDiffuseColor.rgb * uAmbientColor;";
1374 | fragment_shader.innerHTML += " vec3 color = ambient;";
1375 | fragment_shader.innerHTML += " if ( uUseLighting ) {";
1376 | fragment_shader.innerHTML += " vec3 light_direction = normalize( uPointLightingLocation - vPosition.xyz );";
1377 | fragment_shader.innerHTML += " vec3 light_direction1 = normalize( uPointLightingLocation1 - vPosition.xyz );";
1378 | fragment_shader.innerHTML += " vec3 eye_direction = -normalize( vPosition.xyz );";
1379 | fragment_shader.innerHTML += " vec3 half_vector = normalize(light_direction + eye_direction);";
1380 | fragment_shader.innerHTML += " vec3 half_vector1 = normalize(light_direction1 + eye_direction);";
1381 | fragment_shader.innerHTML += " vec3 surface_normal;";
1382 | fragment_shader.innerHTML += " if ( gl_FrontFacing ) {";
1383 | fragment_shader.innerHTML += " surface_normal = normalize( vTransformedNormal );";
1384 | fragment_shader.innerHTML += " }";
1385 | fragment_shader.innerHTML += " else {";
1386 | fragment_shader.innerHTML += " surface_normal = -normalize( vTransformedNormal );";
1387 | fragment_shader.innerHTML += " }";
1388 | fragment_shader.innerHTML += " if ( uNormalMap ) {";
1389 | fragment_shader.innerHTML += " surface_normal = normalize( surface_normal - ( sin( dot( vDiffuseColor.rgb, vec3( 12.9898, 78.233, 1.0 ) ) ) ) );";
1390 | fragment_shader.innerHTML += " }";
1391 | fragment_shader.innerHTML += " vec3 diffuse = vDiffuseColor.rgb * uPointLightingColor * max( dot( surface_normal, light_direction ), 0.0 );";
1392 | fragment_shader.innerHTML += " vec3 diffuse1 = vDiffuseColor.rgb * uPointLightingColor1 * max( dot( surface_normal, light_direction1 ), 0.0 );";
1393 | fragment_shader.innerHTML += " vec3 specular = uPointLightingColor * pow( max( dot( half_vector, surface_normal ), 0.0 ), 100.0 );";
1394 | fragment_shader.innerHTML += " vec3 specular1 = uPointLightingColor1 * pow( max( dot( half_vector1, surface_normal ), 0.0 ), 100.0 );";
1395 | fragment_shader.innerHTML += " float light_outer_radius = 20.0;";
1396 | fragment_shader.innerHTML += " float light_inner_radius = 0.0;";
1397 | fragment_shader.innerHTML += " float light_outer_radius1 = 10.0;";
1398 | fragment_shader.innerHTML += " float light_inner_radius1 = 0.0;";
1399 | fragment_shader.innerHTML += " float light_distance = length( vPosition.xyz - uPointLightingLocation );";
1400 | fragment_shader.innerHTML += " float light_distance1 = length( vPosition.xyz - uPointLightingLocation1 );";
1401 | fragment_shader.innerHTML += " float attenuation = 1.0 - smoothstep( light_inner_radius, light_outer_radius, light_distance );";
1402 | fragment_shader.innerHTML += " float attenuation1 = 1.0 - smoothstep( light_inner_radius1, light_outer_radius1, light_distance1 );";
1403 | fragment_shader.innerHTML += " diffuse = attenuation * diffuse;";
1404 | fragment_shader.innerHTML += " diffuse1 = attenuation1 * diffuse1;";
1405 | fragment_shader.innerHTML += " specular = attenuation * specular;";
1406 | fragment_shader.innerHTML += " specular1 = attenuation1 * specular1;";
1407 | fragment_shader.innerHTML += " color = ambient + diffuse + diffuse1 + specular + specular1;";
1408 | fragment_shader.innerHTML += " }";
1409 | fragment_shader.innerHTML += " vec4 final_color;";
1410 | fragment_shader.innerHTML += " if ( uAlphaBlendingEnabled ) {";
1411 | fragment_shader.innerHTML += " final_color = vec4( color, vDiffuseColor.a );";
1412 | fragment_shader.innerHTML += " }";
1413 | fragment_shader.innerHTML += " else {";
1414 | fragment_shader.innerHTML += " final_color = vec4( color, 1.0 );";
1415 | fragment_shader.innerHTML += " }";
1416 | fragment_shader.innerHTML += " float far = 50.0;";
1417 | fragment_shader.innerHTML += " float fog_coord;";
1418 | fragment_shader.innerHTML += " if ( uPerspectiveProjection ) {";
1419 | fragment_shader.innerHTML += " fog_coord = ( gl_FragCoord.z / gl_FragCoord.w ) / far;";
1420 | fragment_shader.innerHTML += " }";
1421 | fragment_shader.innerHTML += " else {";
1422 | fragment_shader.innerHTML += " fog_coord = ( gl_FragCoord.z / gl_FragCoord.w );";
1423 | fragment_shader.innerHTML += " }";
1424 | fragment_shader.innerHTML += " float fog_density = 1.5;";
1425 | fragment_shader.innerHTML += " float fog = fog_coord * fog_density;";
1426 | fragment_shader.innerHTML += " float fog_factor = clamp( 1.0 - fog, 0.0, 1.0 );";
1427 | fragment_shader.innerHTML += " gl_FragColor = mix( fog_color, final_color, vec4( fog_factor, fog_factor, fog_factor, fog_factor ) );";
1428 | fragment_shader.innerHTML += " gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(1.0 / 2.2));";
1429 | fragment_shader.innerHTML += " if ( uShowDepth ) {";
1430 | fragment_shader.innerHTML += " gl_FragColor = mix( vec4( 1.0 ), vec4( vec3( 0.0 ), 1.0 ), smoothstep( 0.1, 1.0, fog_coord ) );";
1431 | fragment_shader.innerHTML += " }";
1432 | fragment_shader.innerHTML += " if ( uShowNormals ) {";
1433 | fragment_shader.innerHTML += " vec3 nTN = normalize( vTransformedNormal );";
1434 | fragment_shader.innerHTML += " gl_FragColor = vec4( nTN.r, nTN.g, nTN.b, 1.0 );";
1435 | fragment_shader.innerHTML += " }";
1436 | fragment_shader.innerHTML += " if ( uShowPosition ) {";
1437 | fragment_shader.innerHTML += " vec3 nP = normalize( vPosition.xyz );";
1438 | fragment_shader.innerHTML += " gl_FragColor = vec4( nP.r, nP.g, nP.b, 1.0 );";
1439 | fragment_shader.innerHTML += " }";
1440 | fragment_shader.innerHTML += "}";
1441 | document.body.appendChild( fragment_shader );
1442 |
1443 | initGL( canvas ); // Initialize WebGL.
1444 | initShaders( ); // Initialize the shaders.
1445 | initBuffers( ); // Initialize the 3D shapes.
1446 | initHUD( ); // Initialize the onscreen elements.
1447 |
1448 | gl.clearColor( base_color[ 0 ], base_color[ 1 ], base_color[ 2 ], 1.0 ); // Set the WebGL background color.
1449 | gl.enable( gl.DEPTH_TEST ); // Enable the depth buffer.
1450 |
1451 | window.requestAnimationFrame( drawScene ); // Begin rendering animation.
1452 |
1453 | }
1454 |
1455 | /* Taken from http://paulbourke.net/geometry/polygonise/ */
1456 |
1457 | var marching_cubes_edge_table = [
1458 |
1459 | 0x0 , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
1460 | 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
1461 | 0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,
1462 | 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
1463 | 0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c,
1464 | 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
1465 | 0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac,
1466 | 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
1467 | 0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c,
1468 | 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
1469 | 0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc,
1470 | 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
1471 | 0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c,
1472 | 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
1473 | 0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc ,
1474 | 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
1475 | 0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,
1476 | 0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
1477 | 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,
1478 | 0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
1479 | 0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,
1480 | 0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
1481 | 0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,
1482 | 0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460,
1483 | 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
1484 | 0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0,
1485 | 0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,
1486 | 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230,
1487 | 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,
1488 | 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190,
1489 | 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,
1490 | 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0
1491 |
1492 | ];
1493 |
1494 | var marching_cubes_triangle_table = [
1495 |
1496 | [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1497 | [ 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1498 | [ 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1499 | [ 1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1500 | [ 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1501 | [ 0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1502 | [ 9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1503 | [ 2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1 ],
1504 | [ 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1505 | [ 0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1506 | [ 1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1507 | [ 1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1 ],
1508 | [ 3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1509 | [ 0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1 ],
1510 | [ 3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1 ],
1511 | [ 9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1512 | [ 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1513 | [ 4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1514 | [ 0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1515 | [ 4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1 ],
1516 | [ 1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1517 | [ 3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1 ],
1518 | [ 9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 ],
1519 | [ 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1 ],
1520 | [ 8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1521 | [ 11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1 ],
1522 | [ 9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 ],
1523 | [ 4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1 ],
1524 | [ 3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1 ],
1525 | [ 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1 ],
1526 | [ 4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1 ],
1527 | [ 4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1 ],
1528 | [ 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1529 | [ 9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1530 | [ 0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1531 | [ 8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1 ],
1532 | [ 1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1533 | [ 3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 ],
1534 | [ 5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1 ],
1535 | [ 2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1 ],
1536 | [ 9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1537 | [ 0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 ],
1538 | [ 0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 ],
1539 | [ 2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1 ],
1540 | [ 10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1 ],
1541 | [ 4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1 ],
1542 | [ 5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1 ],
1543 | [ 5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1 ],
1544 | [ 9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1545 | [ 9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1 ],
1546 | [ 0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1 ],
1547 | [ 1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1548 | [ 9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1 ],
1549 | [ 10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1 ],
1550 | [ 8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1 ],
1551 | [ 2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1 ],
1552 | [ 7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1 ],
1553 | [ 9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1 ],
1554 | [ 2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1 ],
1555 | [ 11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1 ],
1556 | [ 9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1 ],
1557 | [ 5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1 ],
1558 | [ 11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1 ],
1559 | [ 11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1560 | [ 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1561 | [ 0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1562 | [ 9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1563 | [ 1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 ],
1564 | [ 1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1565 | [ 1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1 ],
1566 | [ 9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1 ],
1567 | [ 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1 ],
1568 | [ 2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1569 | [ 11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 ],
1570 | [ 0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 ],
1571 | [ 5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1 ],
1572 | [ 6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1 ],
1573 | [ 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1 ],
1574 | [ 3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1 ],
1575 | [ 6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1 ],
1576 | [ 5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1577 | [ 4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1 ],
1578 | [ 1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 ],
1579 | [ 10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1 ],
1580 | [ 6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1 ],
1581 | [ 1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1 ],
1582 | [ 8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1 ],
1583 | [ 7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1 ],
1584 | [ 3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 ],
1585 | [ 5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1 ],
1586 | [ 0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1 ],
1587 | [ 9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1 ],
1588 | [ 8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1 ],
1589 | [ 5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1 ],
1590 | [ 0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1 ],
1591 | [ 6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1 ],
1592 | [ 10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1593 | [ 4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1 ],
1594 | [ 10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1 ],
1595 | [ 8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1 ],
1596 | [ 1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1 ],
1597 | [ 3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1 ],
1598 | [ 0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1599 | [ 8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1 ],
1600 | [ 10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1 ],
1601 | [ 0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1 ],
1602 | [ 3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1 ],
1603 | [ 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1 ],
1604 | [ 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1 ],
1605 | [ 8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1 ],
1606 | [ 3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1 ],
1607 | [ 6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1608 | [ 7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1 ],
1609 | [ 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1 ],
1610 | [ 10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1 ],
1611 | [ 10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1 ],
1612 | [ 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1 ],
1613 | [ 2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1 ],
1614 | [ 7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1 ],
1615 | [ 7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1616 | [ 2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1 ],
1617 | [ 2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1 ],
1618 | [ 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1 ],
1619 | [ 11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1 ],
1620 | [ 8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1 ],
1621 | [ 0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1622 | [ 7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1 ],
1623 | [ 7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1624 | [ 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1625 | [ 3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1626 | [ 0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1627 | [ 8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 ],
1628 | [ 10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1629 | [ 1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 ],
1630 | [ 2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 ],
1631 | [ 6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1 ],
1632 | [ 7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1633 | [ 7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1 ],
1634 | [ 2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1 ],
1635 | [ 1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1 ],
1636 | [ 10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1 ],
1637 | [ 10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1 ],
1638 | [ 0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1 ],
1639 | [ 7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1 ],
1640 | [ 6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1641 | [ 3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1 ],
1642 | [ 8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1 ],
1643 | [ 9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1 ],
1644 | [ 6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1 ],
1645 | [ 1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1 ],
1646 | [ 4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1 ],
1647 | [ 10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1 ],
1648 | [ 8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1 ],
1649 | [ 0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1650 | [ 1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1 ],
1651 | [ 1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1 ],
1652 | [ 8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1 ],
1653 | [ 10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1 ],
1654 | [ 4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1 ],
1655 | [ 10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1656 | [ 4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1657 | [ 0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 ],
1658 | [ 5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 ],
1659 | [ 11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1 ],
1660 | [ 9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 ],
1661 | [ 6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1 ],
1662 | [ 7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1 ],
1663 | [ 3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1 ],
1664 | [ 7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1 ],
1665 | [ 9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1 ],
1666 | [ 3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1 ],
1667 | [ 6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1 ],
1668 | [ 9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1 ],
1669 | [ 1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1 ],
1670 | [ 4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1 ],
1671 | [ 7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1 ],
1672 | [ 6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1 ],
1673 | [ 3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1 ],
1674 | [ 0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1 ],
1675 | [ 6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1 ],
1676 | [ 1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1 ],
1677 | [ 0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1 ],
1678 | [ 11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1 ],
1679 | [ 6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1 ],
1680 | [ 5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1 ],
1681 | [ 9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1 ],
1682 | [ 1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1 ],
1683 | [ 1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1684 | [ 1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1 ],
1685 | [ 10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1 ],
1686 | [ 0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1687 | [ 10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1688 | [ 11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1689 | [ 11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1 ],
1690 | [ 5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1 ],
1691 | [ 10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1 ],
1692 | [ 11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1 ],
1693 | [ 0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1 ],
1694 | [ 9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1 ],
1695 | [ 7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1 ],
1696 | [ 2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1 ],
1697 | [ 8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1 ],
1698 | [ 9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1 ],
1699 | [ 9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1 ],
1700 | [ 1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1701 | [ 0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1 ],
1702 | [ 9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1 ],
1703 | [ 9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1704 | [ 5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1 ],
1705 | [ 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1 ],
1706 | [ 0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1 ],
1707 | [ 10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1 ],
1708 | [ 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1 ],
1709 | [ 0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1 ],
1710 | [ 0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1 ],
1711 | [ 9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1712 | [ 2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1 ],
1713 | [ 5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1 ],
1714 | [ 3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1 ],
1715 | [ 5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1 ],
1716 | [ 8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1 ],
1717 | [ 0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1718 | [ 8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1 ],
1719 | [ 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1720 | [ 4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1 ],
1721 | [ 0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1 ],
1722 | [ 1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1 ],
1723 | [ 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1 ],
1724 | [ 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1 ],
1725 | [ 9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1 ],
1726 | [ 11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1 ],
1727 | [ 11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1 ],
1728 | [ 2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1 ],
1729 | [ 9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1 ],
1730 | [ 3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1 ],
1731 | [ 1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1732 | [ 4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1 ],
1733 | [ 4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1 ],
1734 | [ 4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1735 | [ 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1736 | [ 9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1737 | [ 3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1 ],
1738 | [ 0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1 ],
1739 | [ 3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1740 | [ 1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1 ],
1741 | [ 3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1 ],
1742 | [ 0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1743 | [ 3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1744 | [ 2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1 ],
1745 | [ 9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1746 | [ 2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1 ],
1747 | [ 1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1748 | [ 1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1749 | [ 0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1750 | [ 0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1751 | [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ]
1752 |
1753 | ];
1754 |
--------------------------------------------------------------------------------
/source/assets/scripts/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | (C) 2014 David Lettier
3 | lettier.com
4 | */
5 |
6 | // The WebGL context.
7 |
8 | var gl;
9 |
10 | // The compiled and linked vertex and fragment shaders.
11 |
12 | var shaderProgram;
13 |
14 | // A stack for preserving matrix transformation states.
15 |
16 | var mvMatrixStack = [ ];
17 |
18 | // Perspective or orthographic projection?
19 |
20 | var perspective_projection = true;
21 |
22 | // Model view and projection matrices.
23 |
24 | var mvMatrix = mat4.create( );
25 | var pMatrix = mat4.create( );
26 |
27 | // Isosurface data structures for holding the vertices, vertex normals, and vertex colors.
28 |
29 | var isosurfaceVertexPositionBuffer;
30 | var isosurfaceVertexNormalBuffer;
31 | var isosurfaceVertexColorBuffer;
32 |
33 | var isosurface1VertexPositionBuffer;
34 | var isosurface1VertexNormalBuffer;
35 | var isosurface1VertexColorBuffer;
36 |
37 | var pointLightSphereVertexPositionBuffer;
38 | var pointLightSphereVertexNormalBuffer;
39 | var pointLightSphereVertexColorBuffer;
40 |
41 | // Base color used for the ambient, fog, and clear-to colors.
42 |
43 | var base_color = [ 0.123, 0.154, 0.182 ];
44 |
45 | // Lighting power.
46 |
47 | var lighting_power = 2;
48 |
49 | // Used for time based animation.
50 |
51 | var time_last = 0;
52 |
53 | // Used to rotate the isosurface.
54 |
55 | var rotation_radians = 0.0;
56 | var rotation_radians_step = 0.3;
57 |
58 | // Use lighting?
59 |
60 | var use_lighting = 1;
61 |
62 | // Use wireframe rendering?
63 |
64 | var use_wireframe = 0;
65 |
66 | // Render different buffers.
67 |
68 | var show_depth = 0;
69 | var show_normals = 0;
70 | var show_position = 0;
71 |
72 | // Alpha blending enabled?
73 |
74 | var alpha_blending_enabled = 0;
75 |
76 | // Normal map?
77 |
78 | var normal_map = 1;
79 |
80 | // Number of times initBuffers has been called.
81 |
82 | var init_buffers_called = 0;
83 |
84 | // Used to orbit the point lights.
85 |
86 | var point_light_theta = 1.57;
87 | var point_light_phi = 1.57;
88 | var point_light_theta_step = 0.39;
89 | var point_light_phi_step = 0.39;
90 |
91 | var point_light_theta1 = 1.57;
92 | var point_light_phi1 = 1.57;
93 | var point_light_theta_step1 = 0.3;
94 | var point_light_phi_step1 = 0.3;
95 |
96 | // Performs the draw loop iteration at roughly 60 frames per second.
97 |
98 | window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
99 |
100 | // On-load event callback.
101 |
102 | window.onload = function ( ) {
103 | var gui = new dat.GUI();
104 |
105 | gui.add(this, "lighting_power", 0, 5);
106 | gui.add(this, "perspective_projection", { On: true, Off: false });
107 | gui.add(this, "use_lighting", { On: 1, Off: 0 });
108 | gui.add(this, "use_wireframe", { On: 1, Off: 0 });
109 | gui.add(this, "show_depth", { Yes: 1, No: 0 });
110 | gui.add(this, "show_normals", { Yes: 1, No: 0 });
111 | gui.add(this, "show_position", { Yes: 1, No: 0 });
112 | gui.add(this, "normal_map", { On: 1, Off: 0 });
113 |
114 | webGLStart( );
115 | };
116 |
117 | // Browser window re-size event callback.
118 |
119 | window.onresize = function ( ) { resize_contents( ); };
120 |
121 | // Initializes the WebGL context.
122 |
123 | function initGL( canvas )
124 | {
125 |
126 | try
127 | {
128 |
129 | gl = canvas.getContext( "webgl" ) || canvas.getContext( "experimental-webgl" );
130 |
131 | gl.viewportWidth = canvas.width;
132 | gl.viewportHeight = canvas.height;
133 |
134 | }
135 | catch ( error )
136 | {
137 |
138 | // Browser cannot initialize a WebGL context.
139 |
140 | window.location.assign( "http://get.webgl.org/" );
141 |
142 | }
143 |
144 | if ( !gl )
145 | {
146 |
147 | // Browser cannot initialize a WebGL context.
148 |
149 | window.location.assign( "http://get.webgl.org/" );
150 |
151 | }
152 |
153 | }
154 |
155 | // Function to retrieve the shader strings thereby compiling them into shader programs run by the GPU.
156 |
157 | function getShader( gl, id )
158 | {
159 | var shaderScript = document.getElementById( id );
160 |
161 | if ( !shaderScript )
162 | {
163 |
164 | console.error( "No shader scripts present." );
165 |
166 | return null;
167 |
168 | }
169 |
170 | var str = "";
171 |
172 | var k = shaderScript.firstChild;
173 |
174 | while ( k )
175 | {
176 |
177 | if ( k.nodeType == 3 )
178 | {
179 |
180 | str += k.textContent;
181 |
182 | }
183 |
184 | k = k.nextSibling;
185 |
186 | }
187 |
188 | var shader;
189 |
190 | if ( shaderScript.type == "x-shader/x-fragment" )
191 | {
192 |
193 | shader = gl.createShader( gl.FRAGMENT_SHADER );
194 |
195 | }
196 | else if ( shaderScript.type == "x-shader/x-vertex" )
197 | {
198 |
199 | shader = gl.createShader( gl.VERTEX_SHADER );
200 |
201 | }
202 | else
203 | {
204 |
205 | console.error( "No fragment/vertex shaders found." );
206 |
207 | return null;
208 |
209 | }
210 |
211 | gl.shaderSource( shader, str );
212 |
213 | gl.compileShader( shader );
214 |
215 | if ( !gl.getShaderParameter( shader, gl.COMPILE_STATUS ) )
216 | {
217 |
218 | console.error( gl.getShaderInfoLog( shader ) );
219 |
220 | return null;
221 |
222 | }
223 |
224 | return shader;
225 |
226 | }
227 |
228 | // Initialize the vertex and fragment shaders.
229 |
230 | function initShaders( )
231 | {
232 |
233 | var fragmentShader = getShader( gl, "shader-fs" );
234 | var vertexShader = getShader( gl, "shader-vs" );
235 |
236 | shaderProgram = gl.createProgram( );
237 |
238 | gl.attachShader( shaderProgram, vertexShader );
239 | gl.attachShader( shaderProgram, fragmentShader );
240 | gl.linkProgram( shaderProgram );
241 |
242 | if ( !gl.getProgramParameter( shaderProgram, gl.LINK_STATUS ) )
243 | {
244 |
245 | console.error( "Could not initialize shaders." );
246 |
247 | }
248 |
249 | gl.useProgram( shaderProgram );
250 |
251 | // Acquire handles to shader program variables in order to pass data to the shaders.
252 |
253 | shaderProgram.vertexPositionAttribute = gl.getAttribLocation( shaderProgram, "aVertexPosition" );
254 | gl.enableVertexAttribArray( shaderProgram.vertexPositionAttribute );
255 |
256 | shaderProgram.vertexColorAttribute = gl.getAttribLocation( shaderProgram, "aVertexColor" );
257 | gl.enableVertexAttribArray( shaderProgram.vertexColorAttribute );
258 |
259 | shaderProgram.vertexNormalAttribute = gl.getAttribLocation( shaderProgram, "aVertexNormal" );
260 | gl.enableVertexAttribArray( shaderProgram.vertexNormalAttribute );
261 |
262 | shaderProgram.pMatrixUniform = gl.getUniformLocation( shaderProgram, "uPMatrix" );
263 | shaderProgram.mvMatrixUniform = gl.getUniformLocation( shaderProgram, "uMVMatrix" );
264 | shaderProgram.nMatrixUniform = gl.getUniformLocation( shaderProgram, "uNMatrix" );
265 |
266 | shaderProgram.useLightingUniform = gl.getUniformLocation( shaderProgram, "uUseLighting" );
267 |
268 | shaderProgram.alphaBlendingEnabled = gl.getUniformLocation( shaderProgram, "uAlphaBlendingEnabled" );
269 |
270 | shaderProgram.normalMapEnabled = gl.getUniformLocation( shaderProgram, "uNormalMap" );
271 |
272 | shaderProgram.perspectiveProjection = gl.getUniformLocation( shaderProgram, "uPerspectiveProjection" );
273 |
274 | shaderProgram.showDepth = gl.getUniformLocation( shaderProgram, "uShowDepth" );
275 | shaderProgram.showNormals = gl.getUniformLocation( shaderProgram, "uShowNormals" );
276 | shaderProgram.showPosition = gl.getUniformLocation( shaderProgram, "uShowPosition" );
277 |
278 | shaderProgram.ambientColorUniform = gl.getUniformLocation( shaderProgram, "uAmbientColor" );
279 |
280 | shaderProgram.pointLightingLocationUniform = gl.getUniformLocation( shaderProgram, "uPointLightingLocation" );
281 | shaderProgram.pointLightingColorUniform = gl.getUniformLocation( shaderProgram, "uPointLightingColor" );
282 |
283 | shaderProgram.pointLightingLocationUniform1 = gl.getUniformLocation( shaderProgram, "uPointLightingLocation1" );
284 | shaderProgram.pointLightingColorUniform1 = gl.getUniformLocation( shaderProgram, "uPointLightingColor1" );
285 |
286 | }
287 |
288 | // Initialize all of the vertex, vertex normal, and vertex color buffers.
289 |
290 | function initBuffers( )
291 | {
292 |
293 | // Generates one triangle complete with vertex normals and vertex colors.
294 |
295 | function triangle( p1, p2, p3, isosurface_function, resolution, invert_normals )
296 | {
297 |
298 | // Push the vertices to this triangle face.
299 | // Pushing point 3, then 2, and then 1 so that the front face of the triangle
300 | // points outward from the surface.
301 |
302 | // Push point 1, then 2, and then 3 so that the front front face of the triangle
303 | // points inward from the surface.
304 |
305 | vertices.push( p3[ 0 ] ); vertices.push( p3[ 1 ] ); vertices.push( p3[ 2 ] );
306 | vertices.push( p2[ 0 ] ); vertices.push( p2[ 1 ] ); vertices.push( p2[ 2 ] );
307 | vertices.push( p1[ 0 ] ); vertices.push( p1[ 1 ] ); vertices.push( p1[ 2 ] );
308 |
309 | // Calculate the isosurface gradient at point 1, 2, and 3 of the triangle.
310 | // These three gradient vectors are the vertex normals of this triangle.
311 | // This will provide a nice smooth appearance when the lighting is calculated.
312 | // These three gradient vectors will also be the vertex colors.
313 |
314 | var invert_normal = 1;
315 |
316 | if ( invert_normals === true ) invert_normal = -1;
317 |
318 | var vertext_color_alpha = 0.2;
319 |
320 | // Point 3.
321 |
322 | vertex_normal_x = 0.5 * ( isosurface_function( p3[ 0 ] + 1, p3[ 1 ], p3[ 2 ] ) - isosurface_function( p3[ 0 ] - 1, p3[ 1 ], p3[ 2 ] ) ) / resolution;
323 | vertex_normal_y = 0.5 * ( isosurface_function( p3[ 0 ], p3[ 1 ] + 1, p3[ 2 ] ) - isosurface_function( p3[ 0 ], p3[ 1 ] - 1, p3[ 2 ] ) ) / resolution;
324 | vertex_normal_z = 0.5 * ( isosurface_function( p3[ 0 ], p3[ 1 ], p3[ 2 ] + 1 ) - isosurface_function( p3[ 0 ], p3[ 1 ], p3[ 2 ] - 1 ) ) / resolution;
325 |
326 | vertex_normal_length = Math.sqrt( ( vertex_normal_x * vertex_normal_x ) + ( vertex_normal_y * vertex_normal_y ) + ( vertex_normal_z * vertex_normal_z ) );
327 |
328 | if ( vertex_normal_length !== 0 )
329 | {
330 |
331 | vertex_normal_x = vertex_normal_x / vertex_normal_length;
332 | vertex_normal_y = vertex_normal_y / vertex_normal_length;
333 | vertex_normal_z = vertex_normal_z / vertex_normal_length;
334 |
335 | }
336 |
337 | vertex_normals.push( invert_normal * vertex_normal_x ); vertex_normals.push( invert_normal * vertex_normal_y ); vertex_normals.push( invert_normal * vertex_normal_z );
338 |
339 | // Push the vertex colors for this triangle face point.
340 |
341 | vertex_colors.push( 1.0 - vertex_normal_x ); vertex_colors.push( 1.0 - vertex_normal_y ); vertex_colors.push( 1.0 - vertex_normal_z ); vertex_colors.push( vertext_color_alpha );
342 |
343 | // Point 2.
344 |
345 | vertex_normal_x = 0.5 * ( isosurface_function( p2[ 0 ] + 1, p2[ 1 ], p2[ 2 ] ) - isosurface_function( p2[ 0 ] - 1, p2[ 1 ], p2[ 2 ] ) ) / resolution;
346 | vertex_normal_y = 0.5 * ( isosurface_function( p2[ 0 ], p2[ 1 ] + 1, p2[ 2 ] ) - isosurface_function( p2[ 0 ], p2[ 1 ] - 1, p2[ 2 ] ) ) / resolution;
347 | vertex_normal_z = 0.5 * ( isosurface_function( p2[ 0 ], p2[ 1 ], p2[ 2 ] + 1 ) - isosurface_function( p2[ 0 ], p2[ 1 ], p2[ 2 ] - 1 ) ) / resolution;
348 |
349 | vertex_normal_length = Math.sqrt( ( vertex_normal_x * vertex_normal_x ) + ( vertex_normal_y * vertex_normal_y ) + ( vertex_normal_z * vertex_normal_z ) );
350 |
351 | if ( vertex_normal_length !== 0 )
352 | {
353 |
354 | vertex_normal_x = vertex_normal_x / vertex_normal_length;
355 | vertex_normal_y = vertex_normal_y / vertex_normal_length;
356 | vertex_normal_z = vertex_normal_z / vertex_normal_length;
357 |
358 | }
359 |
360 | vertex_normals.push( invert_normal * vertex_normal_x ); vertex_normals.push( invert_normal * vertex_normal_y ); vertex_normals.push( invert_normal * vertex_normal_z );
361 |
362 | // Push the vertex colors for this triangle face point.
363 |
364 | vertex_colors.push( 1.0 - vertex_normal_x ); vertex_colors.push( 1.0 - vertex_normal_y ); vertex_colors.push( 1.0 - vertex_normal_z ); vertex_colors.push( vertext_color_alpha );
365 |
366 | // Point 1.
367 |
368 | var vertex_normal_x = 0.5 * ( isosurface_function( p1[ 0 ] + 1, p1[ 1 ], p1[ 2 ] ) - isosurface_function( p1[ 0 ] - 1, p1[ 1 ], p1[ 2 ] ) ) / resolution;
369 | var vertex_normal_y = 0.5 * ( isosurface_function( p1[ 0 ], p1[ 1 ] + 1, p1[ 2 ] ) - isosurface_function( p1[ 0 ], p1[ 1 ] - 1, p1[ 2 ] ) ) / resolution;
370 | var vertex_normal_z = 0.5 * ( isosurface_function( p1[ 0 ], p1[ 1 ], p1[ 2 ] + 1 ) - isosurface_function( p1[ 0 ], p1[ 1 ], p1[ 2 ] - 1 ) ) / resolution;
371 |
372 | // Normalize.
373 |
374 | var vertex_normal_length = Math.sqrt( ( vertex_normal_x * vertex_normal_x ) + ( vertex_normal_y * vertex_normal_y ) + ( vertex_normal_z * vertex_normal_z ) );
375 |
376 | if ( vertex_normal_length !== 0 )
377 | {
378 |
379 | vertex_normal_x = vertex_normal_x / vertex_normal_length;
380 | vertex_normal_y = vertex_normal_y / vertex_normal_length;
381 | vertex_normal_z = vertex_normal_z / vertex_normal_length;
382 |
383 | }
384 |
385 | vertex_normals.push( invert_normal * vertex_normal_x ); vertex_normals.push( invert_normal * vertex_normal_y ); vertex_normals.push( invert_normal * vertex_normal_z );
386 |
387 | // Push the vertex colors for this triangle face point.
388 |
389 | vertex_colors.push( 1.0 - vertex_normal_x ); vertex_colors.push( 1.0 - vertex_normal_y ); vertex_colors.push( 1.0 - vertex_normal_z ); vertex_colors.push( vertext_color_alpha );
390 |
391 | }
392 |
393 | // The marching cubes algorithm.
394 |
395 | function marching_cubes( grid_min, grid_max, resolution, iso_level, isosurface_function, invert_normals )
396 | {
397 |
398 | // Cube grid dimensions.
399 |
400 | var cube_grid_axis_min = grid_min;
401 | var cube_grid_axis_max = grid_max;
402 |
403 | // Generate the cube grid scalar field.
404 |
405 | /*
406 |
407 | j
408 | |
409 | | k
410 | | .
411 | | .
412 | | .
413 | | .
414 | | .
415 | |._________________i
416 |
417 | */
418 |
419 | function Scalar_Point( x, y, z, value )
420 | {
421 |
422 | this.id = x.toFixed( 2 ) + y.toFixed( 2 ) + z.toFixed( 2 );
423 |
424 | this.x = x;
425 | this.y = y;
426 | this.z = z;
427 | this.value = value;
428 |
429 | }
430 |
431 | var scalar_points = { };
432 |
433 | for ( var k = cube_grid_axis_min; k <= ( cube_grid_axis_max + resolution ); k += resolution )
434 | {
435 |
436 | for ( var j = cube_grid_axis_min; j <= ( cube_grid_axis_max + resolution ); j += resolution )
437 | {
438 |
439 | for ( var i = cube_grid_axis_min; i <= ( cube_grid_axis_max + resolution ); i += resolution )
440 | {
441 |
442 | var x = i;
443 | var y = j;
444 | var z = k;
445 |
446 | var value = isosurface_function( x, y, z );
447 |
448 | var scalar_point = new Scalar_Point( x, y, z, value );
449 |
450 | scalar_points[ scalar_point.id ] = scalar_point;
451 |
452 | }
453 |
454 | }
455 |
456 | }
457 |
458 | function edge_intersection_interpolation( cube_va, cube_vb )
459 | {
460 |
461 | if ( Math.abs( iso_level - cube_va.value ) < 0.00001 ) return [ cube_va.x, cube_va.y, cube_va.z ];
462 |
463 | if ( Math.abs( iso_level - cube_vb.value ) < 0.00001 ) return [ cube_vb.x, cube_vb.y, cube_vb.z ];
464 |
465 | if ( Math.abs( cube_va.value - cube_vb.value ) < 0.00001 ) return [ cube_va.x, cube_va.y, cube_va.z ];
466 |
467 | var mean = ( iso_level - cube_va.value ) / ( cube_vb.value - cube_va.value );
468 |
469 | var point = [ ];
470 |
471 | point.push( cube_va.x + mean * ( cube_vb.x - cube_va.x ) );
472 | point.push( cube_va.y + mean * ( cube_vb.y - cube_va.y ) );
473 | point.push( cube_va.z + mean * ( cube_vb.z - cube_va.z ) );
474 |
475 | return point;
476 | }
477 |
478 | for ( var k = cube_grid_axis_min; k < cube_grid_axis_max; k += resolution )
479 | {
480 |
481 | for ( var j = cube_grid_axis_min; j < cube_grid_axis_max; j += resolution )
482 | {
483 |
484 | for ( var i = cube_grid_axis_min; i < cube_grid_axis_max; i += resolution )
485 | {
486 |
487 | // Perform the algorithm on one cube in the grid.
488 |
489 | // The cube's vertices.
490 | // There are eight of them.
491 |
492 | // 4---------5
493 | // /| /|
494 | // / | / |
495 | // 7---------6 |
496 | // | | | |
497 | // | 0------|--1
498 | // | / | /
499 | // |/ |/
500 | // 3---------2
501 |
502 | var cube_v3 = scalar_points[ i.toFixed( 2 ) + j.toFixed( 2 ) + k.toFixed( 2 ) ]; // Lower left front corner.
503 | var cube_v2 = scalar_points[ ( i + resolution ).toFixed( 2 ) + j.toFixed( 2 ) + k.toFixed( 2 ) ]; // Lower right front corner.
504 | var cube_v6 = scalar_points[ ( i + resolution ).toFixed( 2 ) + ( j + resolution ).toFixed( 2 ) + k.toFixed( 2 ) ]; // Upper right front corner.
505 | var cube_v7 = scalar_points[ i.toFixed( 2 ) + ( j + resolution ).toFixed( 2 ) + k.toFixed( 2 ) ]; // Upper left front corner
506 |
507 | var cube_v0 = scalar_points[ i.toFixed( 2 ) + j.toFixed( 2 ) + ( k + resolution ).toFixed( 2 ) ]; // Lower left back corner.
508 | var cube_v1 = scalar_points[ ( i + resolution ).toFixed( 2 ) + j.toFixed( 2 ) + ( k + resolution ).toFixed( 2 ) ]; // Lower right back corner.
509 | var cube_v5 = scalar_points[ ( i + resolution ).toFixed( 2 ) + ( j + resolution ).toFixed( 2 ) + ( k + resolution ).toFixed( 2 ) ]; // Upper right back corner.
510 | var cube_v4 = scalar_points[ i.toFixed( 2 ) + ( j + resolution ).toFixed( 2 ) + ( k + resolution ).toFixed( 2 ) ]; // Upper left back corner.
511 |
512 | var cube_index = 0;
513 |
514 | if ( cube_v0.value < iso_level ) cube_index |= 1;
515 | if ( cube_v1.value < iso_level ) cube_index |= 2;
516 | if ( cube_v2.value < iso_level ) cube_index |= 4;
517 | if ( cube_v3.value < iso_level ) cube_index |= 8;
518 | if ( cube_v4.value < iso_level ) cube_index |= 16;
519 | if ( cube_v5.value < iso_level ) cube_index |= 32;
520 | if ( cube_v6.value < iso_level ) cube_index |= 64;
521 | if ( cube_v7.value < iso_level ) cube_index |= 128;
522 |
523 | // Does the isosurface not intersect any edges of the cube?
524 |
525 | if ( marching_cubes_edge_table[ cube_index ] === 0 ) continue;
526 |
527 | // What edges of the cube does the isosurface intersect?
528 | // For each cube edge intersected, interpolate an intersection vertex between the edge's incident vertices.
529 | // These vertices of intersection will form the triangle(s) that approximate the isosurface.
530 |
531 | // There are 12 edges in a cube.
532 |
533 | // 4----5----5
534 | // 8 /| 6/|
535 | // / |9 / | 10
536 | // 7----7----6 |
537 | // | | | |
538 | // 12 | 0---1--|--1
539 | // | / | /
540 | // |/ 4 11 |/ 2
541 | // 3----3----2
542 | //
543 | // 1={0,1}, 2={1,2}, 3={2,3}, 4={3,0},
544 | // 5={4,5}, 6={5,6}, 7={6,7}, 8={7,4},
545 | // 9={0,4}, 10={5,1}, 11={2,6}, 12={3,7}
546 |
547 | // Base ten slot: 2048 | 1024 | 512 | 256 | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1
548 | // Base two slot: 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
549 | // Edge slot: 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1
550 |
551 | var vertices_of_intersection = [ ];
552 |
553 | // Fill allocate the array.
554 |
555 | for ( var c = 0; c < 12; ++c )
556 | {
557 |
558 | vertices_of_intersection.push( [ 0, 0, 0 ] );
559 |
560 | }
561 |
562 | if ( marching_cubes_edge_table[ cube_index ] & 1 ) // Intersects edge one.
563 | {
564 |
565 | vertices_of_intersection[ 0 ] = edge_intersection_interpolation( cube_v0, cube_v1 );
566 |
567 | }
568 |
569 | if ( marching_cubes_edge_table[ cube_index ] & 2 ) // Intersects edge two.
570 | {
571 |
572 | vertices_of_intersection[ 1 ] = edge_intersection_interpolation( cube_v1, cube_v2 );
573 |
574 | }
575 |
576 | if ( marching_cubes_edge_table[ cube_index ] & 4 ) // Intersects edge three.
577 | {
578 |
579 | vertices_of_intersection[ 2 ] = edge_intersection_interpolation( cube_v2, cube_v3 );
580 |
581 | }
582 |
583 | if ( marching_cubes_edge_table[ cube_index ] & 8 ) // Intersects edge four.
584 | {
585 |
586 | vertices_of_intersection[ 3 ] = edge_intersection_interpolation( cube_v3, cube_v0 );
587 |
588 | }
589 |
590 | if ( marching_cubes_edge_table[ cube_index ] & 16 ) // Intersects edge five.
591 | {
592 |
593 | vertices_of_intersection[ 4 ] = edge_intersection_interpolation( cube_v4, cube_v5 );
594 |
595 | }
596 |
597 | if ( marching_cubes_edge_table[ cube_index ] & 32 ) // Intersects edge six.
598 | {
599 |
600 | vertices_of_intersection[ 5 ] = edge_intersection_interpolation( cube_v5, cube_v6 );
601 |
602 | }
603 |
604 | if ( marching_cubes_edge_table[ cube_index ] & 64 ) // Intersects edge seven.
605 | {
606 |
607 | vertices_of_intersection[ 6 ] = edge_intersection_interpolation( cube_v6, cube_v7 );
608 |
609 | }
610 |
611 | if ( marching_cubes_edge_table[ cube_index ] & 128 ) // Intersects edge eight.
612 | {
613 |
614 | vertices_of_intersection[ 7 ] = edge_intersection_interpolation( cube_v7, cube_v4 );
615 |
616 | }
617 |
618 | if ( marching_cubes_edge_table[ cube_index ] & 256 ) // Intersects edge nine.
619 | {
620 |
621 | vertices_of_intersection[ 8 ] = edge_intersection_interpolation( cube_v0, cube_v4 );
622 |
623 | }
624 |
625 | if ( marching_cubes_edge_table[ cube_index ] & 512 ) // Intersects edge ten.
626 | {
627 |
628 | vertices_of_intersection[ 9 ] = edge_intersection_interpolation( cube_v1, cube_v5 );
629 |
630 | }
631 |
632 | if ( marching_cubes_edge_table[ cube_index ] & 1024 ) // Intersects edge eleven.
633 | {
634 |
635 | vertices_of_intersection[ 10 ] = edge_intersection_interpolation( cube_v2, cube_v6 );
636 |
637 | }
638 |
639 | if ( marching_cubes_edge_table[ cube_index ] & 2048 ) // Intersects edge twelve.
640 | {
641 |
642 | vertices_of_intersection[ 11 ] = edge_intersection_interpolation( cube_v3, cube_v7 );
643 |
644 | }
645 |
646 | // Create the triangles.
647 | // Three vertices make up a triangle per iteration.
648 |
649 | for ( var a = 0; marching_cubes_triangle_table[ cube_index ][ a ] != -1; a = a + 3 )
650 | {
651 |
652 | var v1 = vertices_of_intersection[ marching_cubes_triangle_table[ cube_index ][ a ] ];
653 | var v2 = vertices_of_intersection[ marching_cubes_triangle_table[ cube_index ][ a + 1 ] ];
654 | var v3 = vertices_of_intersection[ marching_cubes_triangle_table[ cube_index ][ a + 2 ] ];
655 |
656 | triangle( v1, v2, v3, isosurface_function, resolution, invert_normals );
657 |
658 | }
659 |
660 | }
661 |
662 | }
663 |
664 | }
665 |
666 | }
667 |
668 | // Begin creating the isosurfaces.
669 |
670 | // First isosurface.
671 |
672 | // Temporary arrays to hold all of the data that will be read into the buffers.
673 |
674 | var vertices = [ ];
675 | var vertex_normals = [ ];
676 | var vertex_colors = [ ];
677 |
678 | function isosurface_function( x, y, z )
679 | {
680 |
681 | // Goursat's surface.
682 |
683 | var x2 = x * x;
684 | var y2 = y * y;
685 | var z2 = z * z;
686 |
687 | var x4 = x2 * x2;
688 | var y4 = y2 * y2;
689 | var z4 = z2 * z2;
690 |
691 | var a = -1.0;
692 | var b = 0.0;
693 | var c = 0.5;
694 |
695 | var d = x2 + y2 + z2;
696 | var d2 = d * d;
697 |
698 | var value = x4 + y4 + z4 + a * d2 + b * d + c;
699 |
700 | return value;
701 |
702 | }
703 |
704 | // Grid min, grid max, resolution, iso-level, isosurface function, and invert normals.
705 | // Do not set the resolution to small.
706 |
707 | marching_cubes( -1.0, 1.0, 0.07, 0, isosurface_function, false );
708 |
709 | // Create the vertex buffer and bind it getting it ready to read in the vertices to the isosurface.
710 |
711 | isosurfaceVertexPositionBuffer = gl.createBuffer( );
712 |
713 | gl.bindBuffer( gl.ARRAY_BUFFER, isosurfaceVertexPositionBuffer );
714 |
715 | // Bind and fill the isosurface vertices.
716 |
717 | gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( vertices ), gl.STATIC_DRAW );
718 | isosurfaceVertexPositionBuffer.itemSize = 3;
719 | isosurfaceVertexPositionBuffer.numItems = vertices.length / 3;
720 |
721 | // Bind and fill the isosurface vertex normals.
722 |
723 | isosurfaceVertexNormalBuffer = gl.createBuffer( );
724 | gl.bindBuffer( gl.ARRAY_BUFFER, isosurfaceVertexNormalBuffer );
725 |
726 | gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( vertex_normals ), gl.STATIC_DRAW );
727 | isosurfaceVertexNormalBuffer.itemSize = 3;
728 | isosurfaceVertexNormalBuffer.numItems = vertex_normals.length / 3;
729 |
730 | // Bind and fill the isosurface vertex colors.
731 |
732 | isosurfaceVertexColorBuffer = gl.createBuffer( );
733 | gl.bindBuffer( gl.ARRAY_BUFFER, isosurfaceVertexColorBuffer );
734 |
735 | gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( vertex_colors ), gl.STATIC_DRAW );
736 | isosurfaceVertexColorBuffer.itemSize = 4;
737 | isosurfaceVertexColorBuffer.numItems = vertex_colors.length / 4;
738 |
739 | // Second isosurface.
740 |
741 | if ( init_buffers_called === 0 )
742 | {
743 |
744 | vertices = [ ];
745 | vertex_normals = [ ];
746 | vertex_colors = [ ];
747 |
748 | function isosurface_function1( x, y, z )
749 | {
750 |
751 | // The Taubin (heart) surface.
752 |
753 | // Swapped y and z from the standard formula.
754 |
755 | var x2 = x * x;
756 | var z2 = z * z;
757 | var y2 = y * y;
758 | var y3 = y * y * y;
759 |
760 | var a = x2 + ( 9 / 4 ) * z2 + y2 - 1;
761 | var a3 = a * a * a;
762 |
763 | var value = a3 - ( x2 * y3 ) - ( ( 9 / 80 ) * z2 * y3 );
764 |
765 | return value;
766 |
767 | }
768 |
769 | // Grid min, grid max, resolution, iso-level, isosurface function, and invert normals.
770 | // Do not set the resolution to small.
771 |
772 | marching_cubes( -1.5, 1.5, 0.08, 0, isosurface_function1, false );
773 |
774 | // Create the vertex buffer and bind it getting it ready to read in the vertices to the isosurface.
775 |
776 | isosurface1VertexPositionBuffer = gl.createBuffer( );
777 |
778 | gl.bindBuffer( gl.ARRAY_BUFFER, isosurface1VertexPositionBuffer );
779 |
780 | // Bind and fill the isosurface vertices.
781 |
782 | gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( vertices ), gl.STATIC_DRAW );
783 | isosurface1VertexPositionBuffer.itemSize = 3;
784 | isosurface1VertexPositionBuffer.numItems = vertices.length / 3;
785 |
786 | // Bind and fill the isosurface vertex normals.
787 |
788 | isosurface1VertexNormalBuffer = gl.createBuffer( );
789 | gl.bindBuffer( gl.ARRAY_BUFFER, isosurface1VertexNormalBuffer );
790 |
791 | gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( vertex_normals ), gl.STATIC_DRAW );
792 | isosurface1VertexNormalBuffer.itemSize = 3;
793 | isosurface1VertexNormalBuffer.numItems = vertex_normals.length / 3;
794 |
795 | // Bind and fill the isosurface vertex colors.
796 |
797 | isosurface1VertexColorBuffer = gl.createBuffer( );
798 | gl.bindBuffer( gl.ARRAY_BUFFER, isosurface1VertexColorBuffer );
799 |
800 | gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( vertex_colors ), gl.STATIC_DRAW );
801 | isosurface1VertexColorBuffer.itemSize = 4;
802 | isosurface1VertexColorBuffer.numItems = vertex_colors.length / 4;
803 |
804 | }
805 |
806 | // Point light representation.
807 |
808 | if ( init_buffers_called === 0 ) // Do not recreate the point light sphere more than once.
809 | {
810 |
811 | vertices = [ ];
812 | vertex_normals = [ ];
813 | vertex_colors = [ ];
814 |
815 | function isosurface_function2( x, y, z )
816 | {
817 |
818 | // A sphere.
819 |
820 | var value = ( ( x - 0 ) * ( x - 0 ) ) +
821 | ( ( y - 0 ) * ( y - 0 ) ) +
822 | ( ( z - 0 ) * ( z - 0 ) ) -
823 | ( ( 0.5 ) * ( 0.5 ) );
824 |
825 | return value;
826 |
827 | }
828 |
829 | // Grid min, grid max, resolution, iso-level, isosurface function, and invert normals.
830 | // Do not set the resolution to small.
831 |
832 | marching_cubes( -2, 2, 0.2, 0, isosurface_function2, false );
833 |
834 | // Make the sphere bright white.
835 |
836 | for ( var i = 0; i < vertex_colors.length; i += 4 )
837 | {
838 |
839 | vertex_colors[ i ] = 200.0;
840 | vertex_colors[ i + 1 ] = 200.0;
841 | vertex_colors[ i + 2 ] = 200.0;
842 | vertex_colors[ i + 3 ] = 1.0;
843 |
844 | }
845 |
846 | // Create the vertex buffer and bind it getting it ready to read in the vertices to the isosurface.
847 |
848 | pointLightSphereVertexPositionBuffer = gl.createBuffer( );
849 |
850 | gl.bindBuffer( gl.ARRAY_BUFFER, pointLightSphereVertexPositionBuffer );
851 |
852 | // Bind and fill the isosurface vertices.
853 |
854 | gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( vertices ), gl.STATIC_DRAW );
855 | pointLightSphereVertexPositionBuffer.itemSize = 3;
856 | pointLightSphereVertexPositionBuffer.numItems = vertices.length / 3;
857 |
858 | // Bind and fill the isosurface vertex normals.
859 |
860 | pointLightSphereVertexNormalBuffer = gl.createBuffer( );
861 | gl.bindBuffer( gl.ARRAY_BUFFER, pointLightSphereVertexNormalBuffer );
862 |
863 | gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( vertex_normals ), gl.STATIC_DRAW );
864 | pointLightSphereVertexNormalBuffer.itemSize = 3;
865 | pointLightSphereVertexNormalBuffer.numItems = vertex_normals.length / 3;
866 |
867 | // Bind and fill the isosurface vertex colors.
868 |
869 | pointLightSphereVertexColorBuffer = gl.createBuffer( );
870 | gl.bindBuffer( gl.ARRAY_BUFFER, pointLightSphereVertexColorBuffer );
871 |
872 | gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( vertex_colors ), gl.STATIC_DRAW );
873 | pointLightSphereVertexColorBuffer.itemSize = 4;
874 | pointLightSphereVertexColorBuffer.numItems = vertex_colors.length / 4;
875 |
876 | }
877 |
878 | init_buffers_called += 1;
879 |
880 | }
881 |
882 | function initHUD( )
883 | {
884 |
885 | // Create and show an onscreen logo.
886 |
887 | var logo_box = document.createElement( "div" );
888 | logo_box.id = "logo_box";
889 | logo_box.title = "Lettier";
890 | logo_box.className = "logo_box";
891 | logo_box.innerHTML = "
";
892 |
893 | document.body.appendChild( logo_box );
894 |
895 | var logo_image = document.getElementById( "logo" );
896 | logo_image_height = logo_image.clientHeight * 0.5;
897 | logo_image_width = logo_image.clientWidth * 0.5;
898 | logo_image.style.height = logo_image_height + "px";
899 | logo_image.style.width = logo_image_width + "px";
900 | logo_box.style.top = window.innerHeight - logo_image_height - 10 + "px";
901 | logo_box.style.left = window.innerWidth - logo_image_width - 10 + "px";
902 |
903 | }
904 |
905 | // Pass to the vertex shader the needed matrices.
906 |
907 | function setMatrixUniforms( )
908 | {
909 |
910 | // Pass the vertex shader the projection matrix and the model-view matrix.
911 |
912 | gl.uniformMatrix4fv( shaderProgram.pMatrixUniform, false, pMatrix );
913 | gl.uniformMatrix4fv( shaderProgram.mvMatrixUniform, false, mvMatrix );
914 |
915 | // Pass the vertex normal matrix to the shader so it can compute the lighting calculations.
916 |
917 | var normalMatrix = mat3.create( );
918 | mat3.normalFromMat4( normalMatrix, mvMatrix );
919 | gl.uniformMatrix3fv( shaderProgram.nMatrixUniform, false, normalMatrix );
920 |
921 | }
922 |
923 | function mvPushMatrix( )
924 | {
925 |
926 | // Save the model view matrix for later use.
927 |
928 | var copy = mat4.create( );
929 | copy = mat4.copy( copy, mvMatrix );
930 | mvMatrixStack.push( copy );
931 |
932 | }
933 |
934 | function mvPopMatrix( )
935 | {
936 |
937 | // Gather the previously pushed model view matrix.
938 |
939 | if ( mvMatrixStack.length === 0 )
940 | {
941 |
942 | console.error( "mvMatrixStack empty." );
943 |
944 | }
945 |
946 | mvMatrix = mvMatrixStack.pop( );
947 | }
948 |
949 | // The function renders the isosurfaces lit with the point light.
950 | // It also animates the rotation of the isosurfaces.
951 |
952 | function drawScene( timestamp )
953 | {
954 |
955 | // Call this function to draw the next frame.
956 |
957 | window.requestAnimationFrame( drawScene );
958 |
959 | // Time based animation instead of frame based animation.
960 |
961 | var time_now = new Date( ).getTime( );
962 |
963 | if ( time_last !== 0 )
964 | {
965 |
966 | var time_delta = ( time_now - time_last ) / 1000.0;
967 |
968 | rotation_radians += rotation_radians_step * time_delta;
969 |
970 | if ( rotation_radians > ( Math.PI * 2 ) ) rotation_radians = 0.0;
971 |
972 | if ( Number(use_lighting) === 1 )
973 | {
974 |
975 | point_light_theta += point_light_theta_step * time_delta;
976 | point_light_phi += point_light_phi_step * time_delta;
977 |
978 | if ( point_light_theta > ( Math.PI * 2 ) ) point_light_theta = 0.0;
979 | if ( point_light_phi > ( Math.PI * 2 ) ) point_light_phi = 0.0;
980 |
981 | point_light_theta1 += point_light_theta_step1 * time_delta;
982 | point_light_phi1 += point_light_phi_step1 * time_delta;
983 |
984 | if ( point_light_theta1 > ( Math.PI * 2 ) ) point_light_theta1 = 0.0;
985 | if ( point_light_phi1 > ( Math.PI * 2 ) ) point_light_phi1 = 0.0;
986 |
987 | }
988 |
989 | }
990 |
991 | time_last = time_now;
992 |
993 | // Set the size of and clear the render window.
994 |
995 | gl.viewport( 0, 0, gl.viewportWidth, gl.viewportHeight );
996 |
997 | gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );
998 |
999 | // Create the projection matrix.
1000 |
1001 | var near = 0.1;
1002 | var far = 50.0;
1003 | var fov_d = 55.0;
1004 | var fov_r = 55 * ( Math.PI / 180.0 );
1005 |
1006 | if ( JSON.parse(perspective_projection) )
1007 | {
1008 |
1009 | // Resulting perspective matrix, FOV in radians, aspect ratio, near, and far clipping plane.
1010 |
1011 | mat4.perspective( pMatrix, fov_r, gl.viewportWidth / gl.viewportHeight, near, far );
1012 |
1013 | // Let the fragment shader know that perspective projection is being used.
1014 |
1015 | gl.uniform1i( shaderProgram.perspectiveProjection, 1 );
1016 |
1017 | }
1018 | else
1019 | {
1020 |
1021 | // The goal is to have the object be about the same size in the window
1022 | // during orthographic project as it is during perspective projection.
1023 |
1024 | var a = gl.viewportWidth / gl.viewportHeight; // Window aspect ratio.
1025 | var h = 2 * ( 25 * Math.tan( fov_r / 2 ) ); // 25 is the absolute distance from the world origin to all of the isosurfaces' local origins.
1026 | var w = h * a; // Knowing the new window height size, get the new window width size based on the aspect ratio.
1027 |
1028 | // The canvas' origin is the upper left corner. To the right is the positive x-axis.
1029 | // Going down is the positive y-axis.
1030 |
1031 | // Any object at the world origin would appear at the upper left hand corner.
1032 | // Shift the origin to the middle of the screen.
1033 |
1034 | // Also, invert the y-axis as WebgL's positive y-axis points up while the canvas' positive
1035 | // y-axis points down the screen.
1036 |
1037 | // (0,O)------------------------(w,0)
1038 | // | |
1039 | // | |
1040 | // | |
1041 | // (0,h)------------------------(w,h)
1042 | //
1043 | // (-(w/2),(h/2))------------------------((w/2),(h/2))
1044 | // | |
1045 | // | (0,0) |
1046 | // | |
1047 | // (-(w/2),-(h/2))------------------------((w/2),-(h/2))
1048 |
1049 | // Resulting perspective matrix, left, right, bottom, top, near, and far clipping plane.
1050 |
1051 | mat4.ortho(
1052 |
1053 | pMatrix,
1054 | -( w / 2 ),
1055 | ( w / 2 ),
1056 | -( h / 2 ),
1057 | ( h / 2 ),
1058 | near,
1059 | far
1060 |
1061 | );
1062 |
1063 | // Let the fragment shader know that orthographic projection is being used.
1064 |
1065 | gl.uniform1i( shaderProgram.perspectiveProjection, 0 );
1066 |
1067 | }
1068 |
1069 | // Render different buffers to screen.
1070 |
1071 | gl.uniform1i( shaderProgram.showDepth, show_depth );
1072 | gl.uniform1i( shaderProgram.showNormals, show_normals );
1073 | gl.uniform1i( shaderProgram.showPosition, show_position );
1074 |
1075 | // Move to the 3D space origin.
1076 |
1077 | mat4.identity( mvMatrix );
1078 |
1079 | // Disable alpha blending.
1080 |
1081 | gl.disable( gl.BLEND );
1082 |
1083 | alpha_blending_enabled = 0;
1084 |
1085 | gl.uniform1i( shaderProgram.alphaBlendingEnabled, alpha_blending_enabled );
1086 |
1087 | if ( Number(use_lighting) === 1 )
1088 | {
1089 |
1090 | // Pass the lighting parameters to the fragment shader.
1091 |
1092 | // Global ambient color.
1093 |
1094 | gl.uniform3f( shaderProgram.ambientColorUniform, base_color[ 0 ], base_color[ 1 ], base_color[ 2 ] );
1095 |
1096 | // Point light 1.
1097 |
1098 | var point_light_position_x = 0 + 13.5 * Math.cos( point_light_theta ) * Math.sin( point_light_phi );
1099 | var point_light_position_y = 0 + 13.5 * Math.sin( point_light_theta ) * Math.sin( point_light_phi );
1100 | var point_light_position_z = -25 + 13.5 * Math.cos( point_light_phi );
1101 |
1102 | gl.uniform3f( shaderProgram.pointLightingColorUniform, lighting_power, lighting_power, lighting_power );
1103 |
1104 | gl.uniform3f( shaderProgram.pointLightingLocationUniform, point_light_position_x, point_light_position_y, point_light_position_z );
1105 |
1106 | // Point light 2.
1107 |
1108 | var point_light_position_x1 = 0 + 8.0 * Math.cos( point_light_theta1 ) * Math.sin( point_light_phi1 );
1109 | var point_light_position_y1 = 0 + 8.0 * Math.sin( point_light_theta1 ) * Math.sin( point_light_phi1 );
1110 | var point_light_position_z1 = -25 + 8.0 * Math.cos( point_light_phi1 );
1111 |
1112 | gl.uniform3f( shaderProgram.ambientColorUniform1, base_color[ 0 ], base_color[ 1 ], base_color[ 2 ] );
1113 |
1114 | gl.uniform3f( shaderProgram.pointLightingColorUniform1, lighting_power, lighting_power, lighting_power );
1115 |
1116 | gl.uniform3f( shaderProgram.pointLightingLocationUniform1, point_light_position_x1, point_light_position_y1, point_light_position_z1 );
1117 |
1118 | // Turn off lighting for a moment so that the point light isosurface is
1119 | // bright simulating that the light is emanating from the surface.
1120 |
1121 | use_lighting = 0;
1122 |
1123 | gl.uniform1i( shaderProgram.useLightingUniform, use_lighting );
1124 |
1125 | // Point light surfaces.
1126 |
1127 | // Save the model view matrix state.
1128 |
1129 | mvPushMatrix( );
1130 |
1131 | // Point light surface 1.
1132 |
1133 | mat4.translate( mvMatrix, mvMatrix, [ point_light_position_x, point_light_position_y, point_light_position_z ] );
1134 |
1135 | gl.bindBuffer( gl.ARRAY_BUFFER, pointLightSphereVertexPositionBuffer );
1136 | gl.vertexAttribPointer( shaderProgram.vertexPositionAttribute, pointLightSphereVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0 );
1137 |
1138 | gl.bindBuffer( gl.ARRAY_BUFFER, pointLightSphereVertexNormalBuffer );
1139 | gl.vertexAttribPointer( shaderProgram.vertexNormalAttribute, pointLightSphereVertexNormalBuffer.itemSize, gl.FLOAT, false, 0, 0 );
1140 |
1141 | gl.bindBuffer( gl.ARRAY_BUFFER, pointLightSphereVertexColorBuffer );
1142 | gl.vertexAttribPointer( shaderProgram.vertexColorAttribute, pointLightSphereVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0 );
1143 |
1144 | setMatrixUniforms( );
1145 |
1146 | gl.drawArrays( gl.TRIANGLES, 0, pointLightSphereVertexPositionBuffer.numItems );
1147 |
1148 | mvPopMatrix( );
1149 |
1150 | // Save the model view matrix state.
1151 |
1152 | mvPushMatrix( );
1153 |
1154 | // Point light surface 2.
1155 |
1156 | mat4.translate( mvMatrix, mvMatrix, [ point_light_position_x1, point_light_position_y1, point_light_position_z1 ] );
1157 |
1158 | gl.bindBuffer( gl.ARRAY_BUFFER, pointLightSphereVertexPositionBuffer );
1159 | gl.vertexAttribPointer( shaderProgram.vertexPositionAttribute, pointLightSphereVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0 );
1160 |
1161 | gl.bindBuffer( gl.ARRAY_BUFFER, pointLightSphereVertexNormalBuffer );
1162 | gl.vertexAttribPointer( shaderProgram.vertexNormalAttribute, pointLightSphereVertexNormalBuffer.itemSize, gl.FLOAT, false, 0, 0 );
1163 |
1164 | gl.bindBuffer( gl.ARRAY_BUFFER, pointLightSphereVertexColorBuffer );
1165 | gl.vertexAttribPointer( shaderProgram.vertexColorAttribute, pointLightSphereVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0 );
1166 |
1167 | setMatrixUniforms( );
1168 |
1169 | gl.drawArrays( gl.TRIANGLES, 0, pointLightSphereVertexPositionBuffer.numItems );
1170 |
1171 | mvPopMatrix( );
1172 |
1173 | use_lighting = 1;
1174 |
1175 | }
1176 |
1177 | // Move down the negative z-axis by 25 units.
1178 |
1179 | mat4.translate( mvMatrix, mvMatrix, [ 0.0, 0.0, -25.0 ] );
1180 |
1181 | // Save the model view matrix state.
1182 |
1183 | mvPushMatrix( );
1184 |
1185 | // Use lighting if enabled.
1186 |
1187 | gl.uniform1i( shaderProgram.useLightingUniform, Number(use_lighting) );
1188 |
1189 | // If normal map is enabled.
1190 |
1191 | gl.uniform1i( shaderProgram.normalMapEnabled, normal_map );
1192 |
1193 | // Second isosurface.
1194 |
1195 | // Scale up the surface in all dimensions.
1196 |
1197 | mat4.scale( mvMatrix, mvMatrix, [ 5.0, 5.0, 5.0 ] );
1198 |
1199 | // Rotate around the y-axis.
1200 |
1201 | mat4.rotate( mvMatrix, mvMatrix, -rotation_radians, [ 0, 1, 0 ] );
1202 |
1203 | gl.bindBuffer( gl.ARRAY_BUFFER, isosurface1VertexPositionBuffer );
1204 | gl.vertexAttribPointer( shaderProgram.vertexPositionAttribute, isosurface1VertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0 );
1205 |
1206 | gl.bindBuffer( gl.ARRAY_BUFFER, isosurface1VertexNormalBuffer );
1207 | gl.vertexAttribPointer( shaderProgram.vertexNormalAttribute, isosurface1VertexNormalBuffer.itemSize, gl.FLOAT, false, 0, 0 );
1208 |
1209 | gl.bindBuffer( gl.ARRAY_BUFFER, isosurface1VertexColorBuffer );
1210 | gl.vertexAttribPointer( shaderProgram.vertexColorAttribute, isosurface1VertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0 );
1211 |
1212 | setMatrixUniforms( );
1213 |
1214 | if ( Number(use_wireframe) === 0 )
1215 | {
1216 |
1217 | gl.drawArrays( gl.TRIANGLES, 0, isosurface1VertexPositionBuffer.numItems );
1218 |
1219 | }
1220 | else
1221 | {
1222 |
1223 | gl.drawArrays( gl.LINES, 0, isosurface1VertexPositionBuffer.numItems );
1224 |
1225 | }
1226 |
1227 | // Restore the model view matrix state.
1228 |
1229 | mvPopMatrix( );
1230 |
1231 | // Enable alpha blending.
1232 |
1233 | gl.blendFunc( gl.ONE, gl.ONE_MINUS_SRC_ALPHA );
1234 |
1235 | gl.enable( gl.BLEND );
1236 |
1237 | alpha_blending_enabled = 1;
1238 |
1239 | gl.uniform1i( shaderProgram.alphaBlendingEnabled, alpha_blending_enabled );
1240 |
1241 | // Save the current model view matrix for later use.
1242 |
1243 | mvPushMatrix( );
1244 |
1245 | // First isosurface.
1246 |
1247 | mat4.scale( mvMatrix, mvMatrix, [ 11.0, 11.0, 11.0 ] );
1248 |
1249 | // Rotate the model view matrix thereby rotating the isosurface.
1250 |
1251 | mat4.rotate( mvMatrix, mvMatrix, rotation_radians, [ 1, 1, 0 ] );
1252 |
1253 | // Pass to the vertex shader the isosurface data.
1254 |
1255 | gl.bindBuffer( gl.ARRAY_BUFFER, isosurfaceVertexPositionBuffer );
1256 | gl.vertexAttribPointer( shaderProgram.vertexPositionAttribute, isosurfaceVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0 );
1257 |
1258 | gl.bindBuffer( gl.ARRAY_BUFFER, isosurfaceVertexNormalBuffer );
1259 | gl.vertexAttribPointer( shaderProgram.vertexNormalAttribute, isosurfaceVertexNormalBuffer.itemSize, gl.FLOAT, false, 0, 0 );
1260 |
1261 | gl.bindBuffer( gl.ARRAY_BUFFER, isosurfaceVertexColorBuffer );
1262 | gl.vertexAttribPointer( shaderProgram.vertexColorAttribute, isosurfaceVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0 );
1263 |
1264 | setMatrixUniforms( );
1265 |
1266 | // Render the isosurface to the screen.
1267 |
1268 | if ( Number(use_wireframe) === 0 )
1269 | {
1270 |
1271 | gl.drawArrays( gl.TRIANGLES, 0, isosurfaceVertexPositionBuffer.numItems );
1272 |
1273 | }
1274 | else
1275 | {
1276 |
1277 | gl.drawArrays( gl.LINES, 0, isosurfaceVertexPositionBuffer.numItems );
1278 |
1279 | }
1280 |
1281 | // Get back the old model view matrix.
1282 |
1283 | mvPopMatrix( );
1284 |
1285 | }
1286 |
1287 | function resize_contents( )
1288 | {
1289 |
1290 | // The browser window has been re-sized so re-size the render window and onscreen elements.
1291 |
1292 | var logo_image = document.getElementById( "logo" );
1293 | logo_image_height = logo_image.clientHeight;
1294 | logo_image_width = logo_image.clientWidth;
1295 |
1296 | var logo_box = document.getElementById( "logo_box" );
1297 | logo_box.style.top = window.innerHeight - logo_image_height - 10 + "px";
1298 | logo_box.style.left = window.innerWidth - logo_image_width - 10 + "px";
1299 |
1300 | var canvas = document.getElementById( "webgl_canvas" );
1301 | canvas.width = window.innerWidth;
1302 | canvas.height = window.innerHeight;
1303 |
1304 | gl.viewportWidth = canvas.width;
1305 | gl.viewportHeight = canvas.height;
1306 |
1307 | }
1308 |
1309 | function webGLStart( )
1310 | {
1311 |
1312 | // Create and add the canvas that will be "painted" on or rather rendered to by WebGL.
1313 |
1314 | var canvas = document.createElement( "canvas" );
1315 | canvas.id = "webgl_canvas";
1316 | canvas.width = window.innerWidth;
1317 | canvas.height = window.innerHeight;
1318 | document.body.appendChild( canvas );
1319 |
1320 | // Vertex shader GLSL code.
1321 |
1322 | var vertex_shader = document.createElement( "script" );
1323 | vertex_shader.id = "shader-vs";
1324 | vertex_shader.type = "x-shader/x-vertex";
1325 | vertex_shader.innerHTML = "precision mediump float;";
1326 | vertex_shader.innerHTML += "attribute vec3 aVertexPosition;";
1327 | vertex_shader.innerHTML += "attribute vec3 aVertexNormal;";
1328 | vertex_shader.innerHTML += "attribute vec4 aVertexColor;";
1329 | vertex_shader.innerHTML += "uniform mat4 uMVMatrix;";
1330 | vertex_shader.innerHTML += "uniform mat4 uPMatrix;";
1331 | vertex_shader.innerHTML += "uniform mat3 uNMatrix;";
1332 | vertex_shader.innerHTML += "varying vec4 vPosition;";
1333 | vertex_shader.innerHTML += "varying vec4 vDiffuseColor;";
1334 | vertex_shader.innerHTML += "varying vec3 vTransformedNormal;";
1335 | vertex_shader.innerHTML += "void main( void ) {";
1336 | vertex_shader.innerHTML += " vDiffuseColor = aVertexColor;";
1337 | vertex_shader.innerHTML += " vTransformedNormal = uNMatrix * aVertexNormal;";
1338 | vertex_shader.innerHTML += " vPosition = uMVMatrix * vec4( aVertexPosition, 1.0 );";
1339 | vertex_shader.innerHTML += " gl_Position = uPMatrix * vPosition;";
1340 | vertex_shader.innerHTML += "}";
1341 | document.body.appendChild( vertex_shader );
1342 |
1343 | // Fragment shader GLSL code.
1344 |
1345 | var fragment_shader = document.createElement( "script" );
1346 | fragment_shader.id = "shader-fs";
1347 | fragment_shader.type = "x-shader/x-fragment";
1348 | fragment_shader.innerHTML = "precision mediump float;";
1349 | fragment_shader.innerHTML += "uniform mat4 uPMatrix;";
1350 | fragment_shader.innerHTML += "uniform bool uUseLighting;";
1351 | fragment_shader.innerHTML += "uniform bool uAlphaBlendingEnabled;";
1352 | fragment_shader.innerHTML += "uniform bool uShowDepth;";
1353 | fragment_shader.innerHTML += "uniform bool uShowNormals;";
1354 | fragment_shader.innerHTML += "uniform bool uShowPosition;";
1355 | fragment_shader.innerHTML += "uniform bool uPerspectiveProjection;";
1356 | fragment_shader.innerHTML += "uniform bool uNormalMap;";
1357 | fragment_shader.innerHTML += "uniform vec3 uAmbientColor;";
1358 | fragment_shader.innerHTML += "uniform vec3 uPointLightingLocation;";
1359 | fragment_shader.innerHTML += "uniform vec3 uPointLightingColor;";
1360 | fragment_shader.innerHTML += "uniform vec3 uPointLightingLocation1;";
1361 | fragment_shader.innerHTML += "uniform vec3 uPointLightingColor1;";
1362 | fragment_shader.innerHTML += "varying vec4 vPosition;";
1363 | fragment_shader.innerHTML += "varying vec3 vTransformedNormal;";
1364 | fragment_shader.innerHTML += "varying vec4 vDiffuseColor;";
1365 | fragment_shader.innerHTML += "void main( void ) {";
1366 | fragment_shader.innerHTML += " vec3 uAmbientColor = pow(uAmbientColor, vec3(2.2));";
1367 | fragment_shader.innerHTML += " vec4 vDiffuseColor = vDiffuseColor;";
1368 | fragment_shader.innerHTML += " vDiffuseColor.rgb = pow(vDiffuseColor.rgb, vec3(2.2));";
1369 | fragment_shader.innerHTML += " vec3 uPointLightingColor = pow(uPointLightingColor, vec3(2.2));";
1370 | fragment_shader.innerHTML += " vec3 uPointLightingColor1 = pow(uPointLightingColor1, vec3(2.2));";
1371 | fragment_shader.innerHTML += " vec4 fog_color = vec4( " + base_color[ 0 ] + ", " + base_color[ 1 ] + ", " + base_color[ 2 ] + ", 1.0 );";
1372 | fragment_shader.innerHTML += " fog_color.rgb = pow(fog_color.rgb, vec3(2.2));";
1373 | fragment_shader.innerHTML += " vec3 ambient = vDiffuseColor.rgb * uAmbientColor;";
1374 | fragment_shader.innerHTML += " vec3 color = ambient;";
1375 | fragment_shader.innerHTML += " if ( uUseLighting ) {";
1376 | fragment_shader.innerHTML += " vec3 light_direction = normalize( uPointLightingLocation - vPosition.xyz );";
1377 | fragment_shader.innerHTML += " vec3 light_direction1 = normalize( uPointLightingLocation1 - vPosition.xyz );";
1378 | fragment_shader.innerHTML += " vec3 eye_direction = -normalize( vPosition.xyz );";
1379 | fragment_shader.innerHTML += " vec3 half_vector = normalize(light_direction + eye_direction);";
1380 | fragment_shader.innerHTML += " vec3 half_vector1 = normalize(light_direction1 + eye_direction);";
1381 | fragment_shader.innerHTML += " vec3 surface_normal;";
1382 | fragment_shader.innerHTML += " if ( gl_FrontFacing ) {";
1383 | fragment_shader.innerHTML += " surface_normal = normalize( vTransformedNormal );";
1384 | fragment_shader.innerHTML += " }";
1385 | fragment_shader.innerHTML += " else {";
1386 | fragment_shader.innerHTML += " surface_normal = -normalize( vTransformedNormal );";
1387 | fragment_shader.innerHTML += " }";
1388 | fragment_shader.innerHTML += " if ( uNormalMap ) {";
1389 | fragment_shader.innerHTML += " surface_normal = normalize( surface_normal - ( sin( dot( vDiffuseColor.rgb, vec3( 12.9898, 78.233, 1.0 ) ) ) ) );";
1390 | fragment_shader.innerHTML += " }";
1391 | fragment_shader.innerHTML += " vec3 diffuse = vDiffuseColor.rgb * uPointLightingColor * max( dot( surface_normal, light_direction ), 0.0 );";
1392 | fragment_shader.innerHTML += " vec3 diffuse1 = vDiffuseColor.rgb * uPointLightingColor1 * max( dot( surface_normal, light_direction1 ), 0.0 );";
1393 | fragment_shader.innerHTML += " vec3 specular = uPointLightingColor * pow( max( dot( half_vector, surface_normal ), 0.0 ), 100.0 );";
1394 | fragment_shader.innerHTML += " vec3 specular1 = uPointLightingColor1 * pow( max( dot( half_vector1, surface_normal ), 0.0 ), 100.0 );";
1395 | fragment_shader.innerHTML += " float light_outer_radius = 20.0;";
1396 | fragment_shader.innerHTML += " float light_inner_radius = 0.0;";
1397 | fragment_shader.innerHTML += " float light_outer_radius1 = 10.0;";
1398 | fragment_shader.innerHTML += " float light_inner_radius1 = 0.0;";
1399 | fragment_shader.innerHTML += " float light_distance = length( vPosition.xyz - uPointLightingLocation );";
1400 | fragment_shader.innerHTML += " float light_distance1 = length( vPosition.xyz - uPointLightingLocation1 );";
1401 | fragment_shader.innerHTML += " float attenuation = 1.0 - smoothstep( light_inner_radius, light_outer_radius, light_distance );";
1402 | fragment_shader.innerHTML += " float attenuation1 = 1.0 - smoothstep( light_inner_radius1, light_outer_radius1, light_distance1 );";
1403 | fragment_shader.innerHTML += " diffuse = attenuation * diffuse;";
1404 | fragment_shader.innerHTML += " diffuse1 = attenuation1 * diffuse1;";
1405 | fragment_shader.innerHTML += " specular = attenuation * specular;";
1406 | fragment_shader.innerHTML += " specular1 = attenuation1 * specular1;";
1407 | fragment_shader.innerHTML += " color = ambient + diffuse + diffuse1 + specular + specular1;";
1408 | fragment_shader.innerHTML += " }";
1409 | fragment_shader.innerHTML += " vec4 final_color;";
1410 | fragment_shader.innerHTML += " if ( uAlphaBlendingEnabled ) {";
1411 | fragment_shader.innerHTML += " final_color = vec4( color, vDiffuseColor.a );";
1412 | fragment_shader.innerHTML += " }";
1413 | fragment_shader.innerHTML += " else {";
1414 | fragment_shader.innerHTML += " final_color = vec4( color, 1.0 );";
1415 | fragment_shader.innerHTML += " }";
1416 | fragment_shader.innerHTML += " float far = 50.0;";
1417 | fragment_shader.innerHTML += " float fog_coord;";
1418 | fragment_shader.innerHTML += " if ( uPerspectiveProjection ) {";
1419 | fragment_shader.innerHTML += " fog_coord = ( gl_FragCoord.z / gl_FragCoord.w ) / far;";
1420 | fragment_shader.innerHTML += " }";
1421 | fragment_shader.innerHTML += " else {";
1422 | fragment_shader.innerHTML += " fog_coord = ( gl_FragCoord.z / gl_FragCoord.w );";
1423 | fragment_shader.innerHTML += " }";
1424 | fragment_shader.innerHTML += " float fog_density = 1.5;";
1425 | fragment_shader.innerHTML += " float fog = fog_coord * fog_density;";
1426 | fragment_shader.innerHTML += " float fog_factor = clamp( 1.0 - fog, 0.0, 1.0 );";
1427 | fragment_shader.innerHTML += " gl_FragColor = mix( fog_color, final_color, vec4( fog_factor, fog_factor, fog_factor, fog_factor ) );";
1428 | fragment_shader.innerHTML += " gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(1.0 / 2.2));";
1429 | fragment_shader.innerHTML += " if ( uShowDepth ) {";
1430 | fragment_shader.innerHTML += " gl_FragColor = mix( vec4( 1.0 ), vec4( vec3( 0.0 ), 1.0 ), smoothstep( 0.1, 1.0, fog_coord ) );";
1431 | fragment_shader.innerHTML += " }";
1432 | fragment_shader.innerHTML += " if ( uShowNormals ) {";
1433 | fragment_shader.innerHTML += " vec3 nTN = normalize( vTransformedNormal );";
1434 | fragment_shader.innerHTML += " gl_FragColor = vec4( nTN.r, nTN.g, nTN.b, 1.0 );";
1435 | fragment_shader.innerHTML += " }";
1436 | fragment_shader.innerHTML += " if ( uShowPosition ) {";
1437 | fragment_shader.innerHTML += " vec3 nP = normalize( vPosition.xyz );";
1438 | fragment_shader.innerHTML += " gl_FragColor = vec4( nP.r, nP.g, nP.b, 1.0 );";
1439 | fragment_shader.innerHTML += " }";
1440 | fragment_shader.innerHTML += "}";
1441 | document.body.appendChild( fragment_shader );
1442 |
1443 | initGL( canvas ); // Initialize WebGL.
1444 | initShaders( ); // Initialize the shaders.
1445 | initBuffers( ); // Initialize the 3D shapes.
1446 | initHUD( ); // Initialize the onscreen elements.
1447 |
1448 | gl.clearColor( base_color[ 0 ], base_color[ 1 ], base_color[ 2 ], 1.0 ); // Set the WebGL background color.
1449 | gl.enable( gl.DEPTH_TEST ); // Enable the depth buffer.
1450 |
1451 | window.requestAnimationFrame( drawScene ); // Begin rendering animation.
1452 |
1453 | }
1454 |
1455 | /* Taken from http://paulbourke.net/geometry/polygonise/ */
1456 |
1457 | var marching_cubes_edge_table = [
1458 |
1459 | 0x0 , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
1460 | 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
1461 | 0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,
1462 | 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
1463 | 0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c,
1464 | 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
1465 | 0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac,
1466 | 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
1467 | 0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c,
1468 | 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
1469 | 0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc,
1470 | 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
1471 | 0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c,
1472 | 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
1473 | 0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc ,
1474 | 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
1475 | 0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,
1476 | 0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
1477 | 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,
1478 | 0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
1479 | 0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,
1480 | 0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
1481 | 0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,
1482 | 0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460,
1483 | 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
1484 | 0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0,
1485 | 0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,
1486 | 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230,
1487 | 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,
1488 | 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190,
1489 | 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,
1490 | 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0
1491 |
1492 | ];
1493 |
1494 | var marching_cubes_triangle_table = [
1495 |
1496 | [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1497 | [ 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1498 | [ 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1499 | [ 1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1500 | [ 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1501 | [ 0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1502 | [ 9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1503 | [ 2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1 ],
1504 | [ 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1505 | [ 0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1506 | [ 1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1507 | [ 1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1 ],
1508 | [ 3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1509 | [ 0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1 ],
1510 | [ 3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1 ],
1511 | [ 9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1512 | [ 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1513 | [ 4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1514 | [ 0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1515 | [ 4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1 ],
1516 | [ 1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1517 | [ 3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1 ],
1518 | [ 9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 ],
1519 | [ 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1 ],
1520 | [ 8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1521 | [ 11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1 ],
1522 | [ 9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 ],
1523 | [ 4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1 ],
1524 | [ 3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1 ],
1525 | [ 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1 ],
1526 | [ 4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1 ],
1527 | [ 4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1 ],
1528 | [ 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1529 | [ 9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1530 | [ 0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1531 | [ 8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1 ],
1532 | [ 1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1533 | [ 3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 ],
1534 | [ 5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1 ],
1535 | [ 2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1 ],
1536 | [ 9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1537 | [ 0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 ],
1538 | [ 0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 ],
1539 | [ 2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1 ],
1540 | [ 10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1 ],
1541 | [ 4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1 ],
1542 | [ 5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1 ],
1543 | [ 5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1 ],
1544 | [ 9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1545 | [ 9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1 ],
1546 | [ 0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1 ],
1547 | [ 1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1548 | [ 9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1 ],
1549 | [ 10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1 ],
1550 | [ 8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1 ],
1551 | [ 2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1 ],
1552 | [ 7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1 ],
1553 | [ 9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1 ],
1554 | [ 2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1 ],
1555 | [ 11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1 ],
1556 | [ 9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1 ],
1557 | [ 5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1 ],
1558 | [ 11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1 ],
1559 | [ 11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1560 | [ 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1561 | [ 0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1562 | [ 9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1563 | [ 1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 ],
1564 | [ 1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1565 | [ 1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1 ],
1566 | [ 9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1 ],
1567 | [ 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1 ],
1568 | [ 2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1569 | [ 11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 ],
1570 | [ 0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 ],
1571 | [ 5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1 ],
1572 | [ 6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1 ],
1573 | [ 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1 ],
1574 | [ 3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1 ],
1575 | [ 6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1 ],
1576 | [ 5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1577 | [ 4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1 ],
1578 | [ 1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 ],
1579 | [ 10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1 ],
1580 | [ 6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1 ],
1581 | [ 1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1 ],
1582 | [ 8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1 ],
1583 | [ 7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1 ],
1584 | [ 3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 ],
1585 | [ 5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1 ],
1586 | [ 0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1 ],
1587 | [ 9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1 ],
1588 | [ 8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1 ],
1589 | [ 5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1 ],
1590 | [ 0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1 ],
1591 | [ 6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1 ],
1592 | [ 10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1593 | [ 4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1 ],
1594 | [ 10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1 ],
1595 | [ 8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1 ],
1596 | [ 1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1 ],
1597 | [ 3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1 ],
1598 | [ 0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1599 | [ 8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1 ],
1600 | [ 10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1 ],
1601 | [ 0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1 ],
1602 | [ 3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1 ],
1603 | [ 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1 ],
1604 | [ 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1 ],
1605 | [ 8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1 ],
1606 | [ 3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1 ],
1607 | [ 6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1608 | [ 7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1 ],
1609 | [ 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1 ],
1610 | [ 10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1 ],
1611 | [ 10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1 ],
1612 | [ 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1 ],
1613 | [ 2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1 ],
1614 | [ 7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1 ],
1615 | [ 7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1616 | [ 2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1 ],
1617 | [ 2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1 ],
1618 | [ 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1 ],
1619 | [ 11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1 ],
1620 | [ 8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1 ],
1621 | [ 0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1622 | [ 7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1 ],
1623 | [ 7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1624 | [ 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1625 | [ 3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1626 | [ 0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1627 | [ 8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 ],
1628 | [ 10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1629 | [ 1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 ],
1630 | [ 2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 ],
1631 | [ 6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1 ],
1632 | [ 7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1633 | [ 7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1 ],
1634 | [ 2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1 ],
1635 | [ 1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1 ],
1636 | [ 10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1 ],
1637 | [ 10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1 ],
1638 | [ 0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1 ],
1639 | [ 7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1 ],
1640 | [ 6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1641 | [ 3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1 ],
1642 | [ 8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1 ],
1643 | [ 9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1 ],
1644 | [ 6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1 ],
1645 | [ 1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1 ],
1646 | [ 4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1 ],
1647 | [ 10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1 ],
1648 | [ 8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1 ],
1649 | [ 0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1650 | [ 1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1 ],
1651 | [ 1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1 ],
1652 | [ 8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1 ],
1653 | [ 10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1 ],
1654 | [ 4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1 ],
1655 | [ 10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1656 | [ 4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1657 | [ 0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 ],
1658 | [ 5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 ],
1659 | [ 11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1 ],
1660 | [ 9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 ],
1661 | [ 6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1 ],
1662 | [ 7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1 ],
1663 | [ 3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1 ],
1664 | [ 7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1 ],
1665 | [ 9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1 ],
1666 | [ 3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1 ],
1667 | [ 6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1 ],
1668 | [ 9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1 ],
1669 | [ 1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1 ],
1670 | [ 4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1 ],
1671 | [ 7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1 ],
1672 | [ 6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1 ],
1673 | [ 3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1 ],
1674 | [ 0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1 ],
1675 | [ 6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1 ],
1676 | [ 1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1 ],
1677 | [ 0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1 ],
1678 | [ 11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1 ],
1679 | [ 6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1 ],
1680 | [ 5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1 ],
1681 | [ 9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1 ],
1682 | [ 1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1 ],
1683 | [ 1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1684 | [ 1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1 ],
1685 | [ 10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1 ],
1686 | [ 0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1687 | [ 10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1688 | [ 11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1689 | [ 11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1 ],
1690 | [ 5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1 ],
1691 | [ 10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1 ],
1692 | [ 11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1 ],
1693 | [ 0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1 ],
1694 | [ 9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1 ],
1695 | [ 7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1 ],
1696 | [ 2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1 ],
1697 | [ 8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1 ],
1698 | [ 9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1 ],
1699 | [ 9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1 ],
1700 | [ 1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1701 | [ 0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1 ],
1702 | [ 9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1 ],
1703 | [ 9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1704 | [ 5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1 ],
1705 | [ 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1 ],
1706 | [ 0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1 ],
1707 | [ 10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1 ],
1708 | [ 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1 ],
1709 | [ 0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1 ],
1710 | [ 0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1 ],
1711 | [ 9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1712 | [ 2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1 ],
1713 | [ 5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1 ],
1714 | [ 3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1 ],
1715 | [ 5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1 ],
1716 | [ 8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1 ],
1717 | [ 0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1718 | [ 8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1 ],
1719 | [ 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1720 | [ 4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1 ],
1721 | [ 0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1 ],
1722 | [ 1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1 ],
1723 | [ 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1 ],
1724 | [ 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1 ],
1725 | [ 9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1 ],
1726 | [ 11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1 ],
1727 | [ 11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1 ],
1728 | [ 2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1 ],
1729 | [ 9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1 ],
1730 | [ 3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1 ],
1731 | [ 1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1732 | [ 4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1 ],
1733 | [ 4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1 ],
1734 | [ 4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1735 | [ 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1736 | [ 9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1737 | [ 3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1 ],
1738 | [ 0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1 ],
1739 | [ 3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1740 | [ 1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1 ],
1741 | [ 3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1 ],
1742 | [ 0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1743 | [ 3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1744 | [ 2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1 ],
1745 | [ 9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1746 | [ 2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1 ],
1747 | [ 1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1748 | [ 1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1749 | [ 0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1750 | [ 0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ],
1751 | [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ]
1752 |
1753 | ];
1754 |
--------------------------------------------------------------------------------