#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
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(float x, float y,float 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(float x, float y, float z){
return y; //this is silly
}
float sphere(float x, float y, float z, float radius){
float manhattanDistance = x + y + z;
if(manhattanDistance > radius * 2){
return manhattanDistance; //because.. good enough!
}
return length(x,y,z) - radius;
}
//----------------------------------------
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), 0);
d, m = unio(d, m, sphere(x, y-1, z, .5), 1);
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 white[4] = {255,255,255,0};
float black[4] = {0,0,0,255};
/*
local function dither(x, y, gradient, value)
local whole = flr(value * #gradient)
local fraction = value * #gradient - whole
local low = gradient[min(whole + 1, #gradient)]
local high = gradient[min(min(whole + 1, #gradient) + 1, #gradient)]
if fraction < 1/7 then return low end
if fraction < 2/7 then
if (x+1)%3==0 and y%3==0 then
return high
else return low
end
end
if fraction < 3/7 then if x%2==0 and y%2==0 then return high else return low end end
if fraction < 4/7 then if (x%2==0 and y%2==0) or (x%2~=0 and y%2~=0) then return high else return low end end
if fraction < 5/7 then if x%2==0 and (y+1)%2==0 then return low else return high end end
if fraction < 6/7 then if (x+1)%3==0 and y%3==0 then return low else return high end end
return high
end
}*/
float getShadowPoint( float t, float x, float y, float z){
return x+lx*t, y+ly*t, z+lz*t;
}
float shadow(float x,float y,float z){
//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(float x, float y, float t, float tx, float ty, float tz, float rx, float ry, float rz, float 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 *= shadow(tx,ty,tz); //shadow color
light = min(max(light, 0), 1); //clamp final light value
// return dither(x, y, colorGradients[color], light);
return light;
}
float getRayDirection(float x, float 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(float x,float y){
float rx, ry, rz = getRayDirection(x, y);
float tx = 0;
float ty = 0;
float tz = 0;
float t = 0;
float distance = 0;
float 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()
{
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));
}
}
delay(1000);
}