trevortomesh
12/7/2016 - 5:45 AM

## raytrace.ino

``````#include "LCD4884.h"

// x-y-relation for prepairing pictures is 28 x 19 ~ 3 x 2
// because LCD-pixels in 84x48 matrix seem to bee not quadratic
// use a high density 3x2 picture, resize to 84x48 non propotional
// and change to black and white
// google for bmp to pic converter to prepare include-file

#define DELAY1 200
#define DELAY2 1000
#define DELAY3 5000
#define height 19
#define width 28
#define LCD_BACKLIGHT_PIN  7
unsigned char bildbmp[height*width];

//----------- Our math functions ------------
float length(float x,float y,float z){
return sqrt(x*x+y*y+z*z);
}

float norm(int x, int y,int z){
float l = length(x,y,z);
return x/1, y/1, z/1;
}

float dot(float xa, float ya, float za, float xb, float yb, float zb){
return xa*xb+ya*yb + za*zb;
}
//-------------------------------------------

// define the camera
float ex = 0;
float ey = 1;
float ez = -1.5;
float fov = 90;

float tmin = .1;
float tmax = 100;

int maxSteps = 45;

//define light
float lx, ly, lz = norm(.2,.5,-.6);

//Distance Field Functions----------------
float plane(int x, int y, int z){
return y; //this is silly
}

float sphere(float x, float y, float z, float radius){
float manhattanDistance = x + y + z;
return manhattanDistance; //because.. good enough!
}
}
//----------------------------------------

float unio(float a, float am, float b, float bm){
if(a < b){
return a, am;
}

else return b, bm;
}

float scene(float x, float y, float z){
float d = tmax;
float m = 0;
d, m = unio(d, m, plane(x, y, z), 255);
d, m = unio(d, m, sphere(x, y-1, z, .5), 0);
return d,m;

}

float sceneNormal(float x, float y, float z){
float eps = 0.1;
float xa = scene(x+eps, y, z);
float xb = scene(x, y+eps, z);

float ya = scene(x, y+eps, z);
float yb = scene(x, y-eps ,z);
float za = scene(x, y, z+eps);
float zb = scene(x, y, z-eps);
return norm(xa-xb, ya-yb, za-zb);
}

float noDither(int x,int y, float gradient[], float value){
float whole = floor(value * sizeof(gradient));
float fraction = value * sizeof(gradient) - whole;

if(fraction < 1.0/7.0){
return low;
}

if(fraction < 2.0/7.0){
if ((x+1) % 3 == 0 && y % 3 == 0){
return high;

}
else return low;

}

if( fraction < 3.0/7.0){
if(x%2==0 && y%2==0){
return high;

}
else return low;

}

if(fraction < 4.0/7.0){
if(x%2==0 && y%2==0 || x%2!=0 && y%2!=0){
return high;

}
else return low;

}

if(fraction < 5.0/7.0){
if(x%2==0 && (y+1)%2==0){
return low;

}
else return high;

}

if(fraction < 6.0/7.0){
if((x+1)%3==0 && y%3==0){
return low;

}
else return high;

}
return high;
}

float getShadowPoint( int t, int x, int y, int z){
return x+lx*t, y+ly*t, z+lz*t;
}

//t starts at 0.2 so the shadow ray doesn't intersect
//the object it's trying to shadow
float res=1;
float t = 0.2;
float distance = 0;
float sx = 0;
float sy = 0;
float sz = 0;
for(int i = 1; i < 6; i++){
sx, sy, sz = getShadowPoint(t, x, y, z);
distance = scene(sx, sy, sz); //we don't care about the color
res = min(res, 2 * distance / t); //increase 2 to get sharper shadows
t += min(max(distance, .02), .2);
if(distance < .05 or t > 10.0){
break;
}
}
return min(max(res, 0), 1);
}

//calculates the final lighting and color
float render(int x, int y, int t, float tx, float ty, float tz, float rx, float ry, float rz, int color){
float nx, ny, nz = sceneNormal(tx, ty, tz);
float light = 0;
light += min(max(dot(nx, ny, nz, lx, ly, lz), 0), 1); //sun light
light = min(max(light, 0), 1); //clamp final light value

}

float getRayDirection(int x, int y){
return norm(x / 64 - 1, (128 - y) / 64 - 1, 90 / fov);
}

float getTestPoint(float t, float rx, float ry, float rz){
return ex + rx * t, ey + ry * t, ez + rz * t;
}

float trace(int x,int y){
float rx, ry, rz = getRayDirection(x, y);
float tx = 0;
float ty = 0;
float tz = 0;
float t = 0;
float distance = 0;
int color = 0;
for(int i = 1; i < maxSteps; i++){
tx, ty, tz = getTestPoint(t, rx, ry, rz);
distance, color = scene(tx, ty, tz);
//--the test point is close enough, render
if(distance < .05){
return render(x, y, t, tx, ty, tz, rx, ry, rz, color);
}
//--the test point is too far, give up, draw the sky
if(distance >= tmax){
break;
}
//--move forward by some fraction
t += distance * .7;
}
}

void setup()
{
Serial.begin(9600);
lcd.LCD_init(); // creates instance of LCD
for(int i = 0; i < width*height; i+=2){
bildbmp[i] = 0x00;
bildbmp[i+1] = 0xFF;

}
}

void loop()
{
digitalWrite(LCD_BACKLIGHT_PIN, LOW);
unsigned char i=0, line=0, pos=0, offset;
unsigned char mychar;
int x = 0;
int y = 0;
/*********** 1st ***********/
lcd.LCD_clear(); // blanks the display
lcd.LCD_draw_bmp_pixel(0,0, bildbmp, 84,48);
for(x = 0; x < width; x++){
for(y = 0; y < height; y++){
Serial.println(trace(x,y));

}
}
}
``````