I'm trying to write a pyopencl script to compute Thomas' cyclically symmetric attractor.
The function for which is
x' = sin(y)-bx
y' = sin(z)-by
z' = sin(x)-bz
I have written an implementation in python3 that works, albeit slowly. This is the output I want to get:
working solution
and this is the output from my pyopencl implementation:
broken opencl implementation
I believe I'm encountering some kind of rounding error or approximation error on the sine function, so i tried casting everything to a double with no success. The other possibility I can see is that I am making some mistake in outputting the values reached as the function iterates, but I don't know what it would be.
Here is the kernel in question.
#pragma OPENCL EXTENSION cl_khr_byte_addressable_store : enable
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
__kernel void thomas(__global float3 *a,
__global float3 *output, ulong const maxiter, float const stepSize, float const b )
{
int gid = get_global_id(0);
double x = a[gid][0];
double y = a[gid][1];
double z = a[gid][2];
double x1,y1,z1 = 0.0;
for(int citer = 0; citer<maxiter;citer++){
x1 = x+stepSize*(sin(y)-b*x);
y1 = y+stepSize*(sin(z)-b*y);
z1 = z+stepSize*(sin(x)-b*z);
output[gid*maxiter+citer][0]=x1;
output[gid*maxiter+citer][1]=y1;
output[gid*maxiter+citer][2]=z1;
x = x1;
y = y1;
z = z1;
}
}
a is an array of starting values and the output is an array with length a*maxiter
I expect the output of the pyopencl implementation to match the python3 implementation, but it seems to output a shape only in the xy plane, whose relation to the 3d shape is uncertain to me.
edit: here is the rest of the code for the offending program
import numpy as np
import pyopencl as cl
import open3d as o3d
def calc_thomas_opencl(npoints, stepSize, maxiter, b):
ballRadius = .5
ctx = cl.create_some_context()
queue = cl.CommandQueue(ctx)
mf = cl.mem_flags
points = []
for point in range(npoints):
x1 = np.random.rand()-.5
x2 = np.random.rand()-.5
x3 = np.random.rand()-.5
u = np.random.rand()
fac = ballRadius*u**.3/(np.sqrt(x1**2+x2**2+x3**2))
point = (x1*fac,x2*fac,x3*fac)
points.append(point)
a=np.array(points,dtype = np.float32)
print(a[0])
a_opencl = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=a)
output = np.zeros([npoints*maxiter,3])
output_opencl = cl.Buffer(ctx, mf.WRITE_ONLY, output.nbytes)
prg = cl.Program(ctx, """
#pragma OPENCL EXTENSION cl_khr_byte_addressable_store : enable
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
__kernel void thomas(__global float3 *a,
__global float3 *output, ulong const maxiter, float const stepSize, float const b )
{
int gid = get_global_id(0);
double x = a[gid][0];
double y = a[gid][1];
double z = a[gid][2];
double x1,y1,z1 = 0.0;
for(int citer = 0; citer<maxiter;citer++){
x1 = x+stepSize*(sin(y)-b*x);
y1 = y+stepSize*(sin(z)-b*y);
z1 = z+stepSize*(sin(x)-b*z);
output[gid*maxiter+citer][0]=x1;
output[gid*maxiter+citer][1]=y1;
output[gid*maxiter+citer][2]=z1;
x = x1;
y = y1;
z = z1;
}
}
""").build()
prg.thomas(queue, (npoints,), None, a_opencl,
output_opencl, np.uint64(maxiter), np.float32(stepSize), np.float32(b))
cl.enqueue_copy(queue, output, output_opencl).wait()
return output
xyz = calc_thomas_opencl(1000,.05,1000,.2)
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(xyz)
o3d.visualization.draw_geometries([pcd])
The problem was in
output = np.zeros([npoints*maxiter,3])
it needed to be
output = np.zeros([npoints*maxiter,3], dtype = np.float32)
Related
I want to estimate multiplicity of polynomial roots.
I have found some info about it, choosed the test example and made c program
Here should be 4 roots. One simple root and one with multiplicity 3.
#include <complex.h>
#include <math.h>
#include <stdio.h>
complex long double z0 = +1.5; // exact period = 1 stability = 3.000000000000000000 multiplicity = ?
complex long double z1 = -0.5; // exact period = 2 stability = 0.999999999999900080 multiplicity = ?
complex long double c = -0.75; // parameter of the f function
/*
https://en.wikibooks.org/wiki/Fractals/Mathematics/Newton_method
*/
int GiveMultiplicity(const complex long double c, const complex long double z0 , const int pMax){
complex long double z = z0;
complex long double d = 1.0; /* d = first derivative with respect to z */
complex long double e = 0.0; // second derivative with respect to z
complex long double m;
int multiplicity;
int p;
for (p=0; p < pMax; p++){
d = 2*z*d; // f' = first derivative with respect to z */
e = 2*(d*d +z*e); // f'' = second derivative with respect to z
z = z*z +c ; // f = complex quadratic polynomial
}
m = (d*d)/(d*d -z*e);
multiplicity = (int) round(cabs(m));
return multiplicity;
}
int main(){
int m;
m = GiveMultiplicity(c, z0, 1);
printf("m = %d \n", m);
m = GiveMultiplicity(c, z1, 1);
printf("m = %d \n", m);
m = GiveMultiplicity(c, z1, 2);
printf("m = %d \n", m);
return 0;
}
The result is :
m=1
m=1
m=1
Is it good ? Maybe I should simply add the results ?
Good results using symbolic computations are roots: [ 3/2, -1/2] and its multiplicities : [1,3]
Here is a graph of the function f(z)= (z^2-0.75)^2-z-0.75 = z^4-1.5*z^2-z-3/16
Is it possibly to compute the similar values numerically ?
You do this with contour integration, see here. Software is available.
Summary of changes:
evaluate e before evaluating d inside the loop;
when subtracting z0 from z after the loop, you also need to subtract 1 from d to match;
perturb input a small amount from true root location to avoid 0/0 = NaN result: h must be small enough, but not too small...
Complete program:
#include <complex.h>
#include <math.h>
#include <stdio.h>
complex long double h = 1.0e-6; // perturb a little; not too big, not too small
complex long double z0 = +1.5; // exact period = 1 stability = 3.000000000000000000 multiplicity = ?
complex long double z1 = -0.5; // exact period = 2 stability = 0.999999999999900080 multiplicity = ?
complex long double c = -0.75; // parameter of the f function
/*
https://en.wikibooks.org/wiki/Fractals/Mathematics/Newton_method
*/
int GiveMultiplicity(const complex long double c, const complex long double z0, const int pMax){
complex long double z = z0;
complex long double d = 1.0; /* d = first derivative with respect to z */
complex long double e = 0.0; // second derivative with respect to z
complex long double m;
int multiplicity;
int p;
for (p=0; p < pMax; p++){
e = 2*(d*d +z*e); // f'' = second derivative with respect to z
d = 2*z*d; // f' = first derivative with respect to z */
z = z*z +c ; // f = complex quadratic polynomial
}
d = d - 1;
z = z - z0;
m = (d*d)/(d*d -z*e);
multiplicity = (int) round(cabs(m));
return multiplicity;
}
int main(){
int m;
m = GiveMultiplicity(c, z0 + h, 1);
printf("m = %d\n", m);
m = GiveMultiplicity(c, z1 + h, 1);
printf("m = %d\n", m);
m = GiveMultiplicity(c, z1 + h, 2);
printf("m = %d\n", m);
return 0;
}
Output:
m = 1
m = 1
m = 3
I have found one error im my initial program. Function for finding periodic points should be
f^n(z) - z
so
for (p=0; p < pMax; p++){
d = 2*z*d; // f' = first derivative with respect to z */
e = 2*(d*d +z*e); // f'' = second derivative with respect to z
z = z*z +c ; // f = complex quadratic polynomial
}
z = z - z0; // new line
I have choosed the method based on the geometrical notation of the root
It is described in The Fundamental Theorem of Algebra: A Visual Approach by Daniel J. Velleman
I count how many times color chages along a circle around root.
I use carg function which returns the phase angle of z in the interval [−π; π]. So count the sign change of the argument and divide it by 2. This estimates the multiplicity of the root.
It is probly the same method as above, but easier to understand and implement for me.
Here is the image of dynamical plane
before transformation:
and after f(z):
and the code:
// gcc p.c -Wall -lm
// ./a.out
#include <complex.h>
#include <math.h>
#include <stdio.h>
// parameter c of the function fc(z) = z^2+c is c = -0.7500000000000000 ; 0.0000000000000000
const long double pi = 3.1415926535897932384626433832795029L;
long double EPS2 = 1e-18L*1e-18L; //
complex double c = -0.75;
complex double z = 1.5; //-0.5;
//https://stackoverflow.com/questions/1903954/is-there-a-standard-sign-function-signum-sgn-in-c-c
int sign(long double x){
if (x > 0.0) return 1;
if (x < 0.0) return -1;
return 0;
}
int DifferentSign(long double x, long double y){
if (sign(x)!=sign(y)) return 1;
return 0;
}
long double complex Give_z0(long double InternalAngleInTurns, long double radius )
{
//0 <= InternalAngleInTurns <=1
long double a = InternalAngleInTurns *2.0*pi; // from turns to radians
long double Cx, Cy; /* C = Cx+Cy*i */
Cx = radius*cosl(a);
Cy = radius*sinl(a);
return Cx + Cy*I;
}
int GiveMultiplicity(complex long double zr, int pMax){
int s; // number of starting point z0
int sMax = 5*pMax; // it should be greater then 2*pMax
long double t= 0.0; // angle of circle around zr, measured in turns
long double dt = 1.0 / sMax; // t step
long double radius = 0.001; // radius should be smaller then minimal distance between roots
int p;
long double arg_old = 0.0;
long double arg_new = 0.0;
int change = 0;
complex long double z;
complex long double z0;
//complex long double zp;
//
for (s=0; s<sMax; ++s){
z0 = zr + Give_z0(t, radius); // z = point on the circle around root zr
// compute zp = f^p(z)
z = z0;
for (p=0; p < pMax; ++p){z = z*z + c ;} /* complex quadratic polynomial */
// turn (zp-z0)
z = z - z0; // equation for periodic_points of f for period p
arg_new = carg(z);
if (DifferentSign(arg_new, arg_old)) {change+=1;}
arg_old = arg_new;
//printf("z0 = %.16f %.16f zp = %.16f %.16f\n", creal(z0), cimag(z0), creal(zp), cimag(zp));
t += dt; // next angle using globl variable dt
}
return change/2;
}
int main(){
printf("multiplicity = %d\n", GiveMultiplicity(z,2));
return 0;
}
And here is the image of argument of z around root ( it uses carg )
So I wanted to implement the path of the Moon around the Earth with a C program.
My problem is that you know the Moon's velocity and position at Apogee and Perigee.
So I started to solve it from Apogee, but I cannot figure out how I could add the second velocity and position as "initial value" for it. I tried it with an if but I don't see any difference between the results. Any help is appreciated!
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
typedef void (*ode)(double* p, double t, double* k, double* dk);
void euler(ode f, double *p, double t, double* k, double h, int n, int N)
{
double kn[N];
double dk[N];
double Rp = - 3.633 * pow(10,8); // x position at Perigee
for(int i = 0; i < n; i++)
{
f(p, 0, k, dk);
for (int j = 0; j < N; j++)
{
if (k[0] == Rp) // this is the "if" I mentioned in my comment
// x coordinate at Perigee
{
k[1] = 0; // y coordinate at Perigee
k[2] = 0; // x velocity component at Perigee
k[3] = 1076; // y velocity component at Perigee
}
kn[j] = k[j] + h * dk[j];
printf("%f ", kn[j]);
k[j] = kn[j];
}
printf("\n");
}
}
void gravity_equation(double* p, double t, double* k, double* dk)
{
// Earth is at the (0, 0)
double G = p[0]; // Gravitational constant
double m = p[1]; // Earth mass
double x = k[0]; // x coordinate at Apogee
double y = k[1]; // y coordinate at Apogee
double Vx = k[2]; // x velocity component at Apogee
double Vy = k[3]; // y velocity component at Apogee
dk[0] = Vx;
dk[1] = Vy;
dk[2] = (- G * m * x) / pow(sqrt((x * x)+(y * y)),3);
dk[3] = (- G * m * y) / pow(sqrt((x * x)+(y * y)),3);
}
void run_gravity_equation()
{
int N = 4; // how many equations there are
double initial_values[N];
initial_values[0] = 4.055*pow(10,8); // x position at Apogee
initial_values[1] = 0; // y position at Apogee
initial_values[2] = 0; // x velocity component at Apogee
initial_values[3] = (-1) * 964; //y velocity component at Perigee
int p = 2; // how many parameters there are
double parameters[p];
parameters[0] = 6.67384 * pow(10, -11); // Gravitational constant
parameters[1] = 5.9736 * pow(10, 24); // Earth mass
double h = 3600; // step size
int n = 3000; // the number of steps
euler(&gravity_equation, parameters, 0, initial_values, h, n, N);
}
int main()
{
run_gravity_equation();
return 0;
}
Your interface is
euler(odefun, params, t0, y0, h, n, N)
where
N = dimension of state space
n = number of steps to perform
h = step size
t0, y0 = initial time and value
The intended function of this procedure seems to be that the updated values are returned inside the array y0. There is no reason to insert some hack to force the state to have some initial conditions. The initial condition is passed as argument. As you are doing in void run_gravity_equation(). The integration routine should remain agnostic of the details of the physical model.
It is extremely improbable that you will hit the same value in k[0] == Rp a second time. What you can do is to check for sign changes in Vx, that is, k[1] to find points or segments of extremal x coordinate.
Trying to interpret your description closer, what you want to do is to solve a boundary value problem where x(0)=4.055e8, x'(0)=0, y'(0)=-964 and x(T)=-3.633e8, x'(T)=0. This has the advanced tasks to solve a boundary value problem with single or multiple shooting and additionally, that the upper boundary is variable.
You might want to to use the Kepler laws to get further insights into the parameters of this problem so that you can solve it just with a forward integration. The Kepler ellipse of the first Kepler law has the formula (scaled for Apogee at phi=0, Perigee at phi=pi)
r = R/(1-E*cos(phi))
so that
R/(1-E)=4.055e8 and R/(1+E)=3.633e8,
which gives
R=3.633*(1+E)=4.055*(1-E)
==> E = (4.055-3.633)/(4.055+3.633) = 0.054891,
R = 3.633e8*(1+0.05489) = 3.8324e8
Further, the angular velocity is given by the second Kepler law
phi'*r^2 = const. = sqrt(R*G*m)
which gives tangential velocities at Apogee (r=R/(1-E))
y'(0)=phi'*r = sqrt(R*G*m)*(1-E)/R = 963.9438
and Perigee (r=R/(1+E))
-y'(T)=phi'*r = sqrt(R*G*m)*(1+E)/R = 1075.9130
which indeed reproduces the constants you used in your code.
The area of the Kepler ellipse is pi/4 times the product of smallest and largest diameter. The smallest diameter can be found at cos(phi)=E, the largest is the sum of apogee and perigee radius, so that the area is
pi*R/sqrt(1-E^2)*(R/(1+E)+R/(1-E))/2= pi*R^2/(1-E^2)^1.5
At the same time it is the integral over 0.5*phi*r^2 over the full period 2*T, thus equal to
sqrt(R*G*m)*T
which is the third Kepler law. This allows to compute the half-period as
T = pi/sqrt(G*m)*(R/(1-E^2))^1.5 = 1185821
With h = 3600 the half point should be reached between n=329 and n=330 (n=329.395). Integration with scipy.integrate.odeint vs. Euler steps gives the following table for h=3600:
n [ x[n], y[n] ] for odeint/lsode for Euler
328 [ -4.05469444e+08, 4.83941626e+06] [ -4.28090166e+08, 3.81898023e+07]
329 [ -4.05497554e+08, 1.36933874e+06] [ -4.28507841e+08, 3.48454695e+07]
330 [ -4.05494242e+08, -2.10084488e+06] [ -4.28897657e+08, 3.14986514e+07]
The same for h=36, n=32939..32940
n [ x[n], y[n] ] for odeint/lsode for Euler
32938 [ -4.05499997e+08 5.06668940e+04] [ -4.05754415e+08 3.93845978e+05]
32939 [ -4.05500000e+08 1.59649309e+04] [ -4.05754462e+08 3.59155385e+05]
32940 [ -4.05500000e+08 -1.87370323e+04] [ -4.05754505e+08 3.24464789e+05]
32941 [ -4.05499996e+08 -5.34389954e+04] [ -4.05754545e+08 2.89774191e+05]
which is a little closer for the Euler method, but not much better.
So I'm very new to C programming and I'm being asked to write a programming to compute the mean effective pressure of an internal combustion engine's cylinder.
I'm given:
MEP = (66,000 * HP) / (L * A * RPM)
A = (pi * D^2) / 4 (cross sectional area of the cylinder
D = 3.5in. (Cylinder diameter)
L = 0.417ft (cylinder stroke)
RPM = 5000
HP = 110
I'm supposed to output the Bore (in), Stroke (ft), and the MEP (psi).
This seems like a relatively easy programming, but I just need a few walkthroughs to get me to the finish line. I'm using LCC-Win for testing.
That is what I have so far:
int main()
{
float A, MEP, D, A, L, RPM, HP; //declaring all variables
D = 3.5;
L = .417;
RPM = 5000;
HP = 110;
MEP = (66000*HP)/(L*A*RPM);
double compute_area(double diameter);
const double pi = 3.14159265;
return (pi * diameter * diameter) / 4;
}
You can try this:
#define pi 3.14159265; //macro to define value of pi
//function compute_area is defined here
double compute_area(double diameter){
return (pi * diameter * diameter) / 4;
}
int main(){
double A, MEP, D, L, RPM, HP; //declaring all variables
D = 3.5;
L = .417;
RPM = 5000;
HP = 110;
A=compute_area(D); // calling the function compute_area
MEP = (66000*HP)/(L*A*RPM); // calculating the MEP as per your formula
printf("MEP %f", MEP); //printing the MEP result
return 0;
}
I am trying to write a simple ray tracer. The final image should like this: I have read stuff about it and below is what I am doing:
create an empty image (to fill each pixel, via ray tracing)
for each pixel [for each row, each column]
create the equation of the ray emanating from our pixel
trace() ray:
if ray intersects SPHERE
compute local shading (including shadow determination)
return color;
Now, the scene data is like: It sets a gray sphere of radius 1 at (0,0,-3). It sets a white light source at the origin.
2
amb: 0.3 0.3 0.3
sphere
pos: 0.0 0.0 -3.0
rad: 1
dif: 0.3 0.3 0.3
spe: 0.5 0.5 0.5
shi: 1
light
pos: 0 0 0
col: 1 1 1
Mine looks very weird :
//check ray intersection with the sphere
boolean intersectsWithSphere(struct point rayPosition, struct point rayDirection, Sphere sp,float* t){
//float a = (rayDirection.x * rayDirection.x) + (rayDirection.y * rayDirection.y) +(rayDirection.z * rayDirection.z);
// value for a is 1 since rayDirection vector is normalized
double radius = sp.radius;
double xc = sp.position[0];
double yc =sp.position[1];
double zc =sp.position[2];
double xo = rayPosition.x;
double yo = rayPosition.y;
double zo = rayPosition.z;
double xd = rayDirection.x;
double yd = rayDirection.y;
double zd = rayDirection.z;
double b = 2 * ((xd*(xo-xc))+(yd*(yo-yc))+(zd*(zo-zc)));
double c = (xo-xc)*(xo-xc) + (yo-yc)*(yo-yc) + (zo-zc)*(zo-zc) - (radius * radius);
float D = b*b + (-4.0f)*c;
//ray does not intersect the sphere
if(D < 0 ){
return false;
}
D = sqrt(D);
float t0 = (-b - D)/2 ;
float t1 = (-b + D)/2;
//printf("D=%f",D);
//printf(" t0=%f",t0);
//printf(" t1=%f\n",t1);
if((t0 > 0) && (t1 > 0)){
*t = min(t0,t1);
return true;
}
else {
*t = 0;
return false;
}
}
Below is the trace() function:
unsigned char* trace(struct point rayPosition, struct point rayDirection, Sphere * totalspheres) {
struct point tempRayPosition = rayPosition;
struct point tempRayDirection = rayDirection;
float f=0;
float tnear = INFINITY;
boolean sphereIntersectionFound = false;
int sphereIndex = -1;
for(int i=0; i < num_spheres ; i++){
float t = INFINITY;
if(intersectsWithSphere(tempRayPosition,tempRayDirection,totalspheres[i],&t)){
if(t < tnear){
tnear = t;
sphereIntersectionFound = true;
sphereIndex = i;
}
}
}
if(sphereIndex < 0){
//printf("No interesection found\n");
mycolor[0] = 1;
mycolor[1] = 1;
mycolor[2] = 1;
return mycolor;
}
else {
Sphere sp = totalspheres[sphereIndex];
//intersection point
hitPoint[0].x = tempRayPosition.x + tempRayDirection.x * tnear;
hitPoint[0].y = tempRayPosition.y + tempRayDirection.y * tnear;
hitPoint[0].z = tempRayPosition.z + tempRayDirection.z * tnear;
//normal at the intersection point
normalAtHitPoint[0].x = (hitPoint[0].x - totalspheres[sphereIndex].position[0])/ totalspheres[sphereIndex].radius;
normalAtHitPoint[0].y = (hitPoint[0].y - totalspheres[sphereIndex].position[1])/ totalspheres[sphereIndex].radius;
normalAtHitPoint[0].z = (hitPoint[0].z - totalspheres[sphereIndex].position[2])/ totalspheres[sphereIndex].radius;
normalizedNormalAtHitPoint[0] = normalize(normalAtHitPoint[0]);
for(int j=0; j < num_lights ; j++) {
for(int k=0; k < num_spheres ; k++){
shadowRay[0].x = lights[j].position[0] - hitPoint[0].x;
shadowRay[0].y = lights[j].position[1] - hitPoint[0].y;
shadowRay[0].z = lights[j].position[2] - hitPoint[0].z;
normalizedShadowRay[0] = normalize(shadowRay[0]);
//R = 2 * ( N dot L) * N - L
reflectionRay[0].x = - 2 * dot(normalizedShadowRay[0],normalizedNormalAtHitPoint[0]) * normalizedNormalAtHitPoint[0].x +normalizedShadowRay[0].x;
reflectionRay[0].y = - 2 * dot(normalizedShadowRay[0],normalizedNormalAtHitPoint[0]) * normalizedNormalAtHitPoint[0].y +normalizedShadowRay[0].y;
reflectionRay[0].z = - 2 * dot(normalizedShadowRay[0],normalizedNormalAtHitPoint[0]) * normalizedNormalAtHitPoint[0].z +normalizedShadowRay[0].z;
normalizeReflectionRay[0] = normalize(reflectionRay[0]);
struct point temp;
temp.x = hitPoint[0].x + (shadowRay[0].x * 0.0001 );
temp.y = hitPoint[0].y + (shadowRay[0].y * 0.0001);
temp.z = hitPoint[0].z + (shadowRay[0].z * 0.0001);
struct point ntemp = normalize(temp);
float f=0;
struct point tempHitPoint;
tempHitPoint.x = hitPoint[0].x + 0.001;
tempHitPoint.y = hitPoint[0].y + 0.001;
tempHitPoint.z = hitPoint[0].z + 0.001;
if(intersectsWithSphere(hitPoint[0],ntemp,totalspheres[k],&f)){
// if(intersectsWithSphere(tempHitPoint,ntemp,totalspheres[k],&f)){
printf("In shadow\n");
float r = lights[j].color[0];
float g = lights[j].color[1];
float b = lights[j].color[2];
mycolor[0] = ambient_light[0] + r;
mycolor[1] = ambient_light[1] + g;
mycolor[2] = ambient_light[2] + b;
return mycolor;
} else {
// point is not is shadow , use Phong shading to determine the color of the point.
//I = lightColor * (kd * (L dot N) + ks * (R dot V) ^ sh)
//(for each color channel separately; note that if L dot N < 0, you should clamp L dot N to zero; same for R dot V)
float x = dot(normalizedShadowRay[0],normalizedNormalAtHitPoint[0]);
if(x < 0)
x = 0;
V[0].x = - rayDirection.x;
V[0].x = - rayDirection.y;
V[0].x = - rayDirection.z;
normalizedV[0] = normalize(V[0]);
float y = dot(normalizeReflectionRay[0],normalizedV[0]);
if(y < 0)
y = 0;
float ar = totalspheres[sphereIndex].color_diffuse[0] * x;
float br = totalspheres[sphereIndex].color_specular[0] * pow(y,totalspheres[sphereIndex].shininess);
float r = lights[j].color[0] * (ar+br);
//----------------------------------------------------------------------------------
float bg = totalspheres[sphereIndex].color_specular[1] * pow(y,totalspheres[sphereIndex].shininess);
float ag = totalspheres[sphereIndex].color_diffuse[1] * x;
float g = lights[j].color[1] * (ag+bg);
//----------------------------------------------------------------------------------
float bb = totalspheres[sphereIndex].color_specular[2] * pow(y,totalspheres[sphereIndex].shininess);
float ab = totalspheres[sphereIndex].color_diffuse[2] * x;
float b = lights[j].color[2] * (ab+bb);
mycolor[0] = r + ambient_light[0];
mycolor[1] = g + ambient_light[1];
mycolor[2] = b+ ambient_light[2];
return mycolor;
}
}
}
}
}
The code calling trace() looks like :
void draw_scene()
{
//Aspect Ratio
double a = WIDTH / HEIGHT;
double angel = tan(M_PI * 0.5 * fov/ 180);
ray[0].x = 0.0;
ray[0].y = 0.0;
ray[0].z = 0.0;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
unsigned int x,y;
float sx, sy;
for(x=0;x < WIDTH;x++)
{
glPointSize(2.0);
glBegin(GL_POINTS);
for(y=0;y < HEIGHT;y++)
{
sx = (((x + 0.5) / WIDTH) * 2.0 ) - 1;
sy = (((y + 0.5) / HEIGHT) * 2.0 ) - 1;;
sx = sx * angel * a;
sy = sy * angel;
//set ray direction
ray[1].x = sx;
ray[1].y = sy;
ray[1].z = -1;
normalizedRayDirection[0] = normalize(ray[1]);
unsigned char* color = trace(ray[0],normalizedRayDirection[0],spheres);
unsigned char x1 = color[0] * 255;
unsigned char y1 = color[1] * 255;
unsigned char z1 = color[2] * 255;
plot_pixel(x,y,x1 %256,y1%256,z1%256);
}
glEnd();
glFlush();
}
}
There could be many, many problems with the code/understanding.
I haven't taken the time to understand all your code, and I'm definitely not a graphics expert, but I believe the problem you have is called "surface acne". In this case it's probably happening because your shadow rays are intersecting with the object itself. What I did in my code to fix this is add epsilon * hitPoint.normal to the shadow ray origin. This effectively moves the ray away from your object a bit, so they don't intersect.
The value I'm using for epsilon is the square root of 1.19209290 * 10^-7, as that is the square root of a constant called EPSILON that is defined in the particular language I'm using.
What possible reason do you have for doing this (in the non-shadow branch of trace (...)):
V[0].x = - rayDirection.x;
V[0].x = - rayDirection.y;
V[0].x = - rayDirection.z;
You might as well comment out the first two computations since you write the results of each to the same component. I think you probably meant to do this instead:
V[0].x = - rayDirection.x;
V[0].y = - rayDirection.y;
V[0].z = - rayDirection.z;
That said, you should also avoid using GL_POINT primitives to cover a 2x2 pixel quad. Point primitives are not guaranteed to be square, and OpenGL implementations are not required to support any size other than 1.0. In practice, most support 1.0 - ~64.0 but glDrawPixels (...) is a much better way of writing 2x2 pixels, since it skips primitive assembly and the above mentioned limitations. You are using immediate mode in this example anyway, so glRasterPos (...) and glDrawPixels (...) are still a valid approach.
It seems you are implementing the formula here, but you deviate at the end from the direction the article takes.
First the article warns that D & b can be very close in value, so that -b + D gets you a very limited number. They suggest an alternative.
Also, you are testing that both t0 & t1 > 0. This doesn't have to be true for you to hit the sphere, you could be inside of it (though you obviously should not be in your test scene).
Finally, I would add a test at the beginning to confirm that the direction vector is normalized. I've messed that up more than once in my renderers.
I am trying to generate an array of n points that are equidistant from each other and lie on a circle in C. Basically, I need to be able to pass a function the number of points that I would like to generate and get back an array of points.
It's been a really long time since I've done C/C++, so I've had a stab at this more to see how I got on with it, but here's some code that will calculate the points for you. (It's a VS2010 console application)
// CirclePoints.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "stdio.h"
#include "math.h"
int _tmain()
{
int points = 8;
double radius = 100;
double step = ((3.14159265 * 2) / points);
double x, y, current = 0;
for (int i = 0; i < points; i++)
{
x = sin(current) * radius;
y = cos(current) * radius;
printf("point: %d x:%lf y:%lf\n", i, x, y);
current += step;
}
return 0;
}
Try something like this:
void make_circle(float *output, size_t num, float radius)
{
size_t i;
for(i = 0; i < num; i++)
{
const float angle = 2 * M_PI * i / num;
*output++ = radius * cos(angle);
*output++ = radius * sin(angle);
}
}
This is untested, there might be an off-by-one hiding in the angle step calculation but it should be close.
This assumes I understood the question correctly, of course.
UPDATE: Redid the angle computation to not be incrementing, to reduce float precision loss due to repeated addition.
Here's a solution, somewhat optimized, untested. Error can accumulate, but using double rather than float probably more than makes up for it except with extremely large values of n.
void make_circle(double *dest, size_t n, double r)
{
double x0 = cos(2*M_PI/n), y0 = sin(2*M_PI/n), x=x0, y=y0, tmp;
for (;;) {
*dest++ = r*x;
*dest++ = r*y;
if (!--n) break;
tmp = x*x0 - y*y0;
y = x*y0 + y*x0;
x = tmp;
}
}
You have to solve this in c language:
In an x-y Cartesian coordinate system, the circle with centre coordinates (a, b) and radius r is the set of all points (x, y) such that
(x - a)^2 + (y - b)^2 = r^2
Here's a javascript implementation that also takes an optional center point.
function circlePoints (radius, numPoints, centerX, centerY) {
centerX = centerX || 0;
centerY = centerY || 0;
var
step = (Math.PI * 2) / numPoints,
current = 0,
i = 0,
results = [],
x, y;
for (; i < numPoints; i += 1) {
x = centerX + Math.sin(current) * radius;
y = centerY + Math.cos(current) * radius;
results.push([x,y]);
console.log('point %d # x:%d, y:%d', i, x, y);
current += step;
}
return results;
}