How to make a vertical wave with using canvas? - html5-canvas

I changed the script by adding text instead of an image.
I want to wave was vertically downwards. I know that a little editing but I tried different options and it did not work.
http://jsfiddle.net/7ynn4/3/
var options = {
period:100,
squeeze:0,
wavelength:40,
amplitude:30,
shading:300,
fps:30
}
var ca = document.getElementById('canvas');
var ctx = ca.getContext('2d');
ctx.canvas.width = 400;
ctx.canvas.height = 150;
ctx.font = 'bold 45pt Arial';
ctx.textAlign = 'center';
ctx.fillStyle = 'blue';
ctx.fillText('Hello World', 170, 60);
w = canvas.width,
h = canvas.height,
od = ctx.getImageData( 0, 0, w, h ).data;
setInterval(function() {
var id = ctx.getImageData( 0, 0, w, h ),
d = id.data,
now = ( new Date() )/options.period,
y,
x,
lastO,
shade,
sq = ( y - h/2 ) * options.squeeze,
px,
pct,
o,
y2,
opx;
for ( y = 0; y < h; y += 1 ) {
lastO = 0;
shade = 0;
sq = ( y - h/2 ) * options.squeeze;
for ( x = 0; x < w; x += 1 ) {
px = ( y * w + x ) * 4;
pct = x/w;
o = Math.sin( x/options.wavelength - now ) * options.amplitude * pct;
y2 = y + ( o + sq * pct ) << 0;
opx = ( y2 * w + x ) * 4;
shade = (o-lastO) * options.shading;
d[px ] = od[opx ]+shade;
d[px+1] = od[opx+1]+shade;
d[px+2] = od[opx+2]+shade;
d[px+3] = od[opx+3];
lastO = o;
}
}
ctx.putImageData( id, 0, 0 );
},
1000/options.fps
);

You just flip the values around so that x is affected instead of y -
... vars cut, but replace y2 with x2 ...
/// reversed from here
for (x = 0; x < w; x += 1) {
lastO = 0;
shade = 0;
sq = (x - w * 0.5) * options.squeeze;
for (y = 0; y < h; y += 1) {
px = (y * w + x) * 4;
pct = y / h;
o = Math.sin(y/options.wavelength-now) * options.amplitude * pct;
/// the important one: you might need to compensate here (-5)
x2 = x - 5 + (o + sq * pct) | 0;
opx = (x2 + y * w) * 4;
shade = (o - lastO) * options.shading;
d[px] = od[opx] + shade;
d[px + 1] = od[opx + 1] + shade;
d[px + 2] = od[opx + 2] + shade;
d[px + 3] = od[opx + 3];
lastO = o;
}
}
ctx.putImageData(id, 0, 0);
MODIFIED FIDDLE HERE

Related

How to implement snapping effect and collision detection between two objects using Threejs?

We are able to detect the collision but could not implement a snapping/magnetic effect like Snap edges of objects to each other and prevent overlap
we need help with 3D objects here and we are using Vec3 for the active object's position.
With the following approach, collision detection is working perfectly for all cases, and magnetic effect is somehow working - not perfectly.
It's working well when the object is moving along x or z-axis but when the object's movement is in diagonal direction (moving along x and z-axis simultaneously) that is where the problem comes.
Though am not satisfied with the following approach that's why am looking for new approach to implement both magnetic and collision detection features.
It is not necessary to have the solution in Threejs, any general solution or algorithm of coordinates can be converted into Threejs.
let collide = this.detectCollisionCubes(activeObject, collidingObject, vec3);
let magneticEffect = new MagneticEffect(activeObject, vec3, collidingObject);
vec3 = magneticEffect.setNewPosition();
activeObject.position.copy(vec3);
detectCollisionCubes = function(a, d, vec3){
// a is active object's positon
// d is colliding object
let aHeight = Math.abs(a.getHeight());
let aWidth = Math.abs(a.getWidth());
let aDepth = Math.abs(a.getDepth());
let b1 = vec3.y - aHeight / 2;
let t1 = vec3.y + aHeight / 2;
let r1 = vec3.x + aWidth / 2;
let l1 = vec3.x - aWidth / 2;
let f1 = vec3.z - aDepth / 2;
let B1 = vec3.z + aDepth / 2;
let dHeight = Math.abs(d.getHeight());
let dWidth = Math.abs(d.getWidth());
let dDepth = Math.abs(d.getDepth());
let b2 = d.position.y - dHeight / 2;
let t2 = d.position.y + dHeight / 2;
let r2 = d.position.x + dWidth / 2;
let l2 = d.position.x - dWidth / 2;
let f2 = d.position.z - dDepth / 2;
let B2 = d.position.z + dDepth / 2;
if (t1 < b2 || r1 < l2 || b1 > t2 || l1 > r2 || f1 > B2 || B1 < f2) {
return false;
}
return true;
}
Trying to create magnetic effect via
this.currentObject = currentObject;
this.collisionObject = collisionObject;
this.collisionType = null;
this.objectType = null;
this.currentPosition = currentPosition;
this.currentObjectHeight = Math.abs(currentObject.getHeight());
this.currentObjectWidth = Math.abs(currentObject.getWidth());
this.collisionObjectHeight = Math.abs(collisionObject.getHeight());
this.collisionObjectWidth = Math.abs(collisionObject.getWidth());
this.collisionObjectDepth = Math.abs(collisionObject.getDepth());
this.objectTop = currentObject.position.y + (this.currentObjectHeight/2);
this.objectBottom = currentObject.position.y - (this.currentObjectHeight/2);
this.collideTop = collisionObject.position.y + (this.collisionObjectHeight/2);
this.collideBottom = collisionObject.position.y - (this.collisionObjectHeight/2);
this.zAxisDifference = Math.abs(Math.abs(currentPosition.z) - Math.abs(collisionObject.position.z));
this.xAxisDifference = Math.abs(Math.abs(currentPosition.x) - Math.abs(collisionObject.position.x));
// Extra code here
if (
this.objectTop < this.collideBottom
) {
this.collisionType = collisionTypes.verticalBottom;
} else if (
this.objectBottom > this.collideTop
) {
this.collisionType = collisionTypes.verticalTop;
} else if (
this.currentPosition.x > this.collisionObject.position.x &&
this.zAxisDifference < 2
) {
this.collisionType = collisionTypes.horizentalXLeft;
} else if (
this.currentPosition.x < this.collisionObject.position.x &&
this.zAxisDifference < 2
) {
this.collisionType = collisionTypes.horizentalXRight;
} else if (
this.currentPosition.z > this.collisionObject.position.z &&
this.xAxisDifference < 2
) {
this.collisionType = collisionTypes.horizentalZLeft;
} else if (
this.currentPosition.z < this.collisionObject.position.z &&
this.xAxisDifference < 2
) {
this.collisionType = collisionTypes.horizentalZRight;
}
MagneticEffect.prototype.setNewPosition = function () {
if (this.collisionType === collisionTypes.verticalBottom) {
this.currentPosition.y = this.collideBottom + 0.5;
} else if (this.collisionType === collisionTypes.verticalTop) {
this.currentPosition.y = this.collideTop - 0.5;
} else if (this.collisionType === collisionTypes.horizentalXRight) {
this.currentPosition.x = this.collisionObject.position.x - this.collisionObjectWidth - 0.5;
} else if (this.collisionType === collisionTypes.horizentalXLeft) {
this.currentPosition.x = this.collisionObject.position.x + this.collisionObjectWidth + 0.5;
} else if (this.collisionType === collisionTypes.horizentalZRight) {
this.currentPosition.z = this.collisionObject.position.z - this.collisionObjectWidth - 0.5;
} else if (this.collisionType === collisionTypes.horizentalZLeft) {
this.currentPosition.z = this.collisionObject.position.z + this.collisionObjectWidth + 0.5;
}
return this.currentPosition;
};

Halide JIT vs Generator Differences

While playing around with Halide, I see that totally different pseudocodes are created for a same pipline when using JIT and a generated function approaches. It looks like I'm missing something and so I'd very appreciate and hint. Here is what I did:
A simple 'dilate' pipline is defined as:
int jit_main ()
{
Target target = get_jit_target_from_environment ();
const int width = 1280, height = 1024;
Buffer <uint8_t> input (width, height);
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
input (x, y) = rand () & 0xff;
Var x ("x_1"), y ("y_1");
Func clamped ("clamped_1");
clamped = BoundaryConditions::repeat_edge (input);
Func max_x ("max_x_1");
max_x (x, y) = max (clamped (x - 1, y), clamped (x, y), clamped (x + 1, y));
Func dilate ("dilate_1");
dilate (x, y) = max (max_x (x, y - 1), max_x (x, y), max_x (x, y + 1));
tick (NULL);
Buffer<uint8_t> out = dilate.realize (width, height, target);
tick ("inline");
dilate.print_loop_nest ();
dilate.compile_to_lowered_stmt ("dilate_1_.html", {}, HTML);
}
The resulting pseudocode looks as follows (fragment):
produce dilate_1 {
let t125 = ((dilate_1.min.1 * dilate_1.stride.1) + dilate_1.min.0)
for (dilate_1.s0.y_1, dilate_1.min.1, dilate_1.extent.1) {
let t128 = max(min(dilate_1.s0.y_1, 1024), 1)
let t126 = max(min(dilate_1.s0.y_1, 1023), 0)
let t127 = max(min(dilate_1.s0.y_1, 1022), -1)
let t129 = ((dilate_1.s0.y_1 * dilate_1.stride.1) - t125)
for (dilate_1.s0.x_1, dilate_1.min.0, dilate_1.extent.0) {
dilate_1[(dilate_1.s0.x_1 + t129)] = max(b0[((max(min(dilate_1.s0.x_1, 1278), -1) + (t126 * 1280)) + 1)], max(b0[(max(min(dilate_1.s0.x_1, 1279), 0) + (t126 * 1280))], max(b0[((max(min(dilate_1.s0.x_1, 1280), 1) + (t126 * 1280)) + -1)], max(b0[((max(min(dilate_1.s0.x_1, 1280), 1) + (t127 * 1280)) + 1279)], max(b0[((max(min(dilate_1.s0.x_1, 1279), 0) + (t127 * 1280)) + 1280)], max(b0[((max(min(dilate_1.s0.x_1, 1278), -1) + (t127 * 1280)) + 1281)], max(b0[((max(min(dilate_1.s0.x_1, 1280), 1) + (t128 * 1280)) + -1281)], max(b0[((max(min(dilate_1.s0.x_1, 1279), 0) + (t128 * 1280)) + -1280)], b0[((max(min(dilate_1.s0.x_1, 1278), -1) + (t128 * 1280)) + -1279)]))))))))
}
}
}
Then I defined a generator:
class Dilate0Generator : public Halide::Generator <Dilate0Generator>
{
public:
Input<Buffer<uint8_t>> input_0 {"input_0", 2};
Output<Buffer<uint8_t>> dilate_0 {"dilate_0", 2};
Var x {"x_0"}, y {"y_0"};
void generate ()
{
Func clamped_0 {"clamped_0"};
clamped_0 = BoundaryConditions::repeat_edge (input_0);
Func max_x_0 {"max_x_0"};
max_x_0 (x, y) =
max (clamped_0 (x - 1, y), clamped_0 (x, y), clamped_0 (x + 1, y));
dilate_0 (x, y) =
max (max_x_0 (x, y - 1), max_x_0 (x, y), max_x_0 (x, y + 1));
dilate_0.print_loop_nest ();
}
};
HALIDE_REGISTER_GENERATOR (Dilate0Generator, dilate_0)
And it's pseudocode is completely different (fragment):
produce dilate_0 {
let dilate_0.s0.y_0.prologue = min(max((input_0.min.1 + 1), dilate_0.min.1), (dilate_0.extent.1 + dilate_0.min.1))
let dilate_0.s0.y_0.epilogue$3 = min(max(max((input_0.min.1 + 1), dilate_0.min.1), ((input_0.extent.1 + input_0.min.1) + -1)), (dilate_0.extent.1 + dilate_0.min.1))
let t166 = (dilate_0.s0.y_0.prologue - dilate_0.min.1)
let t168 = ((input_0.min.1 * input_0.stride.1) + input_0.min.0)
let t170 = ((dilate_0.min.1 * dilate_0.stride.1) + dilate_0.min.0)
let t167 = (input_0.extent.1 + input_0.min.1)
let t169 = (input_0.extent.0 + input_0.min.0)
for (dilate_0.s0.y_0, dilate_0.min.1, t166) {
let t171 = ((max(min((t167 + -1), dilate_0.s0.y_0), input_0.min.1) * input_0.stride.1) - t168)
let t173 = ((max((min((dilate_0.s0.y_0 + 2), t167) + -1), input_0.min.1) * input_0.stride.1) - t168)
let t174 = ((max((min(dilate_0.s0.y_0, t167) + -1), input_0.min.1) * input_0.stride.1) - t168)
let t175 = ((dilate_0.s0.y_0 * dilate_0.stride.1) - t170)
for (dilate_0.s0.x_0, dilate_0.min.0, dilate_0.extent.0) {
dilate_0[(dilate_0.s0.x_0 + t175)] = (let t132 = max((min((dilate_0.s0.x_0 + 2), t169) + -1), input_0.min.0) in (let t133 = max(min((t169 + -1), dilate_0.s0.x_0), input_0.min.0) in (let t134 = max((min(dilate_0.s0.x_0, t169) + -1), input_0.min.0) in max(input_0[(t132 + t171)], max(input_0[(t133 + t171)], max(input_0[(t134 + t171)], max(input_0[(t134 + t173)], max(input_0[(t133 + t173)], max(input_0[(t132 + t173)], max(input_0[(t134 + t174)], max(input_0[(t133 + t174)], input_0[(t132 + t174)])))))))))))
}
}
let t183 = (dilate_0.extent.0 + dilate_0.min.0)
let t184 = (input_0.extent.0 + input_0.min.0)
let t185 = max((input_0.min.0 + 1), dilate_0.min.0)
let t178 = min(max((t184 + -1), t185), t183)
let t177 = min(t183, t185)
let t176 = (dilate_0.s0.y_0.epilogue$3 - dilate_0.s0.y_0.prologue)
let t179 = ((input_0.min.1 * input_0.stride.1) + input_0.min.0)
let t181 = ((dilate_0.min.1 * dilate_0.stride.1) + dilate_0.min.0)
for (dilate_0.s0.y_0, dilate_0.s0.y_0.prologue, t176) {
let t189 = (((dilate_0.s0.y_0 + 1) * input_0.stride.1) - t179)
let t190 = (((dilate_0.s0.y_0 + -1) * input_0.stride.1) - t179)
let t187 = ((dilate_0.s0.y_0 * input_0.stride.1) - t179)
let t191 = ((dilate_0.s0.y_0 * dilate_0.stride.1) - t181)
let t186 = (t177 - dilate_0.min.0)
for (dilate_0.s0.x_0, dilate_0.min.0, t186) {
dilate_0[(dilate_0.s0.x_0 + t191)] = (let t140 = max((min((dilate_0.s0.x_0 + 2), t184) + -1), input_0.min.0) in (let t141 = max(min((t184 + -1), dilate_0.s0.x_0), input_0.min.0) in (let t142 = max((min(dilate_0.s0.x_0, t184) + -1), input_0.min.0) in max(input_0[(t140 + t187)], max(input_0[(t141 + t187)], max(input_0[(t142 + t187)], max(input_0[(t142 + t189)], max(input_0[(t141 + t189)], max(input_0[(t140 + t189)], max(input_0[(t142 + t190)], max(input_0[(t141 + t190)], input_0[(t140 + t190)])))))))))))
}
let t194 = (((dilate_0.s0.y_0 + 1) * input_0.stride.1) - t179)
let t195 = (((dilate_0.s0.y_0 + -1) * input_0.stride.1) - t179)
let t193 = ((dilate_0.s0.y_0 * input_0.stride.1) - t179)
let t196 = ((dilate_0.s0.y_0 * dilate_0.stride.1) - t181)
let t192 = (t178 - t177)
for (dilate_0.s0.x_0, t177, t192) {
dilate_0[(dilate_0.s0.x_0 + t196)] = max(input_0[((dilate_0.s0.x_0 + t193) + 1)], max(input_0[(dilate_0.s0.x_0 + t193)], max(input_0[((dilate_0.s0.x_0 + t193) + -1)], max(input_0[((dilate_0.s0.x_0 + t194) + -1)], max(input_0[(dilate_0.s0.x_0 + t194)], max(input_0[((dilate_0.s0.x_0 + t194) + 1)], max(input_0[((dilate_0.s0.x_0 + t195) + -1)], max(input_0[(dilate_0.s0.x_0 + t195)], input_0[((dilate_0.s0.x_0 + t195) + 1)]))))))))
}
let t200 = (((dilate_0.s0.y_0 + 1) * input_0.stride.1) - t179)
let t201 = (((dilate_0.s0.y_0 + -1) * input_0.stride.1) - t179)
let t198 = ((dilate_0.s0.y_0 * input_0.stride.1) - t179)
let t202 = ((dilate_0.s0.y_0 * dilate_0.stride.1) - t181)
let t197 = (t183 - t178)
for (dilate_0.s0.x_0, t178, t197) {
dilate_0[(dilate_0.s0.x_0 + t202)] = (let t152 = max((min((dilate_0.s0.x_0 + 2), t184) + -1), input_0.min.0) in (let t153 = max(min((t184 + -1), dilate_0.s0.x_0), input_0.min.0) in (let t154 = max((min(dilate_0.s0.x_0, t184) + -1), input_0.min.0) in max(input_0[(t152 + t198)], max(input_0[(t153 + t198)], max(input_0[(t154 + t198)], max(input_0[(t154 + t200)], max(input_0[(t153 + t200)], max(input_0[(t152 + t200)], max(input_0[(t154 + t201)], max(input_0[(t153 + t201)], input_0[(t152 + t201)])))))))))))
}
}
let t203 = ((dilate_0.extent.1 + dilate_0.min.1) - dilate_0.s0.y_0.epilogue$3)
let t205 = ((input_0.min.1 * input_0.stride.1) + input_0.min.0)
let t207 = ((dilate_0.min.1 * dilate_0.stride.1) + dilate_0.min.0)
let t204 = (input_0.extent.1 + input_0.min.1)
let t206 = (input_0.extent.0 + input_0.min.0)
for (dilate_0.s0.y_0, dilate_0.s0.y_0.epilogue$3, t203) {
let t208 = ((max(min((t204 + -1), dilate_0.s0.y_0), input_0.min.1) * input_0.stride.1) - t205)
let t210 = ((max((min((dilate_0.s0.y_0 + 2), t204) + -1), input_0.min.1) * input_0.stride.1) - t205)
let t211 = ((max((min(dilate_0.s0.y_0, t204) + -1), input_0.min.1) * input_0.stride.1) - t205)
let t212 = ((dilate_0.s0.y_0 * dilate_0.stride.1) - t207)
for (dilate_0.s0.x_0, dilate_0.min.0, dilate_0.extent.0) {
dilate_0[(dilate_0.s0.x_0 + t212)] = (let t161 = max((min((dilate_0.s0.x_0 + 2), t206) + -1), input_0.min.0) in (let t162 = max(min((t206 + -1), dilate_0.s0.x_0), input_0.min.0) in (let t163 = max((min(dilate_0.s0.x_0, t206) + -1), input_0.min.0) in max(input_0[(t161 + t208)], max(input_0[(t162 + t208)], max(input_0[(t163 + t208)], max(input_0[(t163 + t210)], max(input_0[(t162 + t210)], max(input_0[(t161 + t210)], max(input_0[(t163 + t211)], max(input_0[(t162 + t211)], input_0[(t161 + t211)])))))))))))
}
}
}
The generated version runs in an order of magnitude faster, which is not surprising, given that the pseudocode for it looks a lot more optimized.
It runs even faster that an existed example
My noob question is how comes that JIT can not create the same representation?
Thanks a lot for any answer/idea/help/hint...
The difference between the two is that in the JIT case, the size of the input (and thus the location of the boundary condition) is known at compile-time.
However the generated code should be similar. I think the fact that you don't get five separate cases in the JIT case is a bug in Halide. I have opened an issue on the Halide github repo.
https://github.com/halide/Halide/issues/5353
EDIT: Thanks for uncovering a bug! Fixed in https://github.com/halide/Halide/pull/5355

Particle system running slowly

here is update function. As soon as i turn update on my program gets slower. I'm not even able to render 25000 particles at a time. Voxels is a 3 dimensional array. How to i change my update function so that the calculations is done faster. i want to able to render at least 100000 particles.
function update(){
newTime = Date.now();
elapsedTime = newTime - oldTime;
oldTime = newTime;
for(var index =0 ; index < particles.vertices.length; index++){
//particle's old position
var oldPosition = particles.vertices[index];
//making sure particles do not og out of boundary
if (oldPosition.x > screenSquareLength || oldPosition.x < -screenSquareLength){
oldPosition.x = 2 * screenSquareLength * Math.random() - screenSquareLength;
}
if (oldPosition.y > screenSquareLength || oldPosition.y < -screenSquareLength){
oldPosition.y = 2 * screenSquareLength * Math.random() - screenSquareLength;
}
if (oldPosition.z > screenSquareDepth/2 || oldPosition.z < -screenSquareDepth/2){
oldPosition.z = screenSquareDepth * Math.random() - screenSquareDepth/2;
}
var oldVelocity = particlesExtraInfo[index].velocity;
var fieldVelocity;
var xIndex, yIndex, zIndex;
try{
//calculating index of voxel
xIndex = Math.floor(( oldPosition.x + screenSquareLength ) / voxelSize);
yIndex = Math.floor(( oldPosition.y + screenSquareLength ) / voxelSize);
zIndex = Math.floor(( screenSquareDepth / 2 - oldPosition.z) / voxelSize);
//getting velocity, color for particle and if voxel is
fieldVelocity = voxels[zIndex][xIndex][yIndex].userData["velocity"];
particleColor = voxels[zIndex][xIndex][yIndex].userData["color"];
activeVoxel = voxels[zIndex][xIndex][yIndex].userData["visible"];
}catch (e){
console.log("indexX = "+xIndex + " \t Yindex = "+ yIndex+" \t zIndex = "+ zIndex);
}
var particleColor;
var activeVoxel;
try{
var vx = ((oldVelocity.x + fieldVelocity.x) * elapsedTime);
var vy = ((oldVelocity.y + fieldVelocity.y) * elapsedTime);
var vz = ((oldVelocity.z + fieldVelocity.z) * elapsedTime);
var magnitude = Math.abs(vx) + Math.abs(vy) + Math.abs(vz); //Math.sqrt(vx*vx + vy*vy+ vz*vz);
var normalized = new THREE.Vector3(vx / magnitude, vy / magnitude, vz / magnitude);
if((particles.vertices[index].x < 0.1 && particles.vertices[index].x > -0.1) && (particles.vertices[index].y < 0.1 && particles.vertices[index].y > -0.1) && (particles.vertices[index].z < 0.1 && particles.vertices[index].z > -0.1) ){
particles.vertices[index].x = 2 * screenSquareLength * Math.random() - screenSquareLength;;
particles.vertices[index].y = 2 * screenSquareLength * Math.random() - screenSquareLength;;
particles.vertices[index].z = 2 * screenSquareLength * Math.random() - screenSquareLength;;
}
//if voxel is not part of the model update particle postion and velocity
if( activeVoxel == 0){
particles.colors[index] = new THREE.Color(particleColor);//new THREE.Color(0, 0, 1);
particles.colorsNeedUpdate = true;
particles.vertices[index].x += normalized.x/slowingFactor;
particles.vertices[index].y += normalized.y/slowingFactor;
particles.vertices[index].z += normalized.z/slowingFactor;
particles.verticesNeedUpdate = true;
particlesExtraInfo[index].velocity = normalized;
}else{
//voxel is part of particle so update color property of particle
particles.colors[index] = new THREE.Color(0, 0, 1);
particles.colorsNeedUpdate = true;
particles.vertices[index].x += normalized.x/(slowingFactor * 200);
particles.vertices[index].y += normalized.y/(slowingFactor * 200);
particles.vertices[index].z += normalized.z/(slowingFactor * 200);
particles.verticesNeedUpdate = true;
particlesExtraInfo[index].velocity = new THREE.Vector3( normalized.x/slowingFactor, normalized.y/slowingFactor, normalized.z/slowingFactor );
}
}catch(e){
}
}
}
I don't know much about what exactly happens when you update a buffer like this, but I know that it can be slow.
While 25k may be a lot for what you're trying to do (i experimented with 5k and had trouble) there is no reason why you can't optimize your JS before trying to move everything to the gpu (for example).
var foo = 0;
foo+= normalized.x / someFactor;
//better done this way:
var invSomeFactor = 1/someFactor;
// now you avoid dividing the same thing many times in your loop
foo += normalized.x * invSomeFactor;
Math.random() is pretty expensive, you could make a look up table (a large one) and fetch these precomputed values from it.
var myLookupTable = [];
var MAX_VALUES = 2048;
for ( var i = 0 ; i < MAX_VALUES ; i ++ ){
myLookupTable.push(Math.random());
}
//and then you can have a stride for example
var RAND_STRIDE = 0;
//and in the loop
someVec.x += something.x * myLookupTable[ RAND_STRIDE ++ ];
RAND_STRIDE %= MAX_VALUES; //read from the beginning
Finally, you can write a fragment shader, that would read from a buffer, and write into another buffer doing all this logic in the process. Each fragment is your particle and once you run this pass and compute your positions, you need to be able to read the buffer in your particle vertex shader and just assign those positions.

Convert Euler to Heun (improved Euler)

I already have implemented Euler method in Mathematica.
Now I want to convert this method to Heun method (improved Euler).
I have this Euler implementation:
a = 2;(*my a parameter*)
b = .01; (*my b parameter*)
x = 0; (*starting x value*)
p = 1; (*starting p value*)
t = 1; (*step size t*)
f[p_] := a p - b p^2; (*my function*)
f[0] = 1;
eulertable = {}; (*build table (x,p).n steps in loop*)
For[n = 1,
n <= 21, n++,
AppendTo[eulertable, {x, p}];
p = p + t f[p];
x = x + t;]
Now I want to implement this with the Heun method. I already have this implementation of the Heun method.
heun[f_, {x_, x0_, xn_}, {y_, y0_}, steps_] :=
Block[{ xold = x0, yold = y0, sollist = {{x0, y0}}, x, y, h },
h = N[(xn - x0) / steps];
Do[ xnew = xold + h;
k1 = h * (f /. {x -> xold, y -> yold});
k2 = h * (f /. {x -> xold + h, y -> yold + k1});
ynew = yold + .5 * (k1 + k2);
sollist = Append[sollist, {xnew, ynew}];
xold = xnew;
yold = ynew,
{steps}
];
Return[sollist]
]
But I need to convert this method to have the input like it is in my Euler method. So I have to convert the Heun method that I have the parameter a, b, x, t, p, f[].
As I am new with Mathematica I am having problems to convert the method.
Why do you put f[0]=1?
Replace
p = p + t f[p];
x = x + t;
with
p1 = p + t f[p];
p2 = p + t f[p1];
p = (p1+p2)/2;
x = x + t;
Your step size is rather large for the values of your parameters.

Find the distance from camera to vanishing point in matlab

I have this program that finds the vanishing point for a given set of images. Is there a way to find the distance from the camera and the vanishing point?
Also once the vanishing point is found out, I manually need to find the X and Y coordinates using the tool provided in matlab. How can i code a snippet that writes all the X and Y coordinates into a text or excel file?
Also is there a better and simpler way to find the vanishing point in matlab?
Matlab Calling Function to find Vanishing Point:
clear all; close all;
dname = 'Height';
files = dir(dname);
files(1) = [];
files(1) = [];
for i=1:size(files, 1)
original = imread(fullfile(dname, files(i).name));
original = imresize(original,0.35);
im = im2double(rgb2gray(original));
[row, col] = findVanishingPoint(im);
imshow(original);hold;plot(col,row,'rx');
saveas(gcf,strcat('Height_Result',num2str(i)),'jpg');
close
end
The findVanishingPoint function:
function [row, col] = findVanishingPoint(im)
DEBUG = 0;
IM = fft2(im);
ROWS = size(IM,1); COLS = size(IM,2);
PERIOD = 2^floor(log2(COLS)-5)+2;
SIZE = floor(10*PERIOD/pi);
SIGMA = SIZE/9;
NORIENT = 72;
E = 8;
[C, S] = createGaborBank(SIZE, PERIOD, SIGMA, NORIENT, ROWS, COLS, E);
D = ones(ROWS, COLS);
AMAX = ifftshift(real(ifft2(C{1}.*IM)).^2+real(ifft2(S{1}.*IM))).^2;
for n=2:NORIENT
A = ifftshift(real(ifft2(C{n}.*IM)).^2+real(ifft2(S{n}.*IM))).^2;
D(find(A > AMAX)) = n;
AMAX = max(A, AMAX);
if (DEBUG==1)
colormap('hot');subplot(131);imagesc(real(A));subplot(132);imagesc(real(AMAX));colorbar;
subplot(133);imagesc(D);
pause
end
end
if (DEBUG==2)
figure('DoubleBuffer','on');
end
T = mean(AMAX(:))-3*std(AMAX(:));
VOTE = zeros(ROWS, COLS);
for row=round(1+SIZE/2):round(ROWS-SIZE/2)
for col=round(1+SIZE/2):round(COLS-SIZE/2)
if (AMAX(row,col) > T)
indices = lineBresenham(ROWS, COLS, col, row, D(row, col)*pi/NORIENT-pi/2);
VOTE(indices) = VOTE(indices)+AMAX(row,col);
end
end
if (DEBUG==2)
colormap('hot');imagesc(VOTE);pause;
end
end
if (DEBUG==2)
close
end
M=1;
[b index] = sort(-VOTE(:));
col = floor((index(1:M)-1) / ROWS)+1;
row = mod(index(1:M)-1, ROWS)+1;
col = round(mean(col));
row = round(mean(row));
The creatGaborBank function:
function [C, S] = createGaborBank(SIZE, PERIOD, SIGMA, NORIENT, ROWS, COLS, E)
if (length(NORIENT)==1)
orientations=[1:NORIENT];
else
orientations = NORIENT;
NORIENT = max(orientations);
end
for n=orientations
[C{n}, S{n}] = gabormask(SIZE, SIGMA, PERIOD, n*pi/NORIENT);
C{n} = fft2(padWithZeros(C{n}, ROWS, COLS));
S{n} = fft2(padWithZeros(S{n}, ROWS, COLS));
end
The gabormask function:
function [cmask, smask] = gabormask(Size, sigma, period, orient, E)
if nargin < 5; E = 8; end;
if nargin < 4; orient = 0; end;
if nargin < 3; period = []; end;
if nargin < 2; sigma = []; end;
if nargin < 1; Size = []; end;
if isempty(period) & isempty(sigma); sigma = 5; end;
if isempty(period); period = sigma*2*sqrt(2); end;
if isempty(sigma); sigma = period/(2*sqrt(2)); end;
if isempty(Size); Size = 2*round(2.575*sigma) + 1; end;
if length(Size) == 1
sx = Size-1; sy = sx;
elseif all(size(Size) == [1 2])
sy = Size(1)-1; sx = Size(2)-1;
else
error('Size must be scalar or 1-by-2 vector');
end;
hy = sy/2; hx = sx/2;
[x, y] = meshgrid(-hx:sx-hx, -hy:sy-hy);
omega = 2*pi/period;
cs = omega * cos(orient);
sn = omega * sin(orient);
k = -1/(E*sigma*sigma);
g = exp(k * (E*x.*x + y.*y));
xp = x * cs + y * sn;
cx = cos(xp);
cmask = g .* cx;
sx = sin(xp);
smask = g .* sx;
cmask = cmask - mean(cmask(:));
cmask = cmask/sum(abs(cmask(:)));
smask = smask - mean(smask(:));
smask = smask/sum(abs(smask(:)));
The padWithZeros function:
function out = padWithZeros(in, ROWS, COLS)
out = padarray(in,[floor((ROWS-size(in,1))/2) floor((COLS-size(in,2))/2)],0,'both');
if size(out,1) == ROWS-1
out = padarray(out,[1 0],0,'pre');
end
if size(out,2) == COLS-1
out = padarray(out,[0 1],0,'pre');
end
The findHorizonEdge function:
function row = findHorizon(im)
DEBUG = 2;
ROWS = size(im,1); COLS = size(im,2);
e = edge(im,'sobel', [], 'horizontal');
dd = sum(e, 2);
N=3;
row = 1;
M = 0;
for i=1+N:length(dd)-N
m = sum(dd(i-N:i+N));
if (m > M)
M = m;
row = i;
end
end
imshow(e);pause
The findHorizon function:
function row = findHorizon(im)
DEBUG = 2;
IM = fft2(im);
ROWS = size(IM,1); COLS = size(IM,2);
PERIOD = 2^floor(log2(COLS)-5)+2;
SIZE = floor(10*PERIOD/pi);
SIGMA = SIZE/9;
NORIENT = 72;
E = 16;
orientations = [NORIENT/2-10:NORIENT/2+10];
[C, S] = createGaborBank(SIZE, PERIOD, SIGMA, orientations, ROWS, COLS, E);
ASUM = zeros(ROWS, COLS);
for n=orientations
A = ifftshift(real(ifft2(C{n}.*IM)).^2+real(ifft2(S{n}.*IM))).^2;
ASUM = ASUM + A;
if (DEBUG==1)
colormap('hot');subplot(131);imagesc(real(A));subplot(132);imagesc(real(AMAX));colorbar;
pause
end
end
ASUM(1:round(1+SIZE/2), :)=0; ASUM(end-round(SIZE/2):end, :)=0;
ASUM(:,end-round(SIZE/2):end)=0; ASUM(:, 1:1+round(SIZE/2))=0;
dd = sum(ASUM, 2);
[temp, row] = sort(-dd);
row = round(mean(row(1:10)));
if (DEBUG == 2)
imagesc(ASUM);hold on;line([1:COLS],repmat(row,COLS));
pause
end
The lineImage function:
function v = lineimage(x0, y0, angle, s)
if (abs(tan(angle)) > 1e015)
a(1,:) = repmat(x0,s(1),1)';
a(2,:) = [1:s(1)];
elseif (abs(tan(angle)) < 1e-015)
a(2,:) = repmat(y0,s(2),1)';
a(1,:) = [1:s(2)];
else
k = tan(angle);
hiX = round((1-(s(1)-y0+1)+k*x0)/k);
loX = round((s(1)-(s(1)-y0+1)+k*x0)/k);
temp = max(loX, hiX);
loX = max(min(loX, hiX), 1);
hiX = min(s(2),temp);
a(1,:) = [loX:hiX];
a(2,:) = max(1, floor(s(1)-(k*a(1,:)+(s(1)-y0+1)-k*x0)));
end
v = (a(1,:)-1).*s(1)+a(2,:);
The lineVector function:
function [abscissa, ordinate] = linevector(x0, y0, angle, s)
if (rad2deg(angle) == 90)
abscissa = repmat(x0,s(1),1);
ordinate = [1:s(1)];
else
k = tan(angle);
hiX = round((1-(s(1)-y0+1)+k*x0)/k);
loX = round((s(1)-(s(1)-y0+1)+k*x0)/k);
temp = max(loX, hiX);
loX = max(min(loX, hiX), 1);
hiX = min(s(2),temp);
abscissa = [loX:hiX];
ordinate = k*abscissa+((s(1)-y0+1)-k*x0);
end
The lineBresenham function:
function [i] = lineBresenham(H,W,Sx,Sy,angle)
k = tan(angle);
if (angle == pi || angle == 0)
Ex = W;
Ey = Sy;
Sx = 1;
elseif (angle == pi/2)
Ey = 1;
i = (Sx-1)*H+[Ey:Sy];
return;
elseif k>0 & k < (Sy-1)/(W-Sx)
Ex = W;
Ey = round(Sy-tan(angle)*(Ex-Sx));
elseif k < 0 & abs(k) < (Sy-1)/(Sx-1)
Ex = 1;
Ey = round(Sy-tan(angle)*(Ex-Sx));
else
Ey = 1;
Ex = round((Sy-1)/tan(angle)+Sx);
end
Dx = Ex - Sx;
Dy = Ey - Sy;
iCoords=1;
if(abs(Dy) <= abs(Dx))
if(Ex >= Sx)
D = 2*Dy + Dx;
IncH = 2*Dy;
IncD = 2*(Dy + Dx);
X = Sx;
Y = Sy;
i(iCoords) = (Sx-1)*H+Sy;
iCoords = iCoords + 1;
while(X < Ex)
if(D >= 0)
D = D + IncH;
X = X + 1;
else
D = D + IncD;
X = X + 1;
Y = Y - 1;
end
i(iCoords) = (X-1)*H+Y;
iCoords = iCoords + 1;
end
else
D = -2*Dy + Dx;
IncH = -2*Dy;
IncD = 2*(-Dy + Dx);
X = Sx;
Y = Sy;
i(iCoords) = (Sx-1)*H+Sy;
iCoords = iCoords + 1;
while(X > Ex)
if(D <= 0)
D = D + IncH;
X = X - 1;
else
D = D + IncD;
X = X - 1;
Y = Y - 1;
end
i(iCoords) = (X-1)*H+Y;
iCoords = iCoords + 1;
end
end
else
Tmp = Ex;
Ex = Ey;
Ey = Tmp;
Tmp = Sx;
Sx = Sy;
Sy = Tmp;
Dx = Ex - Sx;
Dy = Ey - Sy;
if(Ex >= Sx)
D = 2*Dy + Dx;
IncH = 2*Dy;
IncD = 2*(Dy + Dx);
X = Sx;
Y = Sy;
i(iCoords) = (Sy-1)*H+Sx;
iCoords = iCoords + 1;
while(X < Ex)
if(D >= 0)
D = D + IncH;
X = X + 1;
else
D = D + IncD;
X = X + 1;
Y = Y - 1;
end
i(iCoords) = (Y-1)*H+X;
iCoords = iCoords + 1;
end
else
D = -2*Dy + Dx;
IncH = -2*Dy;
IncD = 2*(-Dy + Dx);
X = Sx;
Y = Sy;
i(iCoords) = (Sy-1)*H+Sx;
iCoords = iCoords + 1;
while(X > Ex)
if(D <= 0)
D = D + IncH;
X = X - 1;
else
D = D + IncD;
X = X - 1;
Y = Y - 1;
end
i(iCoords) = (Y-1)*H+X;
iCoords = iCoords + 1;
end
end
end
The vanishing point is at infinity hence the distance to the camera is of no use.
Use xlswrite or dlmwrite to write into excel or text file respectively.

Resources