Added Rock and Fossil pages

This commit is contained in:
2014-02-24 13:05:21 +10:00
parent f8a12d58e8
commit c7e9bcd866
17 changed files with 982 additions and 720 deletions

View File

@@ -59,30 +59,43 @@ class Sample(CommonInfo):
#Use the inheritance manager for handling subclasses
objects = InheritanceManager()
def GetTopParent(self, current_parent):
if current_parent.parent is None:
return current_parent
else:
return self.GetTopParent(current_parent.parent)
@property
def url(self):
return 'three_d_viewer:mineral_detail'
#if isinstance(self, Mineral):
# return 'three_d_viewer:mineral_detail'
#else:
# return 'three_d_viewer:detail'
cat = self.GetTopParent(self.parent)
if cat.name == 'Fossils':
return 'three_d_viewer:fossil_detail'
elif cat.name == 'Rocks':
return 'three_d_viewer:rock_detail'
else:
return 'three_d_viewer:sample_detail'
class Mineral(Sample):
"""
Extending the Sample class to add details specific to minerals
"""
chemical_formula = models.CharField(max_length=100, blank=True)
hardness = models.DecimalField(max_digits=3, decimal_places=2, blank=True, null=True)
specific_gravity = models.DecimalField(max_digits=4, decimal_places=2, blank=True, null=True)
cleavage_fracture = models.CharField(max_length=100, blank=True)
lustre = models.CharField(max_length=100, blank=True)
colour = models.CharField(max_length=100, blank=True)
streak = models.CharField(max_length=100, blank=True)
habit = models.CharField(max_length=1000, blank=True)
crystallography = models.CharField(max_length=100, blank=True)
identifying_features = models.CharField(max_length=1000, blank=True)
occurance = models.CharField(max_length=1000, blank=True)
"""
Extending the Sample class to add details specific to minerals
"""
chemical_formula = models.CharField(max_length=100, blank=True)
hardness = models.DecimalField(max_digits=3, decimal_places=2, blank=True, null=True)
specific_gravity = models.DecimalField(max_digits=4, decimal_places=2, blank=True, null=True)
cleavage_fracture = models.CharField(max_length=100, blank=True)
lustre = models.CharField(max_length=100, blank=True)
colour = models.CharField(max_length=100, blank=True)
streak = models.CharField(max_length=100, blank=True)
habit = models.CharField(max_length=1000, blank=True)
crystallography = models.CharField(max_length=100, blank=True)
identifying_features = models.CharField(max_length=1000, blank=True)
occurance = models.CharField(max_length=1000, blank=True)
@property
def url(self):
return 'three_d_viewer:mineral_detail'
class Question(models.Model):

View File

@@ -37,8 +37,8 @@
<li class='last'><a href="{% url 'three_d_viewer:minerals_selftest' %}"><span>Self Test</span></a></li>
</ul>
</li>
<li class="mainitem"><a href='#'><span>Rocks</span></a></li>
<li class='last mainitem'><a href='#'><span>Fossils</span></a></li>
<li class="mainitem"><a href="{% url 'three_d_viewer:rocks_practice' %}"><span>Rocks</span></a></li>
<li class='last mainitem'><a href="{% url 'three_d_viewer:fossil_practice' %}"><span>Fossils</span></a></li>
</ul>
</div><!-- CLOSE CSSMENU !-->
</div><!-- CLOSE MENUCONTAINER !-->

View File

@@ -0,0 +1,35 @@
{% extends "three_d_viewer/sample_detail.html" %}
{% block load %}
function load(){
window.addEventListener('resize', resizeCanvas, false);
resizeCanvas();
var sampleFilename = '{{ sample.model_filename|escapejs }}';
if (sampleFilename.trim() == "")
{
document.getElementById("progress").innerHTML = "No model defined!";
return;
}
request = new XMLHttpRequest();
request.open("GET", '{{ MEDIA_URL }}' + sampleFilename, true);
request.overrideMimeType("text/plain; charset=x-user-defined");
request.onreadystatechange = function(){
if (this.readyState == 3 || this.readyState == 4){
document.getElementById("progress").innerHTML = "Downloading... "
+ formatNumber(this.responseText.length / 1048576, 2) + " MB";
}
if (this.readyState == 4 && (this.status == 200 || this.status == 0) ){
document.getElementById("progress").innerHTML = "Unpacking...";
setTimeout(loaded, 1);
}
}
request.send();
}
{% endblock load %}
{% block menu_header %}Select a Fossil{% endblock %}

View File

@@ -0,0 +1,3 @@
{% extends "three_d_viewer/sample_practice.html" %}
{% block menu_header %}Select a Fossil{% endblock %}

View File

@@ -1,72 +1,4 @@
{% extends "three_d_viewer/minerals_practice.html" %}
{% load static %}
{% block includes %}
{{ block.super }}
<script type="text/javascript" src="{% static "three_d_viewer/js/lzma.js" %}"></script>
<script type="text/javascript" src="{% static "three_d_viewer/js/ctm.js" %}"></script>
<script type="text/javascript" src="{% static "three_d_viewer/js/glMatrix-0.9.5.min.js" %}"></script>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec4 aVertexColor;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
varying vec4 vColor;
void main(void){
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1);
vColor = aVertexColor;
}
</script>
<script id="shader-fs" type="x-shader/x-fragment">
#ifdef GL_ES
precision highp float;
#endif
varying vec4 vColor;
void main(void){
gl_FragColor = vec4(vColor.rgb, 1);;
}
</script>
<script type="text/javascript">
var request;
var file;
var gl;
var shaderProgram;
var mvMatrix = mat4.create();
var pMatrix = mat4.create();
var vertexIndexBuffer;
var vertexPositionBuffer;
var vertexColorBuffer;
var offsets = [];
var mouseDown = false;
var lastMouseX;
var lastMouseY;
var translationMatrix = vec3.create();
var rotationMatrix = mat4.create();
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback, element){
window.setTimeout(callback, 1000/60);
};
})();
function formatNumber(numero, decimales){
var pot = Math.pow(10, decimales);
return parseInt(numero * pot) / pot;
}
{% extends "three_d_viewer/sample_detail.html" %}
{% block load %}
function load(){
@@ -98,317 +30,9 @@ function load(){
}
{% endblock load %}
function loaded(){
/*if ( navigator.userAgent.indexOf("WebKit") == -1){
var worker = new Worker("loader.js");
{% block menu_header %}Select a Mineral{% endblock %}
worker.onmessage = function(event){
file = event.data;
webGLStart();
document.getElementById("progress").innerHTML = "";
};
worker.postMessage(request.responseText);
}else{*/
file = new CTM.File( new CTM.Stream(request.responseText) );
webGLStart();
document.getElementById("progress").innerHTML = "";
//}
}
function webGLStart(){
var canvas = document.getElementById("canvas");
canvas.oncontextmenu = function() { return false; } // supress the context menu in the canvas
initGL(canvas);
initBoundingBox();
initOffsets();
initShaders();
initBuffers();
gl.clearColor(0, 0, 0, 0);
gl.enable(gl.DEPTH_TEST);
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
vec3.set(translationMatrix, [0, 0, -100]);
mat4.identity(rotationMatrix);
canvas.onmousedown = handleMouseDown;
canvas.onmouseup = handleMouseUp;
canvas.onmousemove = handleMouseMove;
canvas.onmousewheel = handleMouseWheel;
canvas.addEventListener("DOMMouseScroll", handleMouseWheel, false);
tick();
}
function initGL(canvas){
try{
gl = canvas.getContext("experimental-webgl");
gl.viewportWidth = canvas.width;
gl.viewportHeight = canvas.height;
}catch(e){
}
if (!gl){
alert("Could not initialise WebGL, sorry :-(");
}
}
function initBoundingBox(){
var v = file.body.vertices;
var x = Infinity, y = Infinity, z = Infinity;
var X = -Infinity, Y = -Infinity, Z = -Infinity;
for (var i = 0; i < v.length; i += 3){
if (v[i] < x) x = v[i];
if (v[i+1] < y) y = v[i+1];
if (v[i+2] < z) z = v[i+2];
if (v[i] > X) X = v[i];
if (v[i+1] > Y) Y = v[i+1];
if (v[i+2] > Z) Z = v[i+2];
}
for (var i = 0; i < v.length; i += 3){
v[i] = -( (X-x)/2 ) + ( v[i] - x);
v[i+1] = -( (Y-y)/2 ) + ( v[i+1] - y);
v[i+2] = -( (Z-z)/2 ) + ( v[i+2] - z);
}
}
function initOffsets(){
var indices = file.body.indices;
var start = 0;
var min = file.body.vertices.length;
var max = 0;
var minPrev = min;
for (var i = 0; i < indices.length;){
for (var j = 0; j < 3; ++ j){
var idx = indices[i ++];
if (idx < min) min = idx;
if (idx > max) max = idx;
}
if (max - min > 65535){
i -= 3;
for (var k = start; k < i; ++ k){
indices[k] -= minPrev;
}
offsets.push( {start: start, count: i - start, index: minPrev} );
start = i;
min = file.body.vertices.length;
max = 0;
}
minPrev = min;
}
for (var k = start; k < i; ++ k){
indices[k] -= minPrev;
}
offsets.push( {start: start, count: i - start, index: minPrev} );
}
function initShaders(){
var fragmentShader = getShader(gl, "shader-fs");
var vertexShader = getShader(gl, "shader-vs");
shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
gl.useProgram(shaderProgram);
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
shaderProgram.vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor");
gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);
shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
}
function getShader(gl, id){
var shaderScript = document.getElementById(id);
var str = "";
var node = shaderScript.firstChild;
while(node){
if (node.nodeType == 3){
str += node.textContent;
}
node = node.nextSibling;
}
var shader;
if (shaderScript.type == "x-shader/x-fragment"){
shader = gl.createShader(gl.FRAGMENT_SHADER);
}else if (shaderScript.type == "x-shader/x-vertex"){
shader = gl.createShader(gl.VERTEX_SHADER);
}
gl.shaderSource(shader, str);
gl.compileShader(shader);
return shader;
}
function initBuffers(){
vertexIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, vertexIndexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,
new Uint16Array(file.body.indices), gl.STATIC_DRAW);
vertexIndexBuffer.itemSize = 1;
vertexIndexBuffer.numItems = file.body.indices.length;
vertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexPositionBuffer);
gl.bufferData(gl.ARRAY_BUFFER,
file.body.vertices, gl.STATIC_DRAW);
vertexPositionBuffer.itemSize = 3;
vertexPositionBuffer.numItems = file.body.vertices.length;
vertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexColorBuffer);
gl.bufferData(gl.ARRAY_BUFFER,
file.body.attrMaps[0].attr, gl.STATIC_DRAW);
vertexColorBuffer.itemSize = 4;
vertexColorBuffer.numItems = file.body.attrMaps[0].attr.length;
}
function tick(){
drawScene();
requestAnimFrame(tick);
}
function drawScene(){
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.01, 1200.0, pMatrix);
mat4.translate(pMatrix, [0.0, 0,-.6]);
mat4.identity(mvMatrix);
mat4.translate(mvMatrix, translationMatrix);
mat4.multiply(mvMatrix, rotationMatrix);
gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
var normalMatrix = mat3.create();
mat4.toInverseMat3(mvMatrix, normalMatrix);
mat3.transpose(normalMatrix);
gl.uniformMatrix3fv(shaderProgram.nMatrixUniform, false, normalMatrix);
for (var i = 0; i < offsets.length; ++ i){
gl.bindBuffer(gl.ARRAY_BUFFER, vertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,
vertexPositionBuffer.itemSize, gl.FLOAT, false, 0, offsets[i].index * 4 * 3);
gl.bindBuffer(gl.ARRAY_BUFFER, vertexColorBuffer);
gl.vertexAttribPointer(shaderProgram.vertexColorAttribute,
vertexColorBuffer.itemSize, gl.FLOAT, false, 0, offsets[i].index * 4 * 4);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, vertexIndexBuffer);
gl.drawElements(gl.TRIANGLES, offsets[i].count, gl.UNSIGNED_SHORT, offsets[i].start * 2); // 2 = uint16
}
}
function degToRad(degrees){
return degrees * Math.PI / 180;
}
function handleMouseWheel(event){
event.preventDefault();
var delta = event.wheelDelta | -event.detail;
if (delta < 0){
translationMatrix[2] -= .05;
}else{
translationMatrix[2] += .05;
}
event.returnValue=false;
}
function handleMouseDown(event){
mouseDown = true;
lastMouseX = event.clientX;
lastMouseY = event.clientY;
}
function handleMouseUp(event){
mouseDown = false;
}
function handleMouseMove(event){
if (mouseDown){
var newX = event.clientX;
var newY = event.clientY;
var deltaX = newX - lastMouseX;
var deltaY = newY - lastMouseY;
switch (event.which) {
case 1: // left mouse
var newRotationMatrix = mat4.create();
mat4.identity(newRotationMatrix);
mat4.rotate(newRotationMatrix, degToRad(deltaX / 5), [0, 1, 0]);
mat4.rotate(newRotationMatrix, degToRad(deltaY / 5), [1, 0, 0]);
mat4.multiply(newRotationMatrix, rotationMatrix, rotationMatrix);
break;
case 3: // right mouse
//translationMatrix[0] += deltaX;
//translationMatrix[1] += deltaY;
var newTranslateMatrix = mat4.create();
mat4.identity(newTranslateMatrix);
mat4.translate(newTranslateMatrix, [deltaX, deltaY, 0], [deltaX, deltaY, 0])
console.log('moving ' + deltaX + ', ' + deltaY)
break;
}
lastMouseX = newX
lastMouseY = newY;
}
}
function resizeCanvas() {
var canvas = document.getElementById("canvas");
var parent = document.getElementById("virtualObject");
var canvasWidth1 = canvas.width;
var canvasHeight1 = canvas.height;
canvas.width = parent.offsetWidth;
canvas.height = parent.offsetHeight;
if (gl){
/*hmove = canvas.width / 2 - canvasWidth1 / 2
vmove = canvas.height / 2 - canvasHeight1 / 2
mat4.translate(mvMatrix, [hmove, vmove, 0.0])
console.log('Resizing from ' + canvasWidth1 + ' x ' + canvasHeight1 + ' to ' + canvas.width + ' x ' + canvas.height);
console.log('moving centre ' + hmove + ' x ' + vmove)*/
}
}
</script>
{% endblock %}
{% block loadscript %}"load()"{% endblock %}
{% block mineral_detail %}
{% block sample_detail %}
<div id="mineralContainer">
<div id="mineralOne">
<h1 class="subHeadings">{{ mineral.name }}</h1>
@@ -453,11 +77,4 @@ function resizeCanvas() {
<p>{{ mineral.occurance }}</p>
</div>
</div>
{% endblock %}
{% block 3dcontent %}
<div id="virtualObject">
<canvas id="canvas" class="example"></canvas>
<div><br><span id="progress" style="color: red"></span></div>
</div>
{% endblock %}
{% endblock %}

View File

@@ -1,23 +1,3 @@
{% extends "three_d_viewer/base.html" %}
{% extends "three_d_viewer/sample_practice.html" %}
{% block content %}
<div id="sidebar">
<div id='mineralMenu'>
<ul>
<li class="has-sub mainitem"><a href="#">Select a mineral</a>
<ul>
{% for sample in active_samples %}
<li><a href={% url sample.url sample.id %}>{{ sample.name }}</a></li>
{% endfor %}
</ul>
</li>
</ul>
</div><!-- close MINERALMENU !-->
{% block mineral_detail %}
{% endblock %}
</div>
{% block 3dcontent %}
{% endblock %}
{% endblock %}
{% block menu_header %}Select a Mineral{% endblock %}

View File

@@ -0,0 +1,35 @@
{% extends "three_d_viewer/sample_detail.html" %}
{% block load %}
function load(){
window.addEventListener('resize', resizeCanvas, false);
resizeCanvas();
var sampleFilename = '{{ sample.model_filename|escapejs }}';
if (sampleFilename.trim() == "")
{
document.getElementById("progress").innerHTML = "No model defined!";
return;
}
request = new XMLHttpRequest();
request.open("GET", '{{ MEDIA_URL }}' + sampleFilename, true);
request.overrideMimeType("text/plain; charset=x-user-defined");
request.onreadystatechange = function(){
if (this.readyState == 3 || this.readyState == 4){
document.getElementById("progress").innerHTML = "Downloading... "
+ formatNumber(this.responseText.length / 1048576, 2) + " MB";
}
if (this.readyState == 4 && (this.status == 200 || this.status == 0) ){
document.getElementById("progress").innerHTML = "Unpacking...";
setTimeout(loaded, 1);
}
}
request.send();
}
{% endblock load %}
{% block menu_header %}Select a rock{% endblock %}

View File

@@ -0,0 +1,3 @@
{% extends "three_d_viewer/sample_practice.html" %}
{% block menu_header %}Select a Rock{% endblock %}

View File

@@ -0,0 +1,406 @@
{% extends "three_d_viewer/sample_practice.html" %}
{% load static %}
{% block includes %}
{{ block.super }}
<script type="text/javascript" src="{% static "three_d_viewer/js/lzma.js" %}"></script>
<script type="text/javascript" src="{% static "three_d_viewer/js/ctm.js" %}"></script>
<script type="text/javascript" src="{% static "three_d_viewer/js/glMatrix-0.9.5.min.js" %}"></script>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec4 aVertexColor;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
varying vec4 vColor;
void main(void){
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1);
vColor = aVertexColor;
}
</script>
<script id="shader-fs" type="x-shader/x-fragment">
#ifdef GL_ES
precision highp float;
#endif
varying vec4 vColor;
void main(void){
gl_FragColor = vec4(vColor.rgb, 1);;
}
</script>
<script type="text/javascript">
var request;
var file;
var gl;
var shaderProgram;
var mvMatrix = mat4.create();
var pMatrix = mat4.create();
var vertexIndexBuffer;
var vertexPositionBuffer;
var vertexColorBuffer;
var offsets = [];
var mouseDown = false;
var lastMouseX;
var lastMouseY;
var translationMatrix = vec3.create();
var rotationMatrix = mat4.create();
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback, element){
window.setTimeout(callback, 1000/60);
};
})();
function formatNumber(numero, decimales){
var pot = Math.pow(10, decimales);
return parseInt(numero * pot) / pot;
}
{% block load %}
function load(){
window.addEventListener('resize', resizeCanvas, false);
resizeCanvas();
var sampleFilename = '{{ sample.model_filename|escapejs }}';
if (sampleFilename.trim() == "")
{
document.getElementById("progress").innerHTML = "No model defined!";
return;
}
request = new XMLHttpRequest();
request.open("GET", '{{ MEDIA_URL }}' + sampleFilename, true);
request.overrideMimeType("text/plain; charset=x-user-defined");
request.onreadystatechange = function(){
if (this.readyState == 3 || this.readyState == 4){
document.getElementById("progress").innerHTML = "Downloading... "
+ formatNumber(this.responseText.length / 1048576, 2) + " MB";
}
if (this.readyState == 4 && (this.status == 200 || this.status == 0) ){
document.getElementById("progress").innerHTML = "Unpacking...";
setTimeout(loaded, 1);
}
}
request.send();
}
{% endblock load %}
function loaded(){
file = new CTM.File( new CTM.Stream(request.responseText) );
webGLStart();
document.getElementById("progress").innerHTML = "";
}
function webGLStart(){
var canvas = document.getElementById("canvas");
canvas.oncontextmenu = function() { return false; } // supress the context menu in the canvas
initGL(canvas);
initBoundingBox();
initOffsets();
initShaders();
initBuffers();
gl.clearColor(0, 0, 0, 0);
gl.enable(gl.DEPTH_TEST);
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
vec3.set(translationMatrix, [0, 0, -100]);
mat4.identity(rotationMatrix);
canvas.onmousedown = handleMouseDown;
canvas.onmouseup = handleMouseUp;
canvas.onmousemove = handleMouseMove;
canvas.onmousewheel = handleMouseWheel;
canvas.addEventListener("DOMMouseScroll", handleMouseWheel, false);
tick();
}
function initGL(canvas){
try{
gl = canvas.getContext("experimental-webgl");
gl.viewportWidth = canvas.width;
gl.viewportHeight = canvas.height;
}catch(e){
}
if (!gl){
alert("Could not initialise WebGL, sorry :-(");
}
}
function initBoundingBox(){
var v = file.body.vertices;
var x = Infinity, y = Infinity, z = Infinity;
var X = -Infinity, Y = -Infinity, Z = -Infinity;
for (var i = 0; i < v.length; i += 3){
if (v[i] < x) x = v[i];
if (v[i+1] < y) y = v[i+1];
if (v[i+2] < z) z = v[i+2];
if (v[i] > X) X = v[i];
if (v[i+1] > Y) Y = v[i+1];
if (v[i+2] > Z) Z = v[i+2];
}
for (var i = 0; i < v.length; i += 3){
v[i] = -( (X-x)/2 ) + ( v[i] - x);
v[i+1] = -( (Y-y)/2 ) + ( v[i+1] - y);
v[i+2] = -( (Z-z)/2 ) + ( v[i+2] - z);
}
}
function initOffsets(){
var indices = file.body.indices;
var start = 0;
var min = file.body.vertices.length;
var max = 0;
var minPrev = min;
for (var i = 0; i < indices.length;){
for (var j = 0; j < 3; ++ j){
var idx = indices[i ++];
if (idx < min) min = idx;
if (idx > max) max = idx;
}
if (max - min > 65535){
i -= 3;
for (var k = start; k < i; ++ k){
indices[k] -= minPrev;
}
offsets.push( {start: start, count: i - start, index: minPrev} );
start = i;
min = file.body.vertices.length;
max = 0;
}
minPrev = min;
}
for (var k = start; k < i; ++ k){
indices[k] -= minPrev;
}
offsets.push( {start: start, count: i - start, index: minPrev} );
}
function initShaders(){
var fragmentShader = getShader(gl, "shader-fs");
var vertexShader = getShader(gl, "shader-vs");
shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
gl.useProgram(shaderProgram);
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
shaderProgram.vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor");
gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);
shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
}
function getShader(gl, id){
var shaderScript = document.getElementById(id);
var str = "";
var node = shaderScript.firstChild;
while(node){
if (node.nodeType == 3){
str += node.textContent;
}
node = node.nextSibling;
}
var shader;
if (shaderScript.type == "x-shader/x-fragment"){
shader = gl.createShader(gl.FRAGMENT_SHADER);
}else if (shaderScript.type == "x-shader/x-vertex"){
shader = gl.createShader(gl.VERTEX_SHADER);
}
gl.shaderSource(shader, str);
gl.compileShader(shader);
return shader;
}
function initBuffers(){
vertexIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, vertexIndexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,
new Uint16Array(file.body.indices), gl.STATIC_DRAW);
vertexIndexBuffer.itemSize = 1;
vertexIndexBuffer.numItems = file.body.indices.length;
vertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexPositionBuffer);
gl.bufferData(gl.ARRAY_BUFFER,
file.body.vertices, gl.STATIC_DRAW);
vertexPositionBuffer.itemSize = 3;
vertexPositionBuffer.numItems = file.body.vertices.length;
vertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexColorBuffer);
gl.bufferData(gl.ARRAY_BUFFER,
file.body.attrMaps[0].attr, gl.STATIC_DRAW);
vertexColorBuffer.itemSize = 4;
vertexColorBuffer.numItems = file.body.attrMaps[0].attr.length;
}
function tick(){
drawScene();
requestAnimFrame(tick);
}
function drawScene(){
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.01, 1200.0, pMatrix);
mat4.translate(pMatrix, [0.0, 0,-.6]);
mat4.identity(mvMatrix);
mat4.translate(mvMatrix, translationMatrix);
mat4.multiply(mvMatrix, rotationMatrix);
gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
var normalMatrix = mat3.create();
mat4.toInverseMat3(mvMatrix, normalMatrix);
mat3.transpose(normalMatrix);
gl.uniformMatrix3fv(shaderProgram.nMatrixUniform, false, normalMatrix);
for (var i = 0; i < offsets.length; ++ i){
gl.bindBuffer(gl.ARRAY_BUFFER, vertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,
vertexPositionBuffer.itemSize, gl.FLOAT, false, 0, offsets[i].index * 4 * 3);
gl.bindBuffer(gl.ARRAY_BUFFER, vertexColorBuffer);
gl.vertexAttribPointer(shaderProgram.vertexColorAttribute,
vertexColorBuffer.itemSize, gl.FLOAT, false, 0, offsets[i].index * 4 * 4);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, vertexIndexBuffer);
gl.drawElements(gl.TRIANGLES, offsets[i].count, gl.UNSIGNED_SHORT, offsets[i].start * 2); // 2 = uint16
}
}
function degToRad(degrees){
return degrees * Math.PI / 180;
}
function handleMouseWheel(event){
event.preventDefault();
var delta = event.wheelDelta | -event.detail;
if (delta < 0){
translationMatrix[2] -= .05;
}else{
translationMatrix[2] += .05;
}
event.returnValue=false;
}
function handleMouseDown(event){
mouseDown = true;
lastMouseX = event.clientX;
lastMouseY = event.clientY;
}
function handleMouseUp(event){
mouseDown = false;
}
function handleMouseMove(event){
if (mouseDown){
var newX = event.clientX;
var newY = event.clientY;
var deltaX = newX - lastMouseX;
var deltaY = newY - lastMouseY;
switch (event.which) {
case 1: // left mouse
var newRotationMatrix = mat4.create();
mat4.identity(newRotationMatrix);
mat4.rotate(newRotationMatrix, degToRad(deltaX / 5), [0, 1, 0]);
mat4.rotate(newRotationMatrix, degToRad(deltaY / 5), [1, 0, 0]);
mat4.multiply(newRotationMatrix, rotationMatrix, rotationMatrix);
break;
case 3: // right mouse
//translationMatrix[0] += deltaX;
//translationMatrix[1] += deltaY;
var newTranslateMatrix = mat4.create();
mat4.identity(newTranslateMatrix);
mat4.translate(newTranslateMatrix, [deltaX, deltaY, 0], [deltaX, deltaY, 0])
console.log('moving ' + deltaX + ', ' + deltaY)
break;
}
lastMouseX = newX
lastMouseY = newY;
}
}
function resizeCanvas() {
var canvas = document.getElementById("canvas");
var parent = document.getElementById("virtualObject");
var canvasWidth1 = canvas.width;
var canvasHeight1 = canvas.height;
canvas.width = parent.offsetWidth;
canvas.height = parent.offsetHeight;
if (gl){
/*hmove = canvas.width / 2 - canvasWidth1 / 2
vmove = canvas.height / 2 - canvasHeight1 / 2
mat4.translate(mvMatrix, [hmove, vmove, 0.0])
console.log('Resizing from ' + canvasWidth1 + ' x ' + canvasHeight1 + ' to ' + canvas.width + ' x ' + canvas.height);
console.log('moving centre ' + hmove + ' x ' + vmove)*/
}
}
</script>
{% endblock %}
{% block loadscript %}"load()"{% endblock %}
{% block sample_detail %}
{% endblock %}
{% block 3dcontent %}
<div id="virtualObject">
<canvas id="canvas" class="example"></canvas>
<div><br><span id="progress" style="color: red"></span></div>
</div>
{% endblock %}

View File

@@ -0,0 +1,23 @@
{% extends "three_d_viewer/base.html" %}
{% block content %}
<div id="sidebar">
<div id='mineralMenu'>
<ul>
<li class="has-sub mainitem"><a href="#">{% block menu_header %}Select a sample{% endblock %}</a>
<ul>
{% for sample in active_samples %}
<li><a href={% url sample.url sample.id %}>{{ sample.name }}</a></li>
{% endfor %}
</ul>
</li>
</ul>
</div><!-- close MINERALMENU !-->
{% block sample_detail %}
{% endblock %}
</div>
{% block 3dcontent %}
{% endblock %}
{% endblock %}

View File

@@ -9,11 +9,12 @@ urlpatterns = patterns(
url(r'^$', generic.TemplateView.as_view(template_name="three_d_viewer/home.html"), name='home'),
url(r'^minerals_theory/$', generic.TemplateView.as_view(template_name="three_d_viewer/minerals_theory.html"), name='minerals_theory'),
url(r'^minerals_practice/$', views.MineralPracticeView.as_view(template_name="three_d_viewer/minerals_practice.html"), name='minerals_practice'),
url(r'^minerals_selftest/$', generic.TemplateView.as_view(template_name="three_d_viewer/minerals_selftest.html"), name='minerals_selftest'),
url(r'^minerals/(?P<pk>\d+)/$', views.MineralDetailView.as_view(), name='mineral_detail'),
#url(r'^minerals/(?P<pk>\d+)/$', views.MineralPracticeView.as_view(), name='mineral_practice'),
#url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'),
#url(r'^minerals/(?P<pk>\d+)/$', views.MineralDetailView.as_view(), name='mineral_detail'),
url(r'^minerals_selftest/$', generic.TemplateView.as_view(template_name="three_d_viewer/minerals_selftest.html"), name='minerals_selftest'),
url(r'^rock_practice/$', views.RockPracticeView.as_view(), name='rocks_practice'),
url(r'^rocks/(?P<pk>\d+)/$', views.RockDetailView.as_view(), name='rock_detail'),
url(r'^fossil_practice/$', views.FossilPracticeView.as_view(), name='fossil_practice'),
url(r'^fossils/(?P<pk>\d+)/$', views.FossilDetailView.as_view(), name='fossil_detail'),
url(r'^media/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': settings.MEDIA_ROOT}),
)

View File

@@ -27,7 +27,7 @@ class HomeView(generic.ListView):
return context
class MineralPracticeView(generic.ListView):
model = Sample
model = Mineral
template_name = 'three_d_viewer/minerals_practice.html'
def get_context_data(self, **kwargs):
@@ -41,23 +41,6 @@ class MineralPracticeView(generic.ListView):
context['active_samples'] = sorted(result, key=attrgetter('name'))
return context
class DetailView(generic.DetailView):
"""
Define the view to view the 3D model of a sample
"""
model = Sample
template_name = 'three_d_viewer/detail.html'
parent_categories = Category.objects.filter(parent=None). \
filter(active=True).order_by("name")
def get_context_data(self, **kwargs):
context = super(DetailView, self).get_context_data(**kwargs)
context['active_samples'] = Sample.objects.select_subclasses(Mineral).filter(active=True).order_by('name')
context['parent_categories'] = Category.objects.filter(parent=None). \
filter(active=True).order_by('name')
return context
class MineralDetailView(generic.DetailView):
"""
Add extra functionality for mineral details
@@ -69,17 +52,87 @@ class MineralDetailView(generic.DetailView):
parent_categories = Category.objects.filter(parent=None). \
filter(active=True).order_by("name")
#def get_context_data(self, **kwargs):
# context = super(MineralDetailView, self).get_context_data(**kwargs)
# context['active_samples'] = Sample.objects.select_subclasses(Mineral).filter(active=True).order_by('name')
# context['parent_categories'] = Category.objects.filter(parent=None). \
# filter(active=True).order_by('name')
# return context
def get_context_data(self, **kwargs):
context = super(MineralDetailView, self).get_context_data(**kwargs)
cat = Category.objects.get(name='Minerals')
result = cat.active_samples
for child in cat.active_children:
result = chain(result, child.active_samples)
context['active_samples'] = sorted(result, key=attrgetter('name'))
return context
class RockPracticeView(generic.ListView):
model = Sample
template_name = 'three_d_viewer/rock_practice.html'
parent_categories = Category.objects.filter(parent=None). \
filter(active=True).order_by("name")
def get_context_data(self, **kwargs):
context = super(RockPracticeView, self).get_context_data(**kwargs)
cat = Category.objects.get(name='Rocks')
result = cat.active_samples
for child in cat.active_children:
result = chain(result, child.active_samples)
context['active_samples'] = sorted(result, key=attrgetter('name'))
return context
class RockDetailView(generic.DetailView):
model = Sample
template_name = 'three_d_viewer/rock_detail.html'
parent_categories = Category.objects.filter(parent=None). \
filter(active=True).order_by("name")
def get_context_data(self, **kwargs):
context = super(RockDetailView, self).get_context_data(**kwargs)
cat = Category.objects.get(name='Rocks')
result = cat.active_samples
for child in cat.active_children:
result = chain(result, child.active_samples)
context['active_samples'] = sorted(result, key=attrgetter('name'))
return context
class FossilPracticeView(generic.ListView):
model = Sample
template_name = 'three_d_viewer/fossil_practice.html'
parent_categories = Category.objects.filter(parent=None). \
filter(active=True).order_by("name")
def get_context_data(self, **kwargs):
context = super(FossilPracticeView, self).get_context_data(**kwargs)
cat = Category.objects.get(name='Fossils')
result = cat.active_samples
for child in cat.active_children:
result = chain(result, child.active_samples)
context['active_samples'] = sorted(result, key=attrgetter('name'))
return context
class FossilDetailView(generic.DetailView):
model = Sample
template_name = 'three_d_viewer/fossil_detail.html'
parent_categories = Category.objects.filter(parent=None). \
filter(active=True).order_by("name")
def get_context_data(self, **kwargs):
context = super(FossilDetailView, self).get_context_data(**kwargs)
cat = Category.objects.get(name='Fossils')
result = cat.active_samples
for child in cat.active_children:
result = chain(result, child.active_samples)