I would like to simulate gravitation between particles, but I think I forgot something? - math

So, for each star, i compare this one to all other stars to calculate his speed, velocity, etc.
But that didn't work, I'm not too strong in maths and I think my formula is maybe wrong? idk why that didn't work here my code :
//for each star I compare to all other stars
for(let i = 0; i < pos.length; i ++) {
for (let j = 0; j < pos.length; j ++){
if (i !== j){
// Formula part
const vector = compute_interaction(pos[i], pos[j], 1.0);
accelerations[i].x += vector.x;
accelerations[i].y += vector.y;
accelerations[i].z += vector.z;
break;
}
}
}
for (let i = 0 ; i<accelerations.length ; i++){
speedStars[i].x += accelerations[i].x * 0.001;
speedStars[i].y += accelerations[i].y * 0.001;
speedStars[i].z += accelerations[i].z * 0.001;
}
for (let i = 0 ; i<speedStars.length ; i++){
const i3 = i*3;
starsPositions[i3] += speedStars[i].x * 0.001;
starsPositions[i3 + 1] += speedStars[i].y * 0.001;
starsPositions[i3 + 2] += speedStars[i].z * 0.001;
}
function compute_interaction(currentPosition, positionOtherStar, smoothing_length)
{
const vector = new THREE.Vector3(positionOtherStar.x - currentPosition.x, positionOtherStar.y - currentPosition.y, positionOtherStar.z - currentPosition.z).normalize();
let x = vector.x / (Math.pow(positionOtherStar.x,2.0) - Math.pow(currentPosition.x,2.0)+ smoothing_length)
let y = vector.y / (Math.pow(positionOtherStar.y,2.0) - Math.pow(currentPosition.y,2.0)+ smoothing_length)
let z = vector.z / (Math.pow(positionOtherStar.z,2.0) - Math.pow(currentPosition.z,2.0)+ smoothing_length)
return new THREE.Vector3(x, y, z);
}
Here the CodePen: https://codepen.io/n0rvel/pen/ExEXbYN?editors=0010
Here is the formula/code logic I found on one OpenCL program that works:

Probably, the compute_interaction() function should be:
function compute_interaction(currentPosition, positionOtherStar, smoothing_length)
{
//const vector = new THREE.Vector3(positionOtherStar.x - currentPosition.x, positionOtherStar.y - currentPosition.y, positionOtherStar.z - currentPosition.z).normalize();
//let x = vector.x / (Math.pow(positionOtherStar.x,2.0) - Math.pow(currentPosition.x,2.0)+ smoothing_length)
//let y = vector.y / (Math.pow(positionOtherStar.y,2.0) - Math.pow(currentPosition.y,2.0)+ smoothing_length)
//let z = vector.z / (Math.pow(positionOtherStar.z,2.0) - Math.pow(currentPosition.z,2.0)+ smoothing_length)
//return new THREE.Vector3(x, y, z);
const vector = new THREE.Vector3().subVectors(positionOtherStar, currentPosition);
return vector.normalize().divideScalar(vector.lengthSq() + smoothing_length);
}

Related

pyglet gives error regarding GLSL version

I am trying to run a code that has a GUI built with pyglet.
but it gives this error. I have searched and found that I need to directly set the version of GLSL to be used by the code but I don't know how. would be happy if you helped me out with it.
b"0:20(27): error: cannot initialize uniform weight in GLSL 1.10 (GLSL 1.20 required)\n0:20(27): error: array constructors forbidden in GLSL 1.10 (GLSL 1.20 or GLSL ES 3.00 required)\n0:20(27): error: initializer of uniform variable `weight' must be a constant expression\n0:79(17): error: could not implicitly convert operands to arithmetic operator\n0:79(16): error: operands to arithmetic operators must be numeric\n0:89(7): warning: `coeff' used uninitialized\n"
this is the shader.py file:
Update
added the glsl file with the uniform weight in it
#ifdef GL_ES
precision highp float;
#endif
uniform sampler2D inlet;
uniform sampler2D disp0;
uniform float sigma;
uniform bool xmirror;
uniform vec3 colors[9];
uniform float streams[9];
/*mat4 gaussm = mat4(0.00000067, 0.00002292, 0.00019117, 0.00038771,
0.00002292, 0.00078634, 0.00655965, 0.01330373,
0.00019117, 0.00655965, 0.05472157, 0.11098164,
0.00038771, 0.01330373, 0.11098164, 0.22508352);*/
uniform float weight[5] = float[](0.2270270270, 0.1945946, 0.1216216216, 0.0540540541, 0.0162162162);
vec4 sample(vec2 p)
{
vec4 col;
if(streams[0] >= 0.)
{
int stream = 0;
for(int i=0;streams[stream] < min(p.x, 1.) && stream < 8;stream++) { }
col = vec4(colors[stream], 1.);
}
else {
col = texture2D(inlet, p);
}
return col;
}
float gaussian(float d, float s)
{
float pi = 3.141592653;
//return exp(- d*d / (4.0 * pi * s * s));
//return pow(4*pi*s*s, 0.5)*exp(- d*d / (4.0 * pi * s * s));
return exp(- d*d / (2.*s*s));
}
float gaussian2(float d, float s)
{
float pi = 3.141592653;
float c = pow(1.0 / (4.0 * pi * s), 0.5);
float e = -1.0*(d * d) / (4.0 * s);
return c * exp(e);
}
float gaussf(int i, int j,float nf, float s)
{
//return gaussm[i][j];
float fi = float(i)/nf;
float jf = float(j)/nf;
return gaussian2(sqrt(fi*fi+jf*jf), s);
}
float cosh(float x)
{
return (exp(x)+exp(-x))/2.;
}
float rect_calc(vec2 d)
{
float pi = 3.141592653;
float AR = 0.25;
float offset = 0.125;
float m = 155.;
float n = 155.;
vec3 xyz = vec3(0., (d.x/1.), (d.y/8. + offset));
float u = 0.;
float coeff = (16 * pow(AR, 2.)) / pow(pi, 4.);
float num;
float den;
for(float i = 1.; i <= n; i += 2.)
{
for(float j = 1.; j <= m; j += 2.)
{
num = sin(i * pi * xyz.y) * sin(j * pi * ((xyz.z)/AR));
den = i * j * (pow(AR, 2.) * pow(AR, 2.) + pow(j, 2.));
u += coeff * (num / den);
}
}
// Convert velocity to time-of-flight
float L = 2.0;
float u_mean = 0.0043;
float u_norm = u/u_mean;
return L / u_norm;
}
void main()
{
vec2 uv = gl_TexCoord[0].st;
if(xmirror)
{
uv.x = 1.-uv.x;
}
vec2 d = texture2D(disp0, uv).yz * vec2(1.,8.);
if(xmirror)
{
d.x = -d.x;
uv.x = 1.-uv.x;
}
vec2 p = uv + d;
if(sigma <= 0.)
{
gl_FragColor = sample(p);
} else {
//Sample
vec4 c = vec4(0.);
float Dt = sigma*rect_calc(uv.xy);
float s = pow(Dt, 0.5);
float s2 = 1.0;
float t = 0.;
int ni = 8;
float n = 8.;
for(int ii = 0; ii < ni-1; ii++)
{
float i = float(ii);
for(int jj = 0; jj < ni-1; jj++)
{
float j = float(jj);
t += gaussf(ii,jj,n-1.,s2)*4.;
c += gaussf(ii,jj,n-1.,s2) * (sample(p + vec2((n-1.-i)*s, (n-1.-j)*s)) + sample(p + vec2(-(n-1.-i)*s, (n-1.-j)*s)) + sample(p + vec2(-(n-1.-i)*s, -(n-1.-j)*s)) + sample(p + vec2((n-1.-i)*s, -(n-1.-j)*s)));
}
t += gaussf(ii,ni-1,n-1.,s2)*4.;
c += gaussf(ii,ni-1,n-1.,s2) * (sample(p + vec2((n-1.-i)*s, 0.)) + sample(p + vec2(-(n-1.-i)*s, 0.))+ sample(p + vec2(0., (n-1.-i)*s))+ sample(p + vec2(0., -(n-1.-i)*s)));
}
t += gaussf(ni-1,ni-1,n-1.,s2);
c += gaussf(ni-1,ni-1,n-1.,s2) * sample(p);
//gl_FragColor = c;
gl_FragColor = c/t;
//gl_FragColor = (sigma*rect_calcu(uv.xy))*c/t;
}
}
well it got solved!
just needed to add the directive #version 120 at the beginning of the shader like this:
#version 120
#ifdef GL_ES
precision highp float;
#endif
uniform sampler2D inlet;
uniform sampler2D disp0;
uniform float sigma;
uniform bool xmirror;
uniform vec3 colors[9];
uniform float streams[9];
/*mat4 gaussm = mat4(0.00000067, 0.00002292, 0.00019117, 0.00038771,
0.00002292, 0.00078634, 0.00655965, 0.01330373,
0.00019117, 0.00655965, 0.05472157, 0.11098164,
0.00038771, 0.01330373, 0.11098164, 0.22508352);*/
uniform float weight[5] = float[](0.2270270270, 0.1945946, 0.1216216216, 0.0540540541, 0.0162162162);
vec4 sample(vec2 p)
{
vec4 col;
if(streams[0] >= 0.)
{
int stream = 0;
for(int i=0;streams[stream] < min(p.x, 1.) && stream < 8;stream++) { }
col = vec4(colors[stream], 1.);
}
else {
col = texture2D(inlet, p);
}
return col;
}
float gaussian(float d, float s)
{
float pi = 3.141592653;
//return exp(- d*d / (4.0 * pi * s * s));
//return pow(4*pi*s*s, 0.5)*exp(- d*d / (4.0 * pi * s * s));
return exp(- d*d / (2.*s*s));
}
float gaussian2(float d, float s)
{
float pi = 3.141592653;
float c = pow(1.0 / (4.0 * pi * s), 0.5);
float e = -1.0*(d * d) / (4.0 * s);
return c * exp(e);
}
float gaussf(int i, int j,float nf, float s)
{
//return gaussm[i][j];
float fi = float(i)/nf;
float jf = float(j)/nf;
return gaussian2(sqrt(fi*fi+jf*jf), s);
}
float cosh(float x)
{
return (exp(x)+exp(-x))/2.;
}
float rect_calc(vec2 d)
{
float pi = 3.141592653;
float AR = 0.25;
float offset = 0.125;
float m = 155.;
float n = 155.;
vec3 xyz = vec3(0., (d.x/1.), (d.y/8. + offset));
float u = 0.;
float coeff = (16 * pow(AR, 2.)) / pow(pi, 4.);
float num;
float den;
for(float i = 1.; i <= n; i += 2.)
{
for(float j = 1.; j <= m; j += 2.)
{
num = sin(i * pi * xyz.y) * sin(j * pi * ((xyz.z)/AR));
den = i * j * (pow(AR, 2.) * pow(AR, 2.) + pow(j, 2.));
u += coeff * (num / den);
}
}
// Convert velocity to time-of-flight
float L = 2.0;
float u_mean = 0.0043;
float u_norm = u/u_mean;
return L / u_norm;
}
void main()
{
vec2 uv = gl_TexCoord[0].st;
if(xmirror)
{
uv.x = 1.-uv.x;
}
vec2 d = texture2D(disp0, uv).yz * vec2(1.,8.);
if(xmirror)
{
d.x = -d.x;
uv.x = 1.-uv.x;
}
vec2 p = uv + d;
if(sigma <= 0.)
{
gl_FragColor = sample(p);
} else {
//Sample
vec4 c = vec4(0.);
float Dt = sigma*rect_calc(uv.xy);
float s = pow(Dt, 0.5);
float s2 = 1.0;
float t = 0.;
int ni = 8;
float n = 8.;
for(int ii = 0; ii < ni-1; ii++)
{
float i = float(ii);
for(int jj = 0; jj < ni-1; jj++)
{
float j = float(jj);
t += gaussf(ii,jj,n-1.,s2)*4.;
c += gaussf(ii,jj,n-1.,s2) * (sample(p + vec2((n-1.-i)*s, (n-1.-j)*s)) + sample(p + vec2(-(n-1.-i)*s, (n-1.-j)*s)) + sample(p + vec2(-(n-1.-i)*s, -(n-1.-j)*s)) + sample(p + vec2((n-1.-i)*s, -(n-1.-j)*s)));
}
t += gaussf(ii,ni-1,n-1.,s2)*4.;
c += gaussf(ii,ni-1,n-1.,s2) * (sample(p + vec2((n-1.-i)*s, 0.)) + sample(p + vec2(-(n-1.-i)*s, 0.))+ sample(p + vec2(0., (n-1.-i)*s))+ sample(p + vec2(0., -(n-1.-i)*s)));
}
t += gaussf(ni-1,ni-1,n-1.,s2);
c += gaussf(ni-1,ni-1,n-1.,s2) * sample(p);
//gl_FragColor = c;
gl_FragColor = c/t;
//gl_FragColor = (sigma*rect_calcu(uv.xy))*c/t;
}
}

Trouble when rendering voxels with pathtracing

I'm currently working on a pathtracer in c and open cl.
I'm using this algorithm for rendering. The first collision works well, however, from the second collision onwards there is a dark shadow on the lower side of the voxels.
This is the color of the voxel the initial ray hits:
result
This is the color of the voxel that the second ray hits:
result
And this is the result after rendering to a depth of 1000:
result
This is the code I used (openCL):
int cast_ray(Renderer *r, Ray ray, float3 *hitPos, int3 *normal, Material *material) {
int3 voxel = convert_int3(ray.origin);
int3 step = {
(ray.direction.x >= 0) ? 1 : -1,
(ray.direction.y >= 0) ? 1 : -1,
(ray.direction.z >= 0) ? 1 : -1
};
float3 tMax = {
(ray.direction.x != 0) ? (voxel.x + step.x - ray.origin.x) / ray.direction.x : MAXFLOAT,
(ray.direction.y != 0) ? (voxel.y + step.y - ray.origin.y) / ray.direction.y : MAXFLOAT,
(ray.direction.z != 0) ? (voxel.z + step.z - ray.origin.z) / ray.direction.z : MAXFLOAT
};
float3 tDelta = {
(ray.direction.x != 0) ? 1 / ray.direction.x * step.x : MAXFLOAT,
(ray.direction.y != 0) ? 1 / ray.direction.y * step.y : MAXFLOAT,
(ray.direction.z != 0) ? 1 / ray.direction.z * step.z : MAXFLOAT
};
int side;
while(1) {
if(tMax.x < tMax.y) {
if(tMax.x < tMax.z) {
voxel.x += step.x;
tMax.x += tDelta.x;
side = 0;
} else {
voxel.z += step.z;
tMax.z += tDelta.z;
side = 2;
}
} else {
if(tMax.y < tMax.z) {
voxel.y += step.y;
tMax.y += tDelta.y;
side = 1;
} else {
voxel.z += step.z;
tMax.z += tDelta.z;
side = 2;
}
}
if(out_of_scene(r, voxel))
return 0;
MaterialID id = get_material_ID(r, voxel);
if(id == 0)
continue;
*material = get_material(r, id);
switch(side) {
case 0:
hitPos->x = (float)voxel.x;
hitPos->y = ray.origin.y + (hitPos->x - ray.origin.x) * ray.direction.y / ray.direction.x;
hitPos->z = ray.origin.z + (hitPos->x - ray.origin.x) * ray.direction.z / ray.direction.x;
*normal = (int3){-step.x, 0, 0};
break;
case 1:
hitPos->y = (float)voxel.y;
hitPos->x = ray.origin.x + (hitPos->y - ray.origin.y) * ray.direction.x / ray.direction.y;
hitPos->z = ray.origin.z + (hitPos->y - ray.origin.y) * ray.direction.z / ray.direction.y;
*normal = (int3){0, -step.y, 0};
break;
case 2:
hitPos->z = (float)voxel.z;
hitPos->y = ray.origin.y + (hitPos->z - ray.origin.z) * ray.direction.y / ray.direction.z;
hitPos->x = ray.origin.x + (hitPos->z - ray.origin.z) * ray.direction.x / ray.direction.z;
*normal = (int3){0, 0, -step.z};
break;
}
return 1;
}
}
float3 get_color(Renderer *r, Ray ray) {
float3 mask = 1;
float3 color = 0;
int maxDepth = 1000;
for(int i = 0; i < maxDepth; i++) {
float3 hitPos;
int3 iNormal;
Material material;
if(cast_ray(r, ray, &hitPos, &iNormal, &material)) {
float3 fNormal = convert_float3(iNormal);
if(material.type == 1) {
color = mask * material.color;
break;
} else if(material.type == 2) {
float3 direction = fNormal + random_unit_vector(r->rng);
ray = (Ray){hitPos, direction};
mask *= material.color;
} else if(material.type == 3) {
float3 direction = reflection_dir(ray.direction, fNormal) + random_unit_vector(r->rng) * material.fuzzyness;
ray = (Ray){hitPos, direction};
mask = mask * (1 - material.tint) + mask * material.color * material.tint;
}
} else {
color = mask * r->bgColor;
break;
}
// if(i == 1)
// return material.color;
}
return color;
}
I think that the problem is that the new origin of the ray is somehow not correct, but I can't find a way to fix it.

Opencl 3D array indexing

I have 3D array (height, width, depth). My global worksize is (height * width * depth). and local work size is 1. In kernel code how I can get row offset and column offset?
I am doing the convolution operation in opencl. In C we do as follow,
// iterating through number of filters
for(c = 0; c < number_of_filters; c++)
{
for(h = 0; h < out_height; h++)
{
for(w = 0; w < out_width; w++)
{
vert_start = h * stride;
vert_end = vert_start + f_size ;
hor_start = w * stride;
hor_end = hor_start + f_size;
sum = 0;
for(c_f = 0; c_f < input_channel; c_f++)
{
for(h_f = vert_start; h_f < vert_end; h_f++)
{
for(w_f = hor_start; w_f < hor_end; w_f++)
{
// computing convolution
sum = sum +
(INPUT[(c_f * input_height * input_width) + (h * input_width) + w] *
FILTER[(c_f * filt_height* filt_width) + (h_f * filt_width) + w_f)]);
}
}
}
// storing result in output
OUTPUT[(c * out_height * out_width) + (h * out_width) + w] = sum;
}
}
}
I am not getting how to get that row offset and column offset from image for convolution in opencl?

R Weighted moving average with partial averages

I am trying to code in R a(centered) weighted moving average function that returns me a vector of the same size than the input vector.
The following code almost gives me what I want but it does not work for the first and last values of my vector
set.seed(0)
len=10
x=floor(l*runif(l))
weights=c(1,3,0,3,1)
weights=weights/sum(weights)
rollapply(x,width=length(weights), function(x) sum(x*weights),align="center")
na.omit(filter(x,sides=2,weights))
Setting partial=TRUE in the rollapply function is sort of what I want to do. Anyway it does not work since my function does not support an x of changing sizes.
I could the latter and manually add the sides computations with a loop. It would work but I would like to find a nicer (computationally faster) way to do it.
For a more rigorous description of my needs here is a mathematical version
r is the vector my function would return
x and the weights w as inputs :
With Rcpp, you can do:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector roll_mean(const NumericVector& x,
const NumericVector& w) {
int n = x.size();
int w_size = w.size();
int size = (w_size - 1) / 2;
NumericVector res(n);
int i, ind_x, ind_w;
double w_sum = Rcpp::sum(w), tmp_wsum, tmp_xwsum, tmp_w;
// beginning
for (i = 0; i < size; i++) {
tmp_xwsum = tmp_wsum = 0;
for (ind_x = i + size, ind_w = w_size - 1; ind_x >= 0; ind_x--, ind_w--) {
tmp_w = w[ind_w];
tmp_wsum += tmp_w;
tmp_xwsum += x[ind_x] * tmp_w;
}
res[i] = tmp_xwsum / tmp_wsum;
}
// middle
int lim2 = n - size;
for (; i < lim2; i++) {
tmp_xwsum = 0;
for (ind_x = i - size, ind_w = 0; ind_w < w_size; ind_x++, ind_w++) {
tmp_xwsum += x[ind_x] * w[ind_w];
}
res[i] = tmp_xwsum / w_sum;
}
// end
for (; i < n; i++) {
tmp_xwsum = tmp_wsum = 0;
for (ind_x = i - size, ind_w = 0; ind_x < n; ind_x++, ind_w++) {
tmp_w = w[ind_w];
tmp_wsum += tmp_w;
tmp_xwsum += x[ind_x] * tmp_w;
}
res[i] = tmp_xwsum / tmp_wsum;
}
return res;
}
I use this function in one of my packages.
Just put that in a .cpp file and source it with Rcpp::sourceCpp.

Arduino: float function returns inf

I have a function (shown below) that I need some advice on. The function returns the slope of a line which is fit (via the least squares method) to n data points. To give you a context, my project is a barometric pressure based altimeter which uses this function to determine velocity based on the n most recent altitude-time pairs. These altitude-time pairs are stored in 2 global arrays(times[] and alts[]).
My problem is not that this method doesn't work. It usually does. But sometimes I will run the altimeter and this function will return the value 'inf' interspersed with a bunch of other wrong values (I have also seen 'NaN' but that is more rare). There are a few areas of suspicion I have at this point but I would like a fresh perspective. Here is some further contextual information that may or may not be of use:
I am using interrupts for a quadrature encoder
The times[] array is of type unsigned long
The alts[] array is of type float
n is a const int, in this case n = 9
On the ATMEGA328 a double is the same as a float.. Arduino-double
float velF() { // uses the last n data points, fits a line to them,
// and uses the slope of that line as the velocity at that moment
float sumTY = 0, sumT = 0, sumY = 0, sumT2 = 0;
for (int i = 0; i < n; i++) {
sumTY += (float)times[i] * alts[i] / 1000;
sumT += (float)times[i] / 1000;
sumY += alts[i];
sumT2 += (float)times[i] * times[i] / 1000000;
}
return (n*sumTY - sumT*sumY) / (n*sumT2 - sumT*sumT);
}
Any help or advice would be greatly appreciated!
Code is certainly performing division by zero.
For a variety of reasons, n*sumT2 - sumT*sumT will be zero. #John Bollinger In most of these cases, the top (dividend) of the division will also be zero and a return value of zero would be acceptable.
float velF(void) {
float sumTY = 0, sumT = 0, sumY = 0, sumT2 = 0;
for (size_t i = 0; i < n; i++) {
// insure values are reasoable
assert(alts[i] >= ALT_MIN && alts[i] <= ALT_MAX);
assert(times[i] >= TIME_MIN && times[i] <= TIME_MAX);
sumTY += (float)times[i] * alts[i] / 1000;
sumT += (float)times[i] / 1000;
sumY += alts[i];
sumT2 += (float)times[i] * times[i] / 1000000;
}
float d = n*sumT2 - sumT*sumT;
if (d == 0) return 0;
return (n*sumTY - sumT*sumY) / d;
}
Side note: could factor out the division for improved accuracy and speed. Suggest performing the last calculation as double.
float velF(void) {
float sumTY = 0, sumT = 0, sumY = 0, sumT2 = 0;
for (size_t i = 0; i < n; i++) {
float tf = (float) times[i];
sumTY += tf * alts[i];
sumT += tf;
sumY += alts[i];
sumT2 += tf * tf;
}
double nd = n;
double sumTd = sumT;
double d = nd*sumT2 - sumTd*sumTd;
if (d == 0) return 0;
return (nd*sumTY - sumTd*sumY)*1000 / d;
}

Resources