diff options
-rw-r--r-- | .gitignore | 5 | ||||
-rw-r--r-- | README.md | 11 | ||||
-rw-r--r-- | Stuff.rtsc | 31 | ||||
-rw-r--r-- | box.rtsc | 21 | ||||
-rw-r--r-- | cuboids.rtsc | 20 | ||||
-rwxr-xr-x | graytrace | bin | 0 -> 46644 bytes | |||
-rw-r--r-- | graytrace.cpp | 493 | ||||
-rw-r--r-- | room.rtsc | 12 | ||||
-rw-r--r-- | room2.rtsc | 12 | ||||
-rw-r--r-- | simple.rtsc | 4 | ||||
-rw-r--r-- | spheres.rtsc | 53 | ||||
-rw-r--r-- | test.rtsc | 3 |
12 files changed, 665 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6fa4ec2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.DS_Store +b.sh +graytracer +*.png +lodepng.h diff --git a/README.md b/README.md new file mode 100644 index 0000000..f2c2496 --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +Graytracer +========== + +A simple, experimental raytracer that doesn't support colours. + +I made this in my spare time and will probably continue to add features. Or not. I don't know. + +It needs lodepng (as found on [lodev.org](http://lodev.org/lodepng/)). +Just compile with `lodepng.cpp` and `lodepng.h` in the same folder as the source and pass both `graytrace.cpp` and `lodepng.cpp` as arguments to the compiler. + +_- Tom Smeding_ diff --git a/Stuff.rtsc b/Stuff.rtsc new file mode 100644 index 0000000..8079ef7 --- /dev/null +++ b/Stuff.rtsc @@ -0,0 +1,31 @@ +1 -16 3 0 0 0 0 +-2 -8 6 1 +sphere -4 -4 -1 1 +sphere -2 -4 -1 1 +sphere 0 -4 -1 1 +sphere 2 -4 -1 1 +sphere 4 -4 -1 1 +sphere -4 -2 -1 1 +sphere -2 -2 -1 1 +sphere 0 -2 -1 1 +sphere 2 -2 -1 1 +sphere 4 -2 -1 1 +sphere -4 0 -1 1 +sphere -2 0 -1 1 +sphere 0 0 -1 1 +sphere 2 0 -1 1 +sphere 4 0 -1 1 +sphere -4 2 -1 1 +sphere -2 2 -1 1 +sphere 0 2 -1 1 +sphere 2 2 -1 1 +sphere 4 2 -1 1 +sphere -4 4 -1 1 +sphere -2 4 -1 1 +sphere 0 4 -1 1 +sphere 2 4 -1 1 +sphere 4 4 -1 1 +sphere -1 -6 3 1 +triangle 0 1 0 1 1 0 1 1.5 2 + +plane 0 0 -1.5 -0.1 0 1
\ No newline at end of file diff --git a/box.rtsc b/box.rtsc new file mode 100644 index 0000000..add669f --- /dev/null +++ b/box.rtsc @@ -0,0 +1,21 @@ +4 -5 2 0 0 0 0 +2.5 .5 2 1 +triangle 0 0 0 1 0 0 1 0 1 +triangle 0 0 0 1 0 1 0 0 1 + +triangle 0 0 1 1 0 1 1 1 1 +triangle 0 0 1 1 1 1 0 1 1 + +triangle 1 0 0 1 1 0 1 1 1 +triangle 1 0 0 1 1 1 1 0 1 + +triangle 0 1 0 1 1 0 1 1 1 +triangle 0 1 0 1 1 1 0 1 1 + +triangle 0 0 0 1 0 0 1 1 0 +triangle 0 0 0 1 1 0 0 1 0 + +triangle 0 0 0 0 1 0 0 1 1 +triangle 0 0 0 0 1 1 0 0 1 + +plane 0 0 -1 0 0 1
\ No newline at end of file diff --git a/cuboids.rtsc b/cuboids.rtsc new file mode 100644 index 0000000..7bc8ef3 --- /dev/null +++ b/cuboids.rtsc @@ -0,0 +1,20 @@ +7.5 -10 6 7.5 0 0 0 +3 -10 15 1 + +cuboid 1 0 4 4 1 5 +cuboid 2 0 0 3 1 4 + +cuboid 5 0 0 10 1 1 +cuboid 5 0 4 10 1 5 +cuboid 5 0 1 6 1 4 +cuboid 9 0 1 10 1 4 + +cuboid 11 0 0 12 1 5 +cuboid 12 0 3 13 1 4 +cuboid 13 0 2 14 1 3 +cuboid 14 0 3 15 1 4 +cuboid 15 0 0 16 1 5 + +sphere 7.5 0.5 2.5 1 + +plane 0 0 -1 0 1 10
\ No newline at end of file diff --git a/graytrace b/graytrace Binary files differnew file mode 100755 index 0000000..aa0a092 --- /dev/null +++ b/graytrace diff --git a/graytrace.cpp b/graytrace.cpp new file mode 100644 index 0000000..b74d387 --- /dev/null +++ b/graytrace.cpp @@ -0,0 +1,493 @@ +#include <iostream> +#include <iomanip> +#include <fstream> +#include <vector> +#include <string> +#include <sstream> +#include <cmath> +#include <cassert> +#include "lodepng.h" + +#define SCREEN_WIDTH (960) +#define SCREEN_HEIGHT (640) + +#define FLOAT_SMALL_NUM (1e-8) + +using namespace std; + +/* +Scene description file (.rtsc, Ray Trace SCene) +=============================================== + +Z The positive Y-axis points away from you in this picture. +^ _Y +| /' +| / +|/ +#------> X + +A "number" is a floating-point number, unless stated otherwise. +A "coordinate" is three numbers, separated by a space. +Between numbers, any amount of whitespace is tolerated. + +First line: coordinate of camera, the coordinate of point the camera looks at + directly and a number in [0,2π) indicating the amount the camera is rotated + clockwise around the axis between the camera position and the point the camera + looks at. Z normally faces up in this right-handed coordinate system. +Second line: coordinate of the point light source, followed by the intensity in + [0,1]. +Further lines: a string in {triangle,sphere} giving the object shape, a + coordinate giving the centre of the object and further parameters for the + object. For a sphere, give the size (radius); for a triangle give the + coordinates of the two other vertices; for a plane, give the normal the + position is any point on the plane. + +Example file: +1 -15 2 0 0 0 0 +-2 -2 6 1 +sphere 0 0 0 1 +sphere 1 10 -3 1.5 +*/ + +bool samesign(const double a,const double b){ + return (a>0&&b>0)||(a<0&&b<0); +} + +class Vec3{ +public: + double x,y,z; + Vec3(void){x=y=z=0;} + Vec3(double _x,double _y,double _z){x=_x;y=_y;z=_z;} + Vec3& operator=(const Vec3 &other){ + x=other.x; + y=other.y; + z=other.z; + return *this; + } + Vec3 operator+(const Vec3 other) const{return Vec3(x+other.x,y+other.y,z+other.z);} + Vec3 operator-(const Vec3 other) const{return Vec3(x-other.x,y-other.y,z-other.z);} + Vec3 operator*(const double other) const{return Vec3(x*other,y*other,z*other);} + double norm(void) const{return sqrt(x*x+y*y+z*z);} + double dot(const Vec3 &other) const{ + return x*other.x+y*other.y+z*other.z; + } + Vec3 cross(const Vec3 &other) const{ + return Vec3(y*other.z-z*other.y,z*other.x-x*other.z,x*other.y-y*other.x); + } + bool hasnan(void) const{return isnan(x)||isnan(y)||isnan(z);} + Vec3 normalised(void) const{return *this*(1/norm());} + void normalise(void){ + double n=norm(); + x/=n; y/=n; z/=n; + } + /*The Vec3::rotated[XYZ] functions rotate around that axis, anti-clockwise + if looking at the rotation when said axis is pointer towards the observer. + Matrices from en.wikipedia.org/wiki/Rotation_matrix#In_three_dimensions */ + Vec3 rotatedX(double theta) const{ + return Vec3(x,y*cos(theta)-z*sin(theta),y*sin(theta)+z*cos(theta)); + } + Vec3 rotatedY(double theta) const{ + return Vec3(x*cos(theta)+z*sin(theta),y,-x*sin(theta)+z*cos(theta)); + } + Vec3 rotatedZ(double theta) const{ + return Vec3(x*cos(theta)-y*sin(theta),x*sin(theta)+y*cos(theta),z); + } + string str(void) const{ + stringstream ss; + ss<<'['<<x<<' '<<y<<' '<<z<<']'; + return ss.str(); + } +}; + +double angleBetween(const Vec3 &a,const Vec3 &b){ + // / u . v \ + //theta=acos|---------| + // \|u| * |v|/ + double angle=acos(a.dot(b)/(a.norm()*b.norm())); + //if(angle<0)cerr<<"angleBetween(Vec3("<<a.x<<','<<a.y<<','<<a.z<<"),Vec3("<<b.x<<','<<b.y<<','<<b.z<<"))="<<angle<<endl; + return angle; +} + +class Camera{ +public: + Vec3 pos,lookat; + double rot; + Camera(void){pos=Vec3(0,0,0);lookat=Vec3(1,0,0);rot=0;} + Camera(Vec3 p,Vec3 l,double r){pos=p;lookat=l;rot=r;} + Camera(double px,double py,double pz,double lx,double ly,double lz,double r){ + pos=Vec3(px,py,pz); + lookat=Vec3(lx,ly,lz); + rot=r; + } +}; + +class Primitive{ +public: + bool isLight=false; + virtual ~Primitive(void){} + /* A line is represented by the formula: + X = P + D * t + for any t in R, where P is a point on the line, D is the direction vector + of the line and X is any point on the line determined by t. + This method finds the intersection of the line with this object which is + closest to P. It returns Vec3(nan,nan,nan) if no intersections.*/ + virtual Vec3 lineIntersect(const Vec3 &P,const Vec3 &D)=0; + virtual Vec3 normalat(const Vec3 &P)=0; +}; + +class Light:public Primitive{ +public: + Vec3 pos; + double intensity; + Light(void){isLight=true;} + Vec3 lineIntersect(const Vec3 &P,const Vec3 &D){ + return Vec3(NAN,NAN,NAN); + } + Vec3 normalat(const Vec3 &P){ + return Vec3(NAN,NAN,NAN); + } +}; + +class Sphere:public Primitive{ +public: + double size; + Vec3 pos; + /* A sphere is represented by the formula: + r^2 = abs(X - C)^2 + where the radius is r, C is the centre of the sphere and X is any + resulting point on the sphere's surface. + The t of the intersection is given by: (en.wikipedia.org/wiki/Line–sphere_intersection) + t=-(D * (P-C)) plusminus sqrt((D * (P-C))^2 - (P-C)^2 + r^2), + iff |D|=1, and thus the point X of the intersection by: + X = P + D * t.*/ + Vec3 lineIntersect(const Vec3 &P,const Vec3 &D){ + double discr,DPminC; + Vec3 unitD,PminC; + unitD=D.normalised(); //to make sure |D|=1 + PminC=P-pos; + DPminC=unitD.dot(PminC); + discr=DPminC*DPminC-PminC.dot(PminC)+size*size; + if(discr<0)return Vec3(NAN,NAN,NAN); //no intersection + else if(discr<FLOAT_SMALL_NUM)return P+unitD*-DPminC; //one intersection + else { //two intersections, choose that for which abs(t) is smallest + if(abs(-DPminC-sqrt(discr))<abs(-DPminC+discr))return P+unitD*(-DPminC-sqrt(discr)); + else return P+unitD*(-DPminC+sqrt(discr)); + } + } + //returns unit vector *from origin*, only indicating direction. + Vec3 normalat(const Vec3 &P){ + return (P-pos).normalised(); + } +}; + +class Triangle:public Primitive{ +private: + Vec3 normal; +public: + Vec3 pos0,pos1,pos2; + Triangle(void):normal(NAN,NAN,NAN){} + /*Follows the algorithm at http://geomalgorithms.com/a06-_intersect-2.html ; + anything that's unclear should be found there!*/ + Vec3 lineIntersect(const Vec3 &P,const Vec3 &D){ + Vec3 P1(P+D); //P0==P + double ri,si,ti,udotv,udotu,vdotv,wdotu,wdotv; + Vec3 normal=normalat(pos0); + ri=normal.dot(P1-P); //denominator actually + //cerr<<ri<<' '; + if(abs(ri)<FLOAT_SMALL_NUM)return Vec3(NAN,NAN,NAN); //parallel to plane + ri=normal.dot(pos0-P)/ri; + if(ri<0)return Vec3(NAN,NAN,NAN); + Vec3 intersection=P+D*ri; //intersection with plane, maybe with triangle + Vec3 u=pos1-pos0,v=pos2-pos0,w=intersection-pos0; + udotv=u.dot(v); udotu=u.dot(u); vdotv=v.dot(v); wdotu=w.dot(u); wdotv=w.dot(v); + ti=udotv*udotv-udotu*vdotv; //actually denominator for si and ti + si=(udotv*wdotv-vdotv*wdotu)/ti; + if(si<0||si>1)return Vec3(NAN,NAN,NAN); //if si>1, si+ti>1 as well. Saves calculating ti for real + ti=(udotv*wdotu-udotu*wdotv)/ti; + if(ti<0||si+ti>1)return Vec3(NAN,NAN,NAN); + return intersection; //apparently, the ray intersects the triangle as well. Yay! + } + Vec3 normalat(const Vec3 &P){ + if(!normal.hasnan())return normal; + return normal=(pos1-pos0).cross(pos2-pos0).normalised(); + } +}; + +class Plane:public Primitive{ +public: + Vec3 pos,normal; + //Also follows the algorithm from http://geomalgorithms.com/a06-_intersect-2.html + Vec3 lineIntersect(const Vec3 &P,const Vec3 &D){ + Vec3 P1(P+D); //P0==P + double ri; + ri=normal.dot(P1-P); //denominator actually + //cerr<<ri<<' '; + if(abs(ri)<FLOAT_SMALL_NUM)return Vec3(NAN,NAN,NAN); //if parallel to plane + ri=normal.dot(pos-P)/ri; + if(ri<0)return Vec3(NAN,NAN,NAN); + return P+D*ri; + } + Vec3 normalat(const Vec3 &P){ + return normal; + } +}; + +/*x,y are screen coordinates in [0,1], FOV is the horizontal field of view in + radians, N is the number of objects.*/ +double calcColour(double x,double y,double FOV,int N,Camera &camera,vector<Primitive*> objs){ + int i,minatidx=0; //=0 for compiler soothing + double mindist,dist,angle; + Vec3 intersection,midD,midDrot,minatinter; + midD=(camera.lookat-camera.pos).normalised(); + mindist=HUGE_VALF; + //first we rotate midD around Z such that it lies on the XZ plane + angle=atan2(midD.y,midD.x); //get angle relative to XZ plane, around Z axis (thus, horizontal) + midDrot=midD.rotatedZ(-angle); + //then we rotate it around the Y axis (thus, vertically) by the needed amount + midDrot=midDrot.rotatedY(-FOV*((double)1-2*y*SCREEN_HEIGHT/SCREEN_WIDTH)); //negative in front because it rotates the wrong way round. See axes at top of source and description of Vec3::rotated[XYZ] functions. + //then we rotate it back around Z to its previous angle + midDrot=midDrot.rotatedZ(angle); + //then we apply the necessary horizontal rotation (around Z) + midDrot=midDrot.rotatedZ(FOV*((double)1-2*x)); + for(i=0;i<N;i++){ + intersection=objs[i]->lineIntersect(camera.pos,midDrot); + if(!intersection.hasnan()){ //if intersection was found + //now go test whether it's BEHIND the camera... + if((intersection.x-camera.pos.x)*midDrot.x<0||(intersection.y-camera.pos.y)*midDrot.y<0||(intersection.z-camera.pos.z)*midDrot.z<0)continue; + dist=(intersection-camera.pos).norm(); + if(dist<mindist){ + mindist=dist; + minatidx=i; + minatinter=intersection; + } + } + } + if(mindist==HUGE_VALF){ + //cout<<". "; + return 0; + } + + if(objs[minatidx]->isLight){ //if intersection was found + double cross=(camera.pos-intersection).normalised().cross(objs[minatidx]->normalat(intersection)).norm(); //cross==sin(angle between those vectors) + return 1-cross/6; //this looks reasonable + } + //cout<<minatidx<<' '; + Light *light=NULL; + for(i=0;i<N;i++)if(objs[i]->isLight){light=(Light*)objs[i];break;} + if(light==NULL)return 0.1; + Vec3 DlightToInter=minatinter-light->pos; + double distLightToInter=DlightToInter.norm(); + for(i=0;i<N;i++){ + if(objs[i]->isLight)continue; + intersection=objs[i]->lineIntersect(light->pos,DlightToInter); + dist=abs((intersection-light->pos).norm()); + if(!intersection.hasnan()&&abs((intersection-minatinter).norm())>FLOAT_SMALL_NUM&&dist<distLightToInter){ + //cout<<abs((intersection-minatinter).norm())<<' '; + break; + } + } + if(i==N){ + //cout<<"N "; + //return 1; + //return 1-abs((light->pos-minatinter).normalised().cross((camera.pos-minatinter).normalised()).norm()); + Vec3 cam=(camera.pos-minatinter).normalised(),nor=objs[minatidx]->normalat(minatinter),lig=(light->pos-minatinter).normalised(); + /*double diff=asin(cam.cross(nor).norm())-asin(nor.cross(lig).norm()); //ANCIENT + if(diff<0)return 0.1; + else return 0.1+diff*0.9;*/ + //if(abs(factor)>M_PI/2||!samesign(angleBetween(cam,lig)-angleBetween(cam,nor),angleBetween(nor,lig)))return 0.1; + //else return 0.1+(1-abs(factor))*0.9; + /*double ligCamAngle=angleBetween(cam,lig); + double ligNorAngle=angleBetween(nor,lig); + double camNorAngle=angleBetween(cam,nor); + angle=abs(ligCamAngle-2*camNorAngle); //how far, in radians, from the perfect reflection angle + if(angle>M_PI/2)return 0.1; + else return 0.1+(1-angle/M_PI)*0.9;*/ + + /*double factor=angleBetween(cam,nor)-angleBetween(nor,lig); //for spheres + if(factor>M_PI/2)return 0.5+(double)rand()/RAND_MAX*0.5; + if(factor<0)return 0.1; + return 0.1+factor/(M_PI/2)*0.9;*/ + /*double factor=angleBetween(cam,lig)-2*angleBetween(cam,nor); //for cubes + if(abs(factor)>M_PI)return 0.1; + return 0.1+(1-abs(factor)/M_PI)*0.9;*/ + Vec3 reflected=nor*cam.dot(nor)*2-cam; // paulbourke.net/geometry/reflected/ + double diff=angleBetween(lig,reflected); //always >=0 + if(diff>M_PI)return 0.1; + //else return 0.1+0.9*(pow(M_E,-diff)-diff*0.01375541740409698); //y=e^(-x)-x*e^(-pi)/pi gives an exponential thing through (0,1) and (pi,0) + //else return 0.1+0.9*cos(diff/2); + //else return 0.1+0.9*sin(0.5*M_PI*nor.dot(lig))*(1-diff/M_PI); + else return 0.1+0.9*0.5*(sin(M_PI*(nor.dot(lig)-0.5))+1)*(1-diff/M_PI); + } else { + //cout<<abs((intersection-minatinter).norm())<<' '; + return 0.1; + } + //return 1/(mindist+1); + //return (minatinter.z+1)/2; +} + +void makeimage(vector<uint8_t> &image,Camera &camera,vector<Primitive*> objs,int N){ + double x,y; + //double minclr=10000,maxclr=-10000; + //cerr<<"camera.pos="<<camera.pos.str()<<endl; + for(y=0;y<SCREEN_HEIGHT;y++){ + for(x=0;x<SCREEN_WIDTH;x++){ + //cout<<".abcdefghijklmnopqrstuvwxyz"[lround(calcColour((double)x/SCREEN_WIDTH,(double)y/SCREEN_HEIGHT,M_PI/4,N,camera,objs)*26)]<<flush; + //cout<<calcColour((double)x/SCREEN_WIDTH,(double)y/SCREEN_HEIGHT,M_PI/2,N,camera,objs)<<" "<<flush; + image[4*(SCREEN_WIDTH*y+x)+0]= + image[4*(SCREEN_WIDTH*y+x)+1]= + image[4*(SCREEN_WIDTH*y+x)+2]=calcColour((double)x/SCREEN_WIDTH,(double)y/SCREEN_HEIGHT,M_PI/4,N,camera,objs)*255; + image[4*(SCREEN_WIDTH*y+x)+3]=255; + //if(image[4*(SCREEN_WIDTH*y+x)+0]/255.0<minclr)minclr=image[4*(SCREEN_WIDTH*y+x)+0]/255.0; + //if(image[4*(SCREEN_WIDTH*y+x)+0]/255.0>maxclr)maxclr=image[4*(SCREEN_WIDTH*y+x)+0]/255.0; + //cout<<hex<<setw(2)<<(int)image[4*(SCREEN_WIDTH*y+x)+0]<<' '; + } + //cout<<endl; + } + //cout<<"colour: ["<<minclr<<','<<maxclr<<']'<<endl; +} + +int main(int argc,char **argv){ + if(argc!=2){ + cout<<"Please give the scene description file as a command-line parameter."<<endl; + return 1; + } + ifstream in(argv[1]); + if(!in.good()){ + cout<<"Could not open file '"<<argv[1]<<"'."<<endl; + return 1; + } + int N,i; + string type; + Camera camera; + vector<Primitive*> objs; + in>>camera.pos.x>>camera.pos.y>>camera.pos.z>>camera.lookat.x>>camera.lookat.y>>camera.lookat.z>>camera.rot; + if(camera.rot!=0){ + cout<<"No camera rotation is currently supported; the given value of "<<camera.rot<<" should be 0."<<endl; + return 1; + } + objs.push_back(new Light); + in>>((Light*)objs[0])->pos.x>>((Light*)objs[0])->pos.y>>((Light*)objs[0])->pos.z>>((Light*)objs[0])->intensity; + objs[0]->isLight=true; + N=1; + for(i=1;;i++){ + in>>type; + if(!in.good())break; + if(type=="sphere"){ + objs.push_back(new Sphere); + in>>((Sphere*)objs[i])->pos.x>>((Sphere*)objs[i])->pos.y>>((Sphere*)objs[i])->pos.z>>((Sphere*)objs[i])->size; + //((Sphere*)objs[i])->printName(); + N++; + } else if(type=="triangle"){ + objs.push_back(new Triangle); + in>>((Triangle*)objs[i])->pos0.x>>((Triangle*)objs[i])->pos0.y>>((Triangle*)objs[i])->pos0.z + >>((Triangle*)objs[i])->pos1.x>>((Triangle*)objs[i])->pos1.y>>((Triangle*)objs[i])->pos1.z + >>((Triangle*)objs[i])->pos2.x>>((Triangle*)objs[i])->pos2.y>>((Triangle*)objs[i])->pos2.z; + //((Triangle*)objs[i])->printName(); + N++; + } else if(type=="cuboid"){ + Vec3 p1,p2; + in>>p1.x>>p1.y>>p1.z>>p2.x>>p2.y>>p2.z; + objs.push_back(new Triangle); + ((Triangle*)objs[i])->pos0.x=p1.x; ((Triangle*)objs[i])->pos0.y=p1.y; ((Triangle*)objs[i])->pos0.z=p1.z; + ((Triangle*)objs[i])->pos1.x=p2.x; ((Triangle*)objs[i])->pos1.y=p1.y; ((Triangle*)objs[i])->pos1.z=p1.z; + ((Triangle*)objs[i])->pos2.x=p2.x; ((Triangle*)objs[i])->pos2.y=p1.y; ((Triangle*)objs[i])->pos2.z=p2.z; + i++; N++; objs.push_back(new Triangle); + ((Triangle*)objs[i])->pos0.x=p1.x; ((Triangle*)objs[i])->pos0.y=p1.y; ((Triangle*)objs[i])->pos0.z=p1.z; + ((Triangle*)objs[i])->pos1.x=p2.x; ((Triangle*)objs[i])->pos1.y=p1.y; ((Triangle*)objs[i])->pos1.z=p2.z; + ((Triangle*)objs[i])->pos2.x=p1.x; ((Triangle*)objs[i])->pos2.y=p1.y; ((Triangle*)objs[i])->pos2.z=p2.z; + + i++; N++; objs.push_back(new Triangle); + ((Triangle*)objs[i])->pos0.x=p1.x; ((Triangle*)objs[i])->pos0.y=p1.y; ((Triangle*)objs[i])->pos0.z=p2.z; + ((Triangle*)objs[i])->pos1.x=p2.x; ((Triangle*)objs[i])->pos1.y=p1.y; ((Triangle*)objs[i])->pos1.z=p2.z; + ((Triangle*)objs[i])->pos2.x=p2.x; ((Triangle*)objs[i])->pos2.y=p2.y; ((Triangle*)objs[i])->pos2.z=p2.z; + i++; N++; objs.push_back(new Triangle); + ((Triangle*)objs[i])->pos0.x=p1.x; ((Triangle*)objs[i])->pos0.y=p1.y; ((Triangle*)objs[i])->pos0.z=p2.z; + ((Triangle*)objs[i])->pos1.x=p2.x; ((Triangle*)objs[i])->pos1.y=p2.y; ((Triangle*)objs[i])->pos1.z=p2.z; + ((Triangle*)objs[i])->pos2.x=p1.x; ((Triangle*)objs[i])->pos2.y=p2.y; ((Triangle*)objs[i])->pos2.z=p2.z; + + i++; N++; objs.push_back(new Triangle); + ((Triangle*)objs[i])->pos0.x=p2.x; ((Triangle*)objs[i])->pos0.y=p1.y; ((Triangle*)objs[i])->pos0.z=p1.z; + ((Triangle*)objs[i])->pos1.x=p2.x; ((Triangle*)objs[i])->pos1.y=p2.y; ((Triangle*)objs[i])->pos1.z=p1.z; + ((Triangle*)objs[i])->pos2.x=p2.x; ((Triangle*)objs[i])->pos2.y=p2.y; ((Triangle*)objs[i])->pos2.z=p2.z; + i++; N++; objs.push_back(new Triangle); + ((Triangle*)objs[i])->pos0.x=p2.x; ((Triangle*)objs[i])->pos0.y=p1.y; ((Triangle*)objs[i])->pos0.z=p1.z; + ((Triangle*)objs[i])->pos1.x=p2.x; ((Triangle*)objs[i])->pos1.y=p2.y; ((Triangle*)objs[i])->pos1.z=p2.z; + ((Triangle*)objs[i])->pos2.x=p2.x; ((Triangle*)objs[i])->pos2.y=p1.y; ((Triangle*)objs[i])->pos2.z=p2.z; + + i++; N++; objs.push_back(new Triangle); + ((Triangle*)objs[i])->pos0.x=p1.x; ((Triangle*)objs[i])->pos0.y=p2.y; ((Triangle*)objs[i])->pos0.z=p1.z; + ((Triangle*)objs[i])->pos1.x=p2.x; ((Triangle*)objs[i])->pos1.y=p2.y; ((Triangle*)objs[i])->pos1.z=p1.z; + ((Triangle*)objs[i])->pos2.x=p2.x; ((Triangle*)objs[i])->pos2.y=p2.y; ((Triangle*)objs[i])->pos2.z=p2.z; + i++; N++; objs.push_back(new Triangle); + ((Triangle*)objs[i])->pos0.x=p1.x; ((Triangle*)objs[i])->pos0.y=p2.y; ((Triangle*)objs[i])->pos0.z=p1.z; + ((Triangle*)objs[i])->pos1.x=p2.x; ((Triangle*)objs[i])->pos1.y=p2.y; ((Triangle*)objs[i])->pos1.z=p2.z; + ((Triangle*)objs[i])->pos2.x=p1.x; ((Triangle*)objs[i])->pos2.y=p2.y; ((Triangle*)objs[i])->pos2.z=p2.z; + + i++; N++; objs.push_back(new Triangle); + ((Triangle*)objs[i])->pos0.x=p1.x; ((Triangle*)objs[i])->pos0.y=p1.y; ((Triangle*)objs[i])->pos0.z=p1.z; + ((Triangle*)objs[i])->pos1.x=p2.x; ((Triangle*)objs[i])->pos1.y=p1.y; ((Triangle*)objs[i])->pos1.z=p1.z; + ((Triangle*)objs[i])->pos2.x=p2.x; ((Triangle*)objs[i])->pos2.y=p2.y; ((Triangle*)objs[i])->pos2.z=p1.z; + i++; N++; objs.push_back(new Triangle); + ((Triangle*)objs[i])->pos0.x=p1.x; ((Triangle*)objs[i])->pos0.y=p1.y; ((Triangle*)objs[i])->pos0.z=p1.z; + ((Triangle*)objs[i])->pos1.x=p2.x; ((Triangle*)objs[i])->pos1.y=p2.y; ((Triangle*)objs[i])->pos1.z=p1.z; + ((Triangle*)objs[i])->pos2.x=p1.x; ((Triangle*)objs[i])->pos2.y=p2.y; ((Triangle*)objs[i])->pos2.z=p1.z; + + i++; N++; objs.push_back(new Triangle); + ((Triangle*)objs[i])->pos0.x=p1.x; ((Triangle*)objs[i])->pos0.y=p1.y; ((Triangle*)objs[i])->pos0.z=p1.z; + ((Triangle*)objs[i])->pos1.x=p1.x; ((Triangle*)objs[i])->pos1.y=p2.y; ((Triangle*)objs[i])->pos1.z=p1.z; + ((Triangle*)objs[i])->pos2.x=p1.x; ((Triangle*)objs[i])->pos2.y=p2.y; ((Triangle*)objs[i])->pos2.z=p2.z; + i++; N++; objs.push_back(new Triangle); + ((Triangle*)objs[i])->pos0.x=p1.x; ((Triangle*)objs[i])->pos0.y=p1.y; ((Triangle*)objs[i])->pos0.z=p1.z; + ((Triangle*)objs[i])->pos1.x=p1.x; ((Triangle*)objs[i])->pos1.y=p2.y; ((Triangle*)objs[i])->pos1.z=p2.z; + ((Triangle*)objs[i])->pos2.x=p1.x; ((Triangle*)objs[i])->pos2.y=p1.y; ((Triangle*)objs[i])->pos2.z=p2.z; + //((Triangle*)objs[i])->printName(); + N++; + } else if(type=="plane"){ + objs.push_back(new Plane); + in>>((Plane*)objs[i])->pos.x>>((Plane*)objs[i])->pos.y>>((Plane*)objs[i])->pos.z + >>((Plane*)objs[i])->normal.x>>((Plane*)objs[i])->normal.y>>((Plane*)objs[i])->normal.z; + ((Plane*)objs[i])->normal.normalise(); + N++; + } else { + cout<<"Unknown object type '"<<type<<"'!"<<endl; + return 1; + } + } + cout<<"Read objects: "<<N<<" objects"<<endl; + + string fnamebase; + if(strrchr(argv[1],'/')==NULL)fnamebase=argv[1]; + else fnamebase=strrchr(argv[1],'/'); + vector<uint8_t> image; + image.resize(4*SCREEN_WIDTH*SCREEN_HEIGHT); + int error; +#if 0 + char fname[fnamebase.length()+8]; + cout<<"Rendered frames: "<<endl; + for(i=0;i<36;i++){ + makeimage(image,camera,objs,N); + cout<<i<<' '<<flush; + snprintf(fname,sizeof(fname),"%s%02d.png",fnamebase.c_str(),i); + error=lodepng::encode(fname,image,SCREEN_WIDTH,SCREEN_HEIGHT); + if(error){ + cout<<"Lodepng encoder error "<<error<<": "<<lodepng_error_text(error)<<endl; + return 1; + } + //camera.lookat=(camera.lookat-camera.pos).rotated(M_PI/9,0)+camera.pos; + camera.pos=camera.pos.rotatedZ(M_PI/18); + } + cout<<endl<<"Written images"<<endl; +#else + fnamebase+=".png"; + //camera.pos=camera.pos.rotatedZ(M_PI/2); + makeimage(image,camera,objs,N); + cout<<"Rendered objects"<<endl; + error=lodepng::encode(fnamebase.c_str(),image,SCREEN_WIDTH,SCREEN_HEIGHT); + if(error){ + cout<<"Lodepng encoder error "<<error<<": "<<lodepng_error_text(error)<<endl; + return 1; + } + cout<<"Written image"<<endl; +#endif + return 0; +} diff --git a/room.rtsc b/room.rtsc new file mode 100644 index 0000000..ba6bd32 --- /dev/null +++ b/room.rtsc @@ -0,0 +1,12 @@ +5 -20 0 -4 0 0 0 +0 -20 1 1 +sphere 0 -3 0 1 +plane 10 0 0 -1 0 0 +plane -10 0 0 1 0 0 +plane 0 10 0 0 -1 0 +plane 0 0 10 0 0 -1 +plane 0 0 -5 0 0 1 + +cuboid -10 4 -5 -9.5 -2 8 +cuboid -9.5 3 1.5 -9.0 2.7 1.3 +sphere -8.8 2.85 1.45 0.3
\ No newline at end of file diff --git a/room2.rtsc b/room2.rtsc new file mode 100644 index 0000000..42abe36 --- /dev/null +++ b/room2.rtsc @@ -0,0 +1,12 @@ +8 -2 0 -4 0 0 0 +0 -20 1 1 +sphere 0 -3 0 1 +plane 10 0 0 -1 0 0 +plane -10 0 0 1 0 0 +plane 0 10 0 0 -1 0 +plane 0 0 10 0 0 -1 +plane 0 0 -5 0 0 1 + +cuboid -10 4 -5 -9.5 -2 8 +cuboid -9.5 3 1.5 -9.0 2.7 1.3 +sphere -8.8 2.85 1.45 0.3
\ No newline at end of file diff --git a/simple.rtsc b/simple.rtsc new file mode 100644 index 0000000..16df9d5 --- /dev/null +++ b/simple.rtsc @@ -0,0 +1,4 @@ +1 -15 2 0 0 0 0 +-2 -8 6 1 +sphere 0 0 0 1 +sphere 1 10 -3 1.5
\ No newline at end of file diff --git a/spheres.rtsc b/spheres.rtsc new file mode 100644 index 0000000..1c8cffe --- /dev/null +++ b/spheres.rtsc @@ -0,0 +1,53 @@ +1 -16 3 0 0 0 0 +-2 -8 6 1 +sphere -6 -6 -1 1 +sphere -4 -6 -1 1 +sphere -2 -6 -1 1 +sphere 0 -6 -1 1 +sphere 2 -6 -1 1 +sphere 4 -6 -1 1 +sphere 6 -6 -1 1 +sphere -6 -4 -1 1 +sphere -4 -4 -1 1 +sphere -2 -4 -1 1 +sphere 0 -4 -1 1 +sphere 2 -4 -1 1 +sphere 4 -4 -1 1 +sphere 6 -4 -1 1 +sphere -6 -2 -1 1 +sphere -4 -2 -1 1 +sphere -2 -2 -1 1 +sphere 0 -2 -1 1 +sphere 2 -2 -1 1 +sphere 4 -2 -1 1 +sphere 6 -2 -1 1 +sphere -6 0 -1 1 +sphere -4 0 -1 1 +sphere -2 0 -1 1 +sphere 0 0 -1 1 +sphere 2 0 -1 1 +sphere 4 0 -1 1 +sphere 6 0 -1 1 +sphere -6 2 -1 1 +sphere -4 2 -1 1 +sphere -2 2 -1 1 +sphere 0 2 -1 1 +sphere 2 2 -1 1 +sphere 4 2 -1 1 +sphere 6 2 -1 1 +sphere -6 4 -1 1 +sphere -4 4 -1 1 +sphere -2 4 -1 1 +sphere 0 4 -1 1 +sphere 2 4 -1 1 +sphere 4 4 -1 1 +sphere 6 4 -1 1 +sphere -6 6 -1 1 +sphere -4 6 -1 1 +sphere -2 6 -1 1 +sphere 0 6 -1 1 +sphere 2 6 -1 1 +sphere 4 6 -1 1 +sphere 6 6 -1 1 +sphere -1 -6 3 1 +plane 0 0 -2 0 0 1
\ No newline at end of file diff --git a/test.rtsc b/test.rtsc new file mode 100644 index 0000000..7fc15c1 --- /dev/null +++ b/test.rtsc @@ -0,0 +1,3 @@ +0 -20 0 0 0 0 0 +0 -20 1 1 +sphere 0 0 0 1
\ No newline at end of file |