Commit dac26064 authored by amandaghassaei's avatar amandaghassaei

verlet integration in gpu

parent 147f2aba
......@@ -116,6 +116,17 @@ define(['glBoilerplate'], function(glBoilerplate){
this.frameBuffers[texture2Name] = temp;
};
GPUMath.prototype.swap3Textures = function(texture1Name, texture2Name, texture3Name){
var temp = this.textures[texture3Name];
this.textures[texture3Name] = this.textures[texture2Name];
this.textures[texture2Name] = this.textures[texture1Name];
this.textures[texture1Name] = temp;
temp = this.frameBuffers[texture3Name];
this.frameBuffers[texture3Name] = this.frameBuffers[texture2Name];
this.frameBuffers[texture2Name] = this.frameBuffers[texture1Name];
this.frameBuffers[texture1Name] = temp;
};
GPUMath.prototype.readyToRead = function(){
return gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE;
};
......
......@@ -4,10 +4,11 @@
define(['underscore', 'backbone', 'threeModel', 'lattice', 'plist', 'emWire', 'GPUMath', "text!simulation/shaders/vertexShader.js",
"text!simulation/function/EM/shaders/velocityCalcShader.js", "text!simulation/shaders/packToBytesShader.js", "text!simulation/function/EM/shaders/positionCalcShader.js",
"text!simulation/function/EM/shaders/angVelocityCalcShader.js", "text!simulation/function/EM/shaders/quaternionCalcShader.js", 'emSimCell'],
function(_, Backbone, three, lattice, plist, EMWire, gpuMath, vertexShader, velocityCalcShader, packToBytesShader,
positionCalcShader, angVelocityCalcShader, quaternionCalcShader) {
"text!simulation/function/EM/shaders/accelerationCalcShader.js", "text!simulation/shaders/packToBytesShader.js", "text!simulation/function/EM/shaders/positionCalcShader.js",
"text!simulation/function/EM/shaders/angVelocityCalcShader.js", "text!simulation/function/EM/shaders/quaternionCalcShader.js",
"text!simulation/function/EM/shaders/velocityCalcShader.js", 'emSimCell'],
function(_, Backbone, three, lattice, plist, EMWire, gpuMath, vertexShader, accelerationCalcShader, packToBytesShader,
positionCalcShader, angVelocityCalcShader, quaternionCalcShader, velocityCalcShader) {
var EMSimLattice = Backbone.Model.extend({
......@@ -52,6 +53,7 @@ define(['underscore', 'backbone', 'threeModel', 'lattice', 'plist', 'emWire', 'G
this.lastLastTranslation = new Float32Array(textureSize*4);
this.velocity = new Float32Array(textureSize*4);
this.lastVelocity = new Float32Array(textureSize*4);
this.acceleration = new Float32Array(textureSize*4);
this.quaternion = new Float32Array(textureSize*4);
this.lastQuaternion = new Float32Array(textureSize*4);
......@@ -257,10 +259,14 @@ define(['underscore', 'backbone', 'threeModel', 'lattice', 'plist', 'emWire', 'G
gpuMath.initFrameBufferForTexture("u_translation");
gpuMath.initTextureFromData("u_lastTranslation", textureDim, textureDim, "FLOAT", this.lastTranslation);
gpuMath.initFrameBufferForTexture("u_lastTranslation");
gpuMath.initTextureFromData("u_lastLastTranslation", textureDim, textureDim, "FLOAT", this.lastLastTranslation);
gpuMath.initFrameBufferForTexture("u_lastLastTranslation");
gpuMath.initTextureFromData("u_velocity", textureDim, textureDim, "FLOAT", this.velocity);
gpuMath.initFrameBufferForTexture("u_velocity");
gpuMath.initTextureFromData("u_lastVelocity", textureDim, textureDim, "FLOAT", this.lastVelocity);
gpuMath.initFrameBufferForTexture("u_lastVelocity");
gpuMath.initTextureFromData("u_acceleration", textureDim, textureDim, "FLOAT", this.acceleration);
gpuMath.initFrameBufferForTexture("u_acceleration");
gpuMath.initTextureFromData("u_quaternion", textureDim, textureDim, "FLOAT", this.quaternion);
gpuMath.initFrameBufferForTexture("u_quaternion");
gpuMath.initTextureFromData("u_lastQuaternion", textureDim, textureDim, "FLOAT", this.lastQuaternion);
......@@ -305,30 +311,37 @@ define(['underscore', 'backbone', 'threeModel', 'lattice', 'plist', 'emWire', 'G
gpuMath.setUniformForProgram("quaternionCalc", "u_mass", 2, "1i");
gpuMath.setUniformForProgram("quaternionCalc", "u_textureDim", [textureDim, textureDim], "2f");
gpuMath.createProgram("velocityCalc", vertexShader, velocityCalcShader);
gpuMath.setUniformForProgram("velocityCalc", "u_lastVelocity", 0, "1i");
gpuMath.setUniformForProgram("velocityCalc", "u_lastTranslation", 1, "1i");
gpuMath.setUniformForProgram("velocityCalc", "u_mass", 2, "1i");
gpuMath.setUniformForProgram("velocityCalc", "u_neighborsXMapping", 3, "1i");
gpuMath.setUniformForProgram("velocityCalc", "u_neighborsYMapping", 4, "1i");
gpuMath.setUniformForProgram("velocityCalc", "u_compositeKs", 5, "1i");
gpuMath.setUniformForProgram("velocityCalc", "u_compositeDs", 6, "1i");
gpuMath.setUniformForProgram("velocityCalc", "u_originalPosition", 7, "1i");
gpuMath.setUniformForProgram("velocityCalc", "u_lastQuaternion", 8, "1i");
gpuMath.setUniformForProgram("velocityCalc", "u_wires", 9, "1i");
gpuMath.setUniformForProgram("velocityCalc", "u_wiresMeta", 10, "1i");
gpuMath.setUniformForProgram("velocityCalc", "u_textureDim", [textureDim, textureDim], "2f");
gpuMath.setUniformForProgram("velocityCalc", "u_multiplier", 1/(plist.allUnitTypes[lattice.getUnits()].multiplier), "1f");
gpuMath.setUniformForProgram("velocityCalc", "u_latticePitch", [latticePitch.x, latticePitch.y, latticePitch.z], "3f");
gpuMath.setUniformForProgram("velocityCalc", "u_wiresMetaLength", this.wiresMeta.length/4, "1f");
gpuMath.setUniformForProgram("velocityCalc", "u_time", 0, "1f");
gpuMath.createProgram("accelerationCalc", vertexShader, accelerationCalcShader);
gpuMath.setUniformForProgram("accelerationCalc", "u_lastVelocity", 0, "1i");
gpuMath.setUniformForProgram("accelerationCalc", "u_lastTranslation", 1, "1i");
gpuMath.setUniformForProgram("accelerationCalc", "u_mass", 2, "1i");
gpuMath.setUniformForProgram("accelerationCalc", "u_neighborsXMapping", 3, "1i");
gpuMath.setUniformForProgram("accelerationCalc", "u_neighborsYMapping", 4, "1i");
gpuMath.setUniformForProgram("accelerationCalc", "u_compositeKs", 5, "1i");
gpuMath.setUniformForProgram("accelerationCalc", "u_compositeDs", 6, "1i");
gpuMath.setUniformForProgram("accelerationCalc", "u_originalPosition", 7, "1i");
gpuMath.setUniformForProgram("accelerationCalc", "u_lastQuaternion", 8, "1i");
gpuMath.setUniformForProgram("accelerationCalc", "u_wires", 9, "1i");
gpuMath.setUniformForProgram("accelerationCalc", "u_wiresMeta", 10, "1i");
gpuMath.setUniformForProgram("accelerationCalc", "u_textureDim", [textureDim, textureDim], "2f");
gpuMath.setUniformForProgram("accelerationCalc", "u_multiplier", 1/(plist.allUnitTypes[lattice.getUnits()].multiplier), "1f");
gpuMath.setUniformForProgram("accelerationCalc", "u_latticePitch", [latticePitch.x, latticePitch.y, latticePitch.z], "3f");
gpuMath.setUniformForProgram("accelerationCalc", "u_wiresMetaLength", this.wiresMeta.length/4, "1f");
gpuMath.setUniformForProgram("accelerationCalc", "u_time", 0, "1f");
gpuMath.createProgram("positionCalc", vertexShader, positionCalcShader);
gpuMath.setUniformForProgram("positionCalc", "u_lastVelocity", 0, "1i");
gpuMath.setUniformForProgram("positionCalc", "u_acceleration", 0, "1i");
gpuMath.setUniformForProgram("positionCalc", "u_lastTranslation", 1, "1i");
gpuMath.setUniformForProgram("positionCalc", "u_mass", 2, "1i");
gpuMath.setUniformForProgram("positionCalc", "u_lastLastTranslation", 2, "1i");
gpuMath.setUniformForProgram("positionCalc", "u_mass", 3, "1i");
gpuMath.setUniformForProgram("positionCalc", "u_textureDim", [textureDim, textureDim], "2f");
gpuMath.createProgram("velocityCalc", vertexShader, velocityCalcShader);
gpuMath.setUniformForProgram("velocityCalc", "u_translation", 0, "1i");
gpuMath.setUniformForProgram("velocityCalc", "u_lastTranslation", 1, "1i");
gpuMath.setUniformForProgram("velocityCalc", "u_mass", 2, "1i");
gpuMath.setUniformForProgram("velocityCalc", "u_textureDim", [textureDim, textureDim], "2f");
gpuMath.createProgram("packToBytes", vertexShader, packToBytesShader);
gpuMath.initTextureFromData("outputPositionBytes", textureDim*3, textureDim, "UNSIGNED_BYTE", null);
gpuMath.initFrameBufferForTexture("outputPositionBytes");
......@@ -542,11 +555,12 @@ define(['underscore', 'backbone', 'threeModel', 'lattice', 'plist', 'emWire', 'G
},
setConstants: function(dt, gravity, groundHeight, friction){
gpuMath.setProgram("accelerationCalc");
gpuMath.setUniformForProgram("accelerationCalc", "u_gravity", [gravity.x, gravity.y, gravity.z], "3f");
gpuMath.setUniformForProgram("accelerationCalc", "u_groundHeight", groundHeight, "1f");
gpuMath.setUniformForProgram("accelerationCalc", "u_friction", friction, "1f");
gpuMath.setProgram("velocityCalc");
gpuMath.setUniformForProgram("velocityCalc", "u_dt", dt, "1f");
gpuMath.setUniformForProgram("velocityCalc", "u_gravity", [gravity.x, gravity.y, gravity.z], "3f");
gpuMath.setUniformForProgram("velocityCalc", "u_groundHeight", groundHeight, "1f");
gpuMath.setUniformForProgram("velocityCalc", "u_friction", friction, "1f");
gpuMath.setProgram("positionCalc");
gpuMath.setUniformForProgram("positionCalc", "u_dt", dt, "1f");
gpuMath.setProgram("angVelocityCalc");
......@@ -557,74 +571,77 @@ define(['underscore', 'backbone', 'threeModel', 'lattice', 'plist', 'emWire', 'G
iter: function(time, runConstants, shouldRender){
//gpuMath.step("velocityCalc", ["u_lastVelocity", "u_lastTranslation", "u_mass", "u_neighborsXMapping",
// "u_neighborsYMapping", "u_compositeKs", "u_compositeDs", "u_originalPosition", "u_lastQuaternion", "u_wires",
// "u_wiresMeta"], "u_velocity", time);
//gpuMath.step("positionCalc", ["u_lastVelocity", "u_lastTranslation", "u_mass"], "u_translation");
//gpuMath.step("angVelocityCalc", ["u_lastAngVelocity", "u_lastVelocity", "u_lastTranslation", "u_mass", "u_neighborsXMapping",
// "u_neighborsYMapping", "u_compositeKs", "u_compositeDs", "u_lastQuaternion", "u_wires",
// "u_wiresMeta"], "u_angVelocity", time);
//gpuMath.step("quaternionCalc", ["u_angVelocity", "u_lastQuaternion", "u_mass"], "u_quaternion");
//
//if (shouldRender) {
// var textureSize = this.textureSize[0]*this.textureSize[1];
//
// //get position
// var vectorLength = 3;
// gpuMath.setProgram("packToBytes");
// gpuMath.setUniformForProgram("packToBytes", "u_vectorLength", vectorLength, "1f");
// gpuMath.setSize(this.textureSize[0]*vectorLength, this.textureSize[1]);
// gpuMath.step("packToBytes", ["u_translation"], "outputPositionBytes");
// var pixels = new Uint8Array(textureSize * 4*vectorLength);
// if (gpuMath.readyToRead()) {
// gpuMath.readPixels(0, 0, this.textureSize[0] * vectorLength, this.textureSize[1], pixels);
// var parsedPixels = new Float32Array(pixels.buffer);
// var cells = lattice.getCells();
// var multiplier = 1 / (plist.allUnitTypes[lattice.getUnits()].multiplier);
// for (var i = 0; i < textureSize; i++) {
// var rgbaIndex = 4 * i;
// if (this.mass[rgbaIndex+1] < 0) continue;//no more cells
// var index = [this.cellsArrayMapping[rgbaIndex], this.cellsArrayMapping[rgbaIndex + 1], this.cellsArrayMapping[rgbaIndex + 2]];
// var parsePixelsIndex = vectorLength * i;
// var translation = [parsedPixels[parsePixelsIndex], parsedPixels[parsePixelsIndex + 1], parsedPixels[parsePixelsIndex + 2]];
// var position = [this.originalPosition[rgbaIndex], this.originalPosition[rgbaIndex + 1], this.originalPosition[rgbaIndex + 2]];
// position[0] += multiplier * translation[0];
// position[1] += multiplier * translation[1];
// position[2] += multiplier * translation[2];
// cells[index[0]][index[1]][index[2]].object3D.position.set(position[0], position[1], position[2]);
// }
// }
//
// vectorLength = 4;
// gpuMath.setUniformForProgram("packToBytes", "u_vectorLength", vectorLength, "1f");
// gpuMath.setSize(this.textureSize[0]*vectorLength, this.textureSize[1]);
// gpuMath.step("packToBytes", ["u_quaternion"], "outputQuaternionBytes");
// pixels = new Uint8Array(textureSize * 4*vectorLength);
// if (gpuMath.readyToRead()) {
// gpuMath.readPixels(0, 0, this.textureSize[0] * vectorLength, this.textureSize[1], pixels);
// parsedPixels = new Float32Array(pixels.buffer);
// for (var i = 0; i < textureSize; i++) {
// var rgbaIndex = 4 * i;
// if (this.mass[rgbaIndex+1] < 0) break;//no more cells
// var index = [this.cellsArrayMapping[rgbaIndex], this.cellsArrayMapping[rgbaIndex + 1], this.cellsArrayMapping[rgbaIndex + 2]];
// var parsePixelsIndex = vectorLength * i;
//
// var quaternion = this._multiplyQuaternions([parsedPixels[parsePixelsIndex], parsedPixels[parsePixelsIndex + 1], parsedPixels[parsePixelsIndex + 2], parsedPixels[parsePixelsIndex + 3]],
// [this.originalQuaternion[rgbaIndex], this.originalQuaternion[rgbaIndex+1], this.originalQuaternion[rgbaIndex+2], this.originalQuaternion[rgbaIndex+3]]);
// var rotation = this._eulerFromQuaternion(quaternion);
//
// cells[index[0]][index[1]][index[2]].object3D.rotation.set(rotation[0], rotation[1], rotation[2]);
// }
// }
//
// gpuMath.setSize(this.textureSize[0], this.textureSize[1]);
//}
//
//gpuMath.swapTextures("u_velocity", "u_lastVelocity");
//gpuMath.swapTextures("u_translation", "u_lastTranslation");
//gpuMath.swapTextures("u_angVelocity", "u_lastAngVelocity");
//gpuMath.swapTextures("u_quaternion", "u_lastQuaternion");
//return;
gpuMath.step("accelerationCalc", ["u_lastVelocity", "u_lastTranslation", "u_mass", "u_neighborsXMapping",
"u_neighborsYMapping", "u_compositeKs", "u_compositeDs", "u_originalPosition", "u_lastQuaternion", "u_wires",
"u_wiresMeta"], "u_acceleration", time);
gpuMath.step("positionCalc", ["u_acceleration", "u_lastTranslation", "u_lastLastTranslation", "u_mass"],
"u_translation");
gpuMath.step("velocityCalc", ["u_translation", "u_lastTranslation"], "u_velocity");
gpuMath.step("angVelocityCalc", ["u_lastAngVelocity", "u_lastVelocity", "u_lastTranslation", "u_mass", "u_neighborsXMapping",
"u_neighborsYMapping", "u_compositeKs", "u_compositeDs", "u_lastQuaternion", "u_wires",
"u_wiresMeta"], "u_angVelocity", time);
gpuMath.step("quaternionCalc", ["u_angVelocity", "u_lastQuaternion", "u_mass"], "u_quaternion");
if (shouldRender) {
var textureSize = this.textureSize[0]*this.textureSize[1];
//get position
var vectorLength = 3;
gpuMath.setProgram("packToBytes");
gpuMath.setUniformForProgram("packToBytes", "u_vectorLength", vectorLength, "1f");
gpuMath.setSize(this.textureSize[0]*vectorLength, this.textureSize[1]);
gpuMath.step("packToBytes", ["u_translation"], "outputPositionBytes");
var pixels = new Uint8Array(textureSize * 4*vectorLength);
if (gpuMath.readyToRead()) {
gpuMath.readPixels(0, 0, this.textureSize[0] * vectorLength, this.textureSize[1], pixels);
var parsedPixels = new Float32Array(pixels.buffer);
var cells = lattice.getCells();
var multiplier = 1 / (plist.allUnitTypes[lattice.getUnits()].multiplier);
for (var i = 0; i < textureSize; i++) {
var rgbaIndex = 4 * i;
if (this.mass[rgbaIndex+1] < 0) continue;//no more cells
var index = [this.cellsArrayMapping[rgbaIndex], this.cellsArrayMapping[rgbaIndex + 1], this.cellsArrayMapping[rgbaIndex + 2]];
var parsePixelsIndex = vectorLength * i;
var translation = [parsedPixels[parsePixelsIndex], parsedPixels[parsePixelsIndex + 1], parsedPixels[parsePixelsIndex + 2]];
var position = [this.originalPosition[rgbaIndex], this.originalPosition[rgbaIndex + 1], this.originalPosition[rgbaIndex + 2]];
position[0] += multiplier * translation[0];
position[1] += multiplier * translation[1];
position[2] += multiplier * translation[2];
cells[index[0]][index[1]][index[2]].object3D.position.set(position[0], position[1], position[2]);
}
}
vectorLength = 4;
gpuMath.setUniformForProgram("packToBytes", "u_vectorLength", vectorLength, "1f");
gpuMath.setSize(this.textureSize[0]*vectorLength, this.textureSize[1]);
gpuMath.step("packToBytes", ["u_quaternion"], "outputQuaternionBytes");
pixels = new Uint8Array(textureSize * 4*vectorLength);
if (gpuMath.readyToRead()) {
gpuMath.readPixels(0, 0, this.textureSize[0] * vectorLength, this.textureSize[1], pixels);
parsedPixels = new Float32Array(pixels.buffer);
for (var i = 0; i < textureSize; i++) {
var rgbaIndex = 4 * i;
if (this.mass[rgbaIndex+1] < 0) break;//no more cells
var index = [this.cellsArrayMapping[rgbaIndex], this.cellsArrayMapping[rgbaIndex + 1], this.cellsArrayMapping[rgbaIndex + 2]];
var parsePixelsIndex = vectorLength * i;
var quaternion = this._multiplyQuaternions([parsedPixels[parsePixelsIndex], parsedPixels[parsePixelsIndex + 1], parsedPixels[parsePixelsIndex + 2], parsedPixels[parsePixelsIndex + 3]],
[this.originalQuaternion[rgbaIndex], this.originalQuaternion[rgbaIndex+1], this.originalQuaternion[rgbaIndex+2], this.originalQuaternion[rgbaIndex+3]]);
var rotation = this._eulerFromQuaternion(quaternion);
cells[index[0]][index[1]][index[2]].object3D.rotation.set(rotation[0], rotation[1], rotation[2]);
}
}
gpuMath.setSize(this.textureSize[0], this.textureSize[1]);
}
gpuMath.swapTextures("u_velocity", "u_lastVelocity");
gpuMath.swap3Textures("u_translation", "u_lastTranslation", "u_lastLastTranslation");
gpuMath.swapTextures("u_angVelocity", "u_lastAngVelocity");
gpuMath.swapTextures("u_quaternion", "u_lastQuaternion");
return;
var gravity = runConstants.gravity;
var groundHeight = runConstants.groundHeight;
......
#define M_PI 3.1415926535897932384626433832795
precision mediump float;
uniform vec2 u_textureDim;
uniform vec3 u_gravity;
uniform float u_multiplier;
uniform vec3 u_latticePitch;
uniform float u_wiresMetaLength;
uniform float u_time;
uniform float u_groundHeight;
uniform float u_friction;
uniform sampler2D u_lastVelocity;
uniform sampler2D u_lastTranslation;
uniform sampler2D u_mass;
uniform sampler2D u_neighborsXMapping;
uniform sampler2D u_neighborsYMapping;
uniform sampler2D u_compositeKs;
uniform sampler2D u_compositeDs;
uniform sampler2D u_originalPosition;
uniform sampler2D u_lastQuaternion;
uniform sampler2D u_wires;
uniform sampler2D u_wiresMeta;
vec3 applyQuaternion(vec3 vector, vec4 quaternion) {
float x = vector[0];
float y = vector[1];
float z = vector[2];
float qx = quaternion[0];
float qy = quaternion[1];
float qz = quaternion[2];
float qw = quaternion[3];
// calculate quat * vector
float ix = qw * x + qy * z - qz * y;
float iy = qw * y + qz * x - qx * z;
float iz = qw * z + qx * y - qy * x;
float iw = - qx * x - qy * y - qz * z;
// calculate result * inverse quat
return vec3(ix * qw + iw * - qx + iy * - qz - iz * - qy, iy * qw + iw * - qy + iz * - qx - ix * - qz,
iz * qw + iw * - qz + ix * - qy - iy * - qx);
}
float neighborSign(float i){
if (mod(i+0.001,2.0) < 0.5) return -1.0;
return 1.0;
}
vec3 neighborOffset(float i){
vec3 offset = vec3(0);
int neighborAxis = int(floor(i/2.0+0.001));
if (neighborAxis == 0) offset[0] = neighborSign(i)*u_latticePitch[0];
else if (neighborAxis == 1) offset[1] = neighborSign(i)*u_latticePitch[1];
else if (neighborAxis == 2) offset[2] = neighborSign(i)*u_latticePitch[2];
return offset;
}
int calcNeighborAxis(float i){
return int(floor(i/2.0+0.001));
}
int convertToInt(float num){
return int(floor(num+0.001));
}
float getActuatorVoltage(float wireIndex){
vec2 wireCoord = vec2(0.5, (floor(wireIndex+0.001)+0.5)/u_wiresMetaLength);
vec4 wireMeta = texture2D(u_wiresMeta, wireCoord);
int type = convertToInt(wireMeta[0]);
if (type == -1) {
//no signal connected
return 0.0;
}
float frequency = wireMeta[1];
float period = 1.0/frequency;
float phase = wireMeta[2];
float currentPhase = mod(u_time+phase*period, period)/period;
if (type == 0){
return 0.5*sin(2.0*M_PI*currentPhase);
}
if (type == 1){
float pwm = wireMeta[3];
if (currentPhase < pwm) return 0.5;
return -0.5;
}
if (type == 2){
if (wireMeta[3]>0.5) return 0.5-currentPhase;
return currentPhase-0.5;
}
if (type == 3){
if (currentPhase < 0.5) return currentPhase*2.0-0.5;
return 0.5-(currentPhase-0.5)*2.0;
}
return 0.0;
}
vec4 averageQuaternions(vec4 quaternion1, vec4 quaternion2){
float x = quaternion1[0], y = quaternion1[1], z = quaternion1[2], w = quaternion1[3];
float _x1 = quaternion1[0], _y1 = quaternion1[1], _z1 = quaternion1[2], _w1 = quaternion1[3];
float _x2 = quaternion2[0], _y2 = quaternion2[1], _z2 = quaternion2[2], _w2 = quaternion2[3];
// http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
float cosHalfTheta = w * _w2 + x * _x2 + y * _y2 + z * _z2;
if ( cosHalfTheta < 0.0 ) {
_w1 = - _w2;
_x1 = - _x2;
_y1 = - _y2;
_z1 = - _z2;
cosHalfTheta = - cosHalfTheta;
} else {
_w1 = _w2;
_x1 = _x2;
_y1 = _y2;
_z1 = _z2;
}
if ( cosHalfTheta >= 1.0 ) {
_w1 = w;
_x1 = x;
_y1 = y;
_z1 = z;
return vec4(_x1, _y1, _z1, _w1);
}
float halfTheta = acos( cosHalfTheta );
float sinHalfTheta = sqrt( 1.0 - cosHalfTheta * cosHalfTheta );
if ( abs( sinHalfTheta ) < 0.001 ) {
_w1 = 0.5 * ( w + _w1 );
_x1 = 0.5 * ( x + _x1 );
_y1 = 0.5 * ( y + _y1 );
_z1 = 0.5 * ( z + _z1 );
return vec4(_x1, _y1, _z1, _w1);
}
float ratioA = sin( ( 0.5 ) * halfTheta ) / sinHalfTheta,
ratioB = sin( 0.5 * halfTheta ) / sinHalfTheta;
_w1 = ( w * ratioA + _w1 * ratioB );
_x1 = ( x * ratioA + _x1 * ratioB );
_y1 = ( y * ratioA + _y1 * ratioB );
_z1 = ( z * ratioA + _z1 * ratioB );
return vec4(_x1, _y1, _z1, _w1);
}
vec4 normalize4D(vec4 vector){
float length = sqrt(vector[0]*vector[0] + vector[1]*vector[1] + vector[2]*vector[2] + vector[3]*vector[3]);
return vec4(vector[0]/length, vector[1]/length, vector[2]/length, vector[3]/length);
}
vec4 invertQuaternion (vec4 quaternion){
return normalize4D(vec4(quaternion[0]*-1.0, quaternion[1]*-1.0, quaternion[2]*-1.0, quaternion[3]));
}
void main(){
vec2 fragCoord = gl_FragCoord.xy;
vec2 scaledFragCoord = fragCoord/u_textureDim;
vec3 massData = texture2D(u_mass, scaledFragCoord).xyz;
float isFixed = massData.y;
if (isFixed < 0.0 || isFixed == 1.0){//no cell or is fixed
gl_FragColor = vec4(0, 0, 0, 0);
return;
}
float mass = massData.x;
vec3 force = u_gravity*mass;
vec3 translation = texture2D(u_lastTranslation, scaledFragCoord).xyz;
vec3 velocity = texture2D(u_lastVelocity, scaledFragCoord).xyz;
vec4 quaternion = texture2D(u_lastQuaternion, scaledFragCoord);
vec4 wiring = texture2D(u_wires, scaledFragCoord);
bool isActuator = wiring[0] < -0.5;//-1
//simple collision
float zPosition = texture2D(u_originalPosition, scaledFragCoord).z + translation.z*u_multiplier - u_groundHeight;
float collisionK = 1.0;
if (zPosition < 0.0) {
float normalForce = -zPosition*collisionK-velocity.z*collisionK/10.0;
force.z += normalForce;
if (u_friction > 0.5){
float mu = 10.0;
if (velocity.x > 0.0) force.x -= mu * normalForce;
else if (velocity.x < 0.0) force.x += mu * normalForce;
if (velocity.y > 0.0) force.y -= mu * normalForce;
else if (velocity.y < 0.0) force.y += mu * normalForce;
}
}
for (float i=0.0;i<2.0;i+=1.0){
float xIndex = 2.0*(fragCoord.x-0.5) + 0.5;
if (i>0.0) xIndex += 1.0;
vec2 mappingIndex = vec2(xIndex/(u_textureDim.x*2.0), scaledFragCoord.y);
vec3 neighborsXMapping = texture2D(u_neighborsXMapping, mappingIndex).xyz;
vec3 neighborsYMapping = texture2D(u_neighborsYMapping, mappingIndex).xyz;
for (int j=0;j<3;j++){
if (neighborsXMapping[j] < 0.0) continue;//no neighbor
int neighborAxis = calcNeighborAxis(i*3.0+float(j));
vec2 neighborIndex = vec2(neighborsXMapping[j], neighborsYMapping[j]);
neighborIndex.x += 0.5;
neighborIndex.y += 0.5;
vec2 scaledNeighborIndex = neighborIndex/u_textureDim;
vec3 neighborTranslation = texture2D(u_lastTranslation, scaledNeighborIndex).xyz;
vec3 neighborVelocity = texture2D(u_lastVelocity, scaledNeighborIndex).xyz;
vec4 neighborQuaternion = texture2D(u_lastQuaternion, scaledNeighborIndex);
vec3 nominalD = neighborOffset(i*3.0+float(j));
vec3 halfNominalD = nominalD/2.0;
vec3 cellHalfNominalD = applyQuaternion(halfNominalD, quaternion);//halfNominalD in cell's reference frame
vec3 neighborHalfNominalD = applyQuaternion(halfNominalD, neighborQuaternion);//halfNominalD in neighbor's reference frame
//vec3 actuatedD = vec3(nominalD[0], nominalD[1], nominalD[2]);
//float actuation = 0.0;
//if (isActuator){
// if (neighborAxis == 0 && wiring[1]>0.1){//>0
// actuation += 0.3*getActuatorVoltage(wiring[1]-1.0);
// } else if (neighborAxis == 1 && wiring[2]>0.1){
// actuation += 0.3*getActuatorVoltage(wiring[2]-1.0);
// } else if (neighborAxis == 2 && wiring[3]>0.1){
// actuation += 0.3*getActuatorVoltage(wiring[3]-1.0);
// }
//}
//vec4 neighborWiring = texture2D(u_wires, scaledNeighborIndex);
//if (neighborWiring[0] < -0.5){
// if (neighborAxis == 0 && neighborWiring[1]>0.1){
// actuation += 0.3*getActuatorVoltage(neighborWiring[1]-1.0);
// } else if (neighborAxis == 1 && neighborWiring[2]>0.1){
// actuation += 0.3*getActuatorVoltage(neighborWiring[2]-1.0);
// } else if (neighborAxis == 2 && neighborWiring[3]>0.1){
// actuation += 0.3*getActuatorVoltage(neighborWiring[3]-1.0);
// }
//}
//if (neighborAxis == 0) actuatedD[0] *= 1.0+actuation;
//else if (neighborAxis == 1) actuatedD[1] *= 1.0+actuation;
//else if (neighborAxis == 2) actuatedD[2] *= 1.0+actuation;
vec2 kIndex = vec2(((fragCoord.x-0.5)*12.0 + 2.0*(i*3.0+float(j)) + 0.5)/(u_textureDim.x*12.0), scaledFragCoord.y);
vec3 translationalK = texture2D(u_compositeKs, kIndex).xyz;
vec3 translationalD = texture2D(u_compositeDs, kIndex).xyz;
vec4 averageQuaternion = averageQuaternions(quaternion, neighborQuaternion);
vec4 averageQuaternionInverse = invertQuaternion(averageQuaternion);
vec3 translationalDelta = neighborTranslation - translation + nominalD - cellHalfNominalD - neighborHalfNominalD;
vec3 translationalDeltaXYZ = applyQuaternion(translationalDelta, averageQuaternionInverse);
vec3 velocityDelta = neighborVelocity-velocity;
vec3 velocityDeltaXYZ = applyQuaternion(velocityDelta, averageQuaternionInverse);
vec3 _force = translationalK*translationalDeltaXYZ + translationalD*velocityDeltaXYZ;
//convert _force vector back into world reference frame
_force = applyQuaternion(_force, averageQuaternion);
force += _force;
}
}
gl_FragColor = vec4(force/mass, 0);
}
\ No newline at end of file
......@@ -3,8 +3,9 @@ precision highp float;
uniform vec2 u_textureDim;
uniform float u_dt;
uniform sampler2D u_velocity;
uniform sampler2D u_acceleration;
uniform sampler2D u_lastTranslation;
uniform sampler2D u_lastLastTranslation;
uniform sampler2D u_mass;
void main(){
......@@ -18,9 +19,10 @@ void main(){
}
vec3 lastTranslation = texture2D(u_lastTranslation, scaledFragCoord).xyz;
vec3 velocity = texture2D(u_velocity, scaledFragCoord).xyz;
vec3 lastLastTranslation = texture2D(u_lastLastTranslation, scaledFragCoord).xyz;
vec3 acceleration = texture2D(u_acceleration, scaledFragCoord).xyz;
vec3 translation = lastTranslation + velocity*u_dt;
vec3 translation = 2.0*lastTranslation - lastLastTranslation + acceleration*u_dt*u_dt;