Im playing around with matrices, with a view to doing 3D transformation in GDI (for the fun of it). At the moment i'm checking that im getting the right values from identity matrix given a representation of four vertices arranged in a square. I've been scratching my head as to why it's not giving expected output. I have done my research but can't see what i am doing wrong here.
Here's my definition of matrix.
typedef struct m{
float _m01, _m05, _m09, _m13;
float _m02, _m06, _m10, _m14;
float _m03, _m07, _m11, _m15;
float _m04, _m08, _m12, _m16;
}mat;
struct m matIdentity(struct m *m1){
m1->_m01 = 1.0; m1->_m05 = 0.0; m1->_m09 = 0.0; m1->_m13 = 0.0;
m1->_m02 = 0.0; m1->_m06 = 1.0; m1->_m10 = 0.0; m1->_m14 = 0.0;
m1->_m03 = 0.0; m1->_m07 = 0.0; m1->_m11 = 1.0; m1->_m15 = 0.0;
m1->_m04 = 0.0; m1->_m08 = 0.0; m1->_m12 = 0.0; m1->_m16 = 1.0;
}
Here's making use of matrix with
struct m matrix;
matIdentity(&matrix);
//represent 4 vertices(x,y,z,w);
float square[4][4] = {
{0.0, 0.0, 0.0, 1.0},
{0.0, 20.0, 0.0, 1.0},
{20.0, 20.0, 0.0, 1.0},
{20.0, 0.0, 0.0, 1.0}
};
float result[4][4];
int i = 0;
for(i = 0; i < 4; i++){
result[i][1] = (matrix._m01 * square[i][0]) + (matrix._m05 * square[i][1]) + (matrix._m09 * square[i][2]) + (matrix._m13 * square[i][3]);
result[i][2] = (matrix._m02 * square[i][0]) + (matrix._m06 * square[i][1]) + (matrix._m10 * square[i][2]) + (matrix._m14 * square[i][3]);
result[i][3] = (matrix._m03 * square[i][0]) + (matrix._m07 * square[i][1]) + (matrix._m11 * square[i][2]) + (matrix._m15 * square[i][3]);
result[i][4] = (matrix._m04 * square[i][0]) + (matrix._m08 * square[i][1]) + (matrix._m12 * square[i][2]) + (matrix._m16 * square[i][3]);
}
char strOutput[500];
sprintf(strOutput,"%f %f %f %f\n %f %f %f %f\n %f %f %f %f\n %f %f %f %f\n ",
result[0][0], result[0][1], result[0][2], result[0][3],
result[1][0], result[1][1], result[1][2], result[1][3],
result[2][0], result[2][1], result[2][2], result[2][3],
result[3][0], result[3][1], result[3][2], result[3][3]
);
I have a feeling the problem is somewhere to do with multiplying a row based representation of vertices using a column major matrix. Can anyone please suggest how i should be doing this.
I don't understand why you don't use array first, then start to use array and iteration, and in the end give up iteration. Please, such program can only cause confusion.
The correct formula is C(i, j)=sigma(A(i, k)*B(k, j), k=1..n), where C=AB and n is 4 for your case.
(e.g., this line should be like: result[i][0] = (matrix._m01 * square[0][i]) + (matrix._m02 * square[1][i]) + (matrix._m03 * square[2][i]) + (matrix._m04 * square[3][i]); )Write a simple nested for-iteration to calculate this...
This is not for one vector, but n vectors....
This is not matrix multiplication. Multiplying a vector by a matrix goes like this:
float mat[4][4];
float vec_in[4];
float vec_out[4];
// todo: initialize values
for (int j = 0; j < 4; ++j)
{
vec_out[j] = 0.0f;
for (int i = 0; i < 4; ++i)
{
vec_out[j] += vec_in[i] * mat[i][j];
}
}
Related
Im writing a C code programm that calcultates sine and cosine of a given angle without using the Sine and Cosine Functions of the Math.h library.
But the problem I am facing right now is that i can only calculate the sine and cosine of the Angles between -90° - 90° (so the angles in the first and fourth quadrant). The Cosine(100) = Cosine(80) with a negative operator. So my way of thinking would be to just write code that whenever it gets an angle that is greater than 90 and smaller than 270, it should just substract the additional value from 90; so in the case of Cos(240) that would be the same as Cos(90-150) with an inverted operator infront.
How should one go about this, without having to write 180-if statements?
#include <stdio.h>
#include <math.h>
int main() {
double alpha[29];
alpha[0] = 45.00000000;
alpha[1] = 26.56505118;
alpha[2] = 14.03624347;
alpha[3] = 7.12501635;
alpha[4] = 3.57633437;
alpha[5] = 1.78991061;
alpha[6] = 0.89517371;
alpha[7] = 0.44761417;
alpha[8] = 0.22381050;
alpha[9] = 0.11190568;
alpha[10] = 0.05595289;
alpha[11] = 0.02797645;
alpha[12] = 0.01398823;
alpha[13] = 0.00699411;
alpha[14] = 0.00349706;
alpha[15] = 0.00174853;
alpha[16] = 0.00087426;
alpha[17] = 0.00043713;
alpha[18] = 0.00021857;
alpha[19] = 0.00010928;
alpha[20] = 0.00005464;
alpha[21] = 0.00002732;
alpha[22] = 0.00001366;
alpha[23] = 0.00000683;
alpha[24] = 0.00000342;
alpha[25] = 0.00000171;
alpha[26] = 0.00000085;
alpha[27] = 0.00000043;
alpha[28] = 0.00000021;
double x = 0.60725294;
double y = 0;
double winkel = -150;
double theta = winkel;
double xs;
double ys;
int i = 0;
}
while ( i < 29 ){
printf("This is run number %d with theta = %lf \n", i, theta);
xs = y / pow(2, i);
ys = x / pow(2, i);
if (theta <= 0){
x = x + xs;
y = y - ys;
theta = theta + alpha[i];
} else {
x = x - xs;
y = y + ys;
theta = theta - alpha[i];
};
printf("x = %lf and y = %lf \n \n",x,y);
i++;
}
printf("cosine = %lf\n", x);
printf("sine = %lf\n", y);
return 0;
}
cos(x) = cos(-x)
cos(x) = cos(x%360) if x is in degrees and x is positive
those identities should be sufficient to understand what to do, right?
likewise sin(-x) = -sin(x)
sin(x) = sin(x%360) if x is in degrees and x is positive
I'm trying to implement an easy backpropagation algorithm for an exam (I'm a beginner programmer).
I've got a set of arrays and I generate random weights to start the algorithm.
I implemented the activation function following the math formula:
formula
(where x index are for inputs and y index is for hidden neuron input)
My problem is that I get some summation results with very high exponential values that are incompatible with what I'd expect to be.
Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#define INPUT_NEURONS 4
#define HIDDEN_NEURONS 7
#define OUTPUT_NEURONS 3
#define MAX_SAMPLES 150
#define LEARNING_RATE 0.1
#define RAND_WEIGHT ((double)rand()/(RAND_MAX+1))
double IHweight[INPUT_NEURONS][HIDDEN_NEURONS]; /* in->hid weight */
double HOweight[HIDDEN_NEURONS][OUTPUT_NEURONS]; /* hid->out weight */
//activation
double inputs[MAX_SAMPLES][INPUT_NEURONS];
double hidden[HIDDEN_NEURONS];
double target[MAX_SAMPLES][OUTPUT_NEURONS];
double actual[OUTPUT_NEURONS];
//errors
double errO[OUTPUT_NEURONS];
double errH[HIDDEN_NEURONS];
double Error = 0.0;
int sample = 0;
typedef struct {
double sepal_lenght;
double sepal_width;
double petal_lenght;
double petal_width;
double output[OUTPUT_NEURONS];
} IRIS;
IRIS samples[MAX_SAMPLES] = {
{ 5.1, 3.5, 1.4, 0.2, 0.0, 0.0, 1.0 },
{ 4.9, 3.0, 1.4, 0.2, 0.0, 0.0, 1.0 },
{ 4.7, 3.2, 1.3, 0.2, 0.0, 0.0, 1.0 },
{...},
};
double sigmoid(double val) {
return (1.0 / (1.0 + exp(-val)));
}
double dsigmoid(double val) {
return (val * (1.0 - val));
}
void assignRandomWeights() {
int hid, inp, out;
printf("Initializing weights...\n\n");
for (inp = 0; inp < INPUT_NEURONS; inp++) {
for (hid = 0; hid < HIDDEN_NEURONS; hid++) {
IHweight[inp][hid] = RAND_WEIGHT;
printf("Weights : input %d -> hidden %d: %f\n",
inp, hid, IHweight[inp][hid]);
}
}
for (hid = 0; hid < HIDDEN_NEURONS; hid++) {
for (out = 0; out < OUTPUT_NEURONS; out++) {
HOweight[hid][out] = RAND_WEIGHT;
printf("hidden %d -> output %d: %f\n",
hid, out, HOweight[hid][out]);
}
}
system("pause");
}
void activation() {
int hid, inp, out;
double sumH[HIDDEN_NEURONS] ;
double sumO[OUTPUT_NEURONS];
for (hid = 0; hid < HIDDEN_NEURONS; hid++) {
for (inp = 0; inp < INPUT_NEURONS; inp++) {
sumH[hid] += (inputs[sample][inp] * IHweight[inp][hid]);
printf("\n%d Input %d = %.1f Weight = %f sumH = %g",
sample, inp, inputs[sample][inp], IHweight[inp][hid], sumH[hid]);
}
hidden[hid] = sigmoid(sumH[hid]);
printf("\nHidden neuron %d activation = %f", hid, hidden[hid]);
}
for (out = 0; out < OUTPUT_NEURONS; out++) {
for (hid = 0; hid < HIDDEN_NEURONS; hid++) {
sumO[out] += (hidden[hid] * HOweight[hid][out]);
printf("\n%d Hidden %d = %f Weight = %f sumO = %g",
sample, hid, hidden[hid], HOweight[hid][out], sumO[out]);
}
actual[out] = sigmoid(sumO[out]);
printf("\nOutput neuron %d activation = %f", out, actual[out]);
}
}
main () {
srand(time(NULL));
assignRandomWeights();
for (int epoch = 0; epoch < 1; epoch++) {
for (int i = 0; i < 1; i++) {
sample = rand() % MAX_SAMPLES;
inputs[sample][0] = samples[sample].sepal_lenght;
inputs[sample][1] = samples[sample].sepal_width;
inputs[sample][2] = samples[sample].petal_lenght;
inputs[sample][3] = samples[sample].petal_width;
target[sample][0] = samples[sample].output[0];
target[sample][1] = samples[sample].output[1];
target[sample][2] = samples[sample].output[2];
activation();
}
}
}
I'm using a lot of printf() to check my results and i get
...
41 Input 0 = 4.5 Weight = 0.321014 sumH = 1.31886e+267
41 Input 1 = 2.3 Weight = 0.772369 sumH = 1.31886e+267
41 Input 2 = 1.3 Weight = 0.526123 sumH = 1.31886e+267
41 Input 3 = 0.3 Weight = 0.271881 sumH = 1.31886e+267
Hidden neuron 6 activation = 1.000000
...
41 Hidden 0 = 0.974952 Weight = 0.343445 sumO = 1.24176e+267
41 Hidden 1 = 0.917789 Weight = 0.288361 sumO = 1.24176e+267
41 Hidden 2 = 0.999188 Weight = 0.972168 sumO = 1.24176e+267
41 Hidden 3 = 0.989726 Weight = 0.082642 sumO = 1.24176e+267
41 Hidden 4 = 0.979063 Weight = 0.531799 sumO = 1.24176e+267
41 Hidden 5 = 0.972474 Weight = 0.552521 sumO = 1.24176e+267
41 Hidden 6 = 1.000000 Weight = 0.707153 sumO = 1.24176e+267
Output neuron 1 activation = 1.000000
The assignRandomweights() and sigmoid() functions are ok as far as i can tell, the problem is in activation().
Please help me understand why this happens and how to solve it.
Your problem is in these lines
double sumH[HIDDEN_NEURONS];
double sumO[OUTPUT_NEURONS];
You don't initialise them before use. Technically the program behaviour is undefined. Your friendly compiler appears to be setting uninitialised variables to large values. (Other platforms such as Itanium will trap a "Not a Thing").
A simple remedy is to use double sumH[HIDDEN_NEURONS] = {0}; etc. which will set every element to zero.
check this line:
double sumH[HIDDEN_NEURONS] ;
and this line:
sumH[hid] += (inputs[sample][inp] * IHweight[inp][hid]);
you have declared the sumH[] without setting to zero every member of it, so, it starts from an arbitrary value as there is no definition of sumH[hid]
you can use:
for(unsigned int i=0; i<HIDDEN_NEURONS; i++) sumH[i] = 0;
before any use of it (if you don't like malloc() or ZeroMemory()), for example...
My homework is to write a C program with openGL/Glut which, after getting groups of 4 points by mouse click (points with 3 coordinates), should draw a bezier curve with adaptive algorithm. At a theoretical level it's clear how the algorithm works but I don't know how to put that in C code. I mean that at lesson we saw that the 4 control points could have a shape similar to a "trapeze" and then the algorithm calculates the two "heights" and then checks if they satisfy a tollerance. The problem is that the user might click everywhere in the screen and the points might not have trapeze-like shape...so, where can I start from? This is all I have
This is the cole I have written, which is called each time a control point is added:
if (bezierMode == CASTELJAU_ADAPTIVE) {
glColor3f (0.0f, 0.8f, 0.4f); /* draw adaptive casteljau curve in green */
for(i=0; i+3<numCV; i += 3)
adaptiveDeCasteljau3(CV, i, 0.01);
}
void adaptiveDeCasteljau3(float CV[MAX_CV][3], int position, float tolerance) {
float x01 = (CV[position][0] + CV[position+1][0]) / 2;
float y01 = (CV[position][1] + CV[position+1][1]) / 2;
float x12 = (CV[position+1][0] + CV[position+2][0]) / 2;
float y12 = (CV[position+1][1] + CV[position+2][1]) / 2;
float x23 = (CV[position+2][0] + CV[position+3][0]) / 2;
float y23 = (CV[position+2][1] + CV[position+3][1]) / 2;
float x012 = (x01 + x12) / 2;
float y012 = (y01 + y12) / 2;
float x123 = (x12 + x23) / 2;
float y123 = (y12 + y23) / 2;
float x0123 = (x012 + x123) / 2;
float y0123 = (y012 + y123) / 2;
float dx = CV[3][0] - CV[0][0];
float dy = CV[3][1] - CV[0][1];
float d2 = fabs(((CV[1][0] - CV[3][0]) * dy - (CV[1][1] - CV[3][1]) * dx));
float d3 = fabs(((CV[2][0] - CV[3][0]) * dy - (CV[2][1] - CV[3][1]) * dx));
if((d2 + d3)*(d2 + d3) < tolerance * (dx*dx + dy*dy)) {
glBegin(GL_LINE_STRIP);
glVertex2f(x0123, y0123);
glEnd();
return;
}
float tmpLEFT[4][3];
float tmpRIGHT[4][3];
tmpLEFT[0][0] = CV[0][0];
tmpLEFT[0][1] = CV[0][1];
tmpLEFT[1][0] = x01;
tmpLEFT[1][1] = y01;
tmpLEFT[2][0] = x012;
tmpLEFT[2][1] = y012;
tmpLEFT[3][0] = x0123;
tmpLEFT[3][1] = y0123;
tmpRIGHT[0][0] = x0123;
tmpRIGHT[0][1] = y0123;
tmpRIGHT[1][0] = x123;
tmpRIGHT[1][1] = y123;
tmpRIGHT[2][0] = x23;
tmpRIGHT[2][1] = y23;
tmpRIGHT[3][0] = CV[3][0];
tmpRIGHT[3][1] = CV[3][1];
adaptiveDeCasteljau3(tmpLEFT, 0, tolerance);
adaptiveDeCasteljau3(tmpRIGHT, 0, tolerance);
}
and obviously nothing is drawn. Do you have any idea?
the Begin / End should engulf your whole loop, not being inside for each isolated vertex !
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.
#include <GL/glut.h>
#include <GL/gl.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define N 200
typedef struct vertex{
float x; // x position of the point
float y; // y position of the point
float r; // red color component of the point
float g; // green color component of the point
float b; // blue color component of the point
char isVisited;
}Vertex;
Vertex *borderLines,*interPolationLines;
int vertex_Count;// total vertex
int counter;//counts matched y coordinates
FILE *f,*g;
void readTotalVertexCount(){
if((f = fopen("vertex.txt","r"))==NULL){
printf("File could not been read\n");
return ;
}
fscanf(f,"%d",&vertex_Count);
/*if((g = fopen("points.txt","w"))==NULL){
return ;
}*/
}
void readVertexCoordinatesFromFile(){
Vertex v[vertex_Count];
borderLines = (Vertex *)calloc(N*vertex_Count,sizeof(Vertex));
interPolationLines = (Vertex *)calloc(N*N*(vertex_Count-1),sizeof(Vertex));
int i = 0;int j;
//read vertexes from file
while(i<vertex_Count){
fscanf(f,"%f",&(v[i].x));
fscanf(f,"%f",&(v[i].y));
fscanf(f,"%f",&(v[i].r));
fscanf(f,"%f",&(v[i].g));
fscanf(f,"%f",&(v[i].b));
//printf("%f %f \n",v[i].x,v[i].y);
i++;
}
Vertex *borderLine,*temp;
float k,landa;
// draw border line actually I am doing 1D Interpolation with coordinates of my vertexes
for (i = 0;i < vertex_Count;i++){
int m = i+1;
if(m==vertex_Count)
m = 0;
borderLine = borderLines + i*N;
for(j = 0;j < N; j++){
k = (float)j/(N - 1);
temp = borderLine + j;
landa = 1-k;
//finding 1D interpolation coord. actually they are borders of my convex polygon
temp->x = v[i].x*landa + v[m].x*k;
temp->y = v[i].y*landa + v[m].y*k;
temp->r = v[i].r*landa + v[m].r*k;
temp->g = v[i].g*landa + v[m].g*k;
temp->b = v[i].b*landa + v[m].b*k;
temp->isVisited = 'n'; // I didn't visit this point yet
//fprintf(g,"%f %f %f %f %f\n",temp->x,temp->y,temp->r,temp->g,temp->b);
}
}
/* here is actual place I am doing 2D Interpolation
I am traversing along the border of the convex polygon and finding the points have the same y coordinates
Between those two points have same y coord. I am doing 1D Interpolation*/
int a;counter = 0;
Vertex *searcherBorder,*wantedBorder,*interPolationLine;
int start = N*(vertex_Count); int finish = N*vertex_Count;
for(i = 0;i< start ;i++){
searcherBorder = i + borderLines;
for(j = i - i%N + N +1; j< finish; j++){
wantedBorder = j + borderLines;
if((searcherBorder->y)==(wantedBorder->y) && searcherBorder->isVisited=='n' && wantedBorder->isVisited=='n'){
//these points have been visited
searcherBorder->isVisited = 'y';
wantedBorder->isVisited = 'y';
interPolationLine = interPolationLines + counter*N;
//counter variable counts the points have same y coordinates.
counter++;
//printf("%d %d %d\n",i,j,counter);
//same as 1D ınterpolation
for(a= 0;a< N;a++){
k = (float)a/(N - 1);
temp = interPolationLine + a;
landa = 1-k;
temp->x = (wantedBorder->x)*landa + (searcherBorder->x)*k;
temp->y = (wantedBorder->y)*landa + (searcherBorder->y)*k;
temp->r = (wantedBorder->r)*landa + (searcherBorder->r)*k;
temp->g = (wantedBorder->g)*landa + (searcherBorder->g)*k;
/*if(temp->x==temp->y)
printf("%f %f \n",wantedBorder->x,searcherBorder->x);*/
temp->b = (wantedBorder->b)*landa + (searcherBorder->b)*k;
}
}
}
}
fclose(f);
}
void display(void){
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0,1.0,1.0);
int i,j;
Vertex *interPol,*temp;
glBegin (GL_POINTS);
for(i = 0;i< counter;i++){
interPol = interPolationLines + i*N;
for(j = 0;j< N;j++){
temp = interPol + j;
glColor3f((temp)->r,(temp)->g,(temp)->b);
//fprintf(g,"%f %f \n",(temp)->x,(temp)->y);
glVertex2f ((temp)->x,(temp)->y);
}
}
//printf("%d\n",counter);
fclose(g);
glEnd ();
glFlush();
}
void init(void){
glutInitDisplayMode( GLUT_RGB | GLUT_SINGLE);
glutInitWindowSize(900,500);
glutInitWindowPosition(200,100);
glutCreateWindow("2D InterPolation");
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glShadeModel(GL_SMOOTH);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
}
int main(int argc, char** argv)
{
readTotalVertexCount();
readVertexCoordinatesFromFile();
glutInit(&argc,argv);
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
I am implementing 2D Interpolation of a convex polygon and my code does not care about concav.my code works for some convex polygons but for others fail.For those my code fails it does not draw middle of the polygon.it only draws an upper and lower triangle.it reads vertexes from file vertex.txt and its format:x co,y co,red,green,blue color info of that point like below and for the values below my code fails.Thanks for replies in advance.I will get mad.
7
0.9 0.4 1.0 0.0 1.0
0.8 0.2 1.0 0.0 1.0
0.5 0.1 1.0 0.0 0.0
0.3 0.3 0.0 0.0 1.0
0.3 0.35 0.0 0.0 1.0
0.4 0.4 0.0 1.0 0.0
0.6 0.5 1.0 1.0 1.0
Without fully debugging your program, I'm suspicious of the line that says, for(j = i - i%N + N +1; j< finish; j++){. I don't know exactly what you're intending to do, but it just looks suspicious. Furthermore, I would recommend a different algorithm:
Trace around the polygon
Mark any edges that span the desired y-value
Corner cases aside, there's only a solution if you find exactly two hits.
Calculate the intersection of the edges with the y-value
Perform the x-interpolation
Also, concise questions are better than, "Why doesn't my program work?" Forgive me but it feels like a homework problem.
Note: Should this be a comment instead of an answer? I'm new here...