trevortomesh
12/7/2016 - 3:22 AM

rayTrace

#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);
}