Commit 3dcb4712 authored by Maxim Gorodnichev's avatar Maxim Gorodnichev
Browse files

initial

parent f6b177f8
#include <iostream>
#include <cmath>
#include "bmpfile.h"
struct IntensityRGB
{
double red;
double green;
double blue;
};
struct Sphere
{
double x,y,z;
double r;
IntensityRGB color;
};
struct LightSource
{
double x, y, z;
IntensityRGB color;
};
struct Vector3D
{
double x;
double y;
double z;
};
Sphere listOfSpheres[10];
int sizeOfLOS;
LightSource listOfLightSources[10];
int sizeOfLOLS;
const Vector3D zeroPoint = {0, 0, 0};
IntensityRGB redPixel = {0.3, 0.3, 1};
IntensityRGB bluePixel = {1, 0.3, 0.3};
IntensityRGB greenPixel = {0.3, 1, 0.3};
const IntensityRGB blackPixel = {0, 0, 0};
IntensityRGB somePixel = {0.6, 0.2, 0.2};
IntensityRGB whitePixel = {0.5, 0.5, 0.5};
IntensityRGB ambientLight = {0.1, 0.1, 0.1};
IntensityRGB yellowPixel = {0.3, 1 , 1};
const int limitOfRecursion = 50;
;
bool intersectSphere(Vector3D &intersectionPoint, Sphere sphere, Vector3D ray, Vector3D startPoint)
{
//std::cerr << "Sph " << sphere.x << " " << sphere.y << " " << sphere.z << " " << sphere.r << "\n";
//std::cerr << "ray " << ray.x << " " << ray.y << " " << ray.z << "\n";
//std::cerr << "sph sp " << startPoint.x << " " << startPoint.y << " " << startPoint.z << "\n";
Vector3D v = {startPoint.x-sphere.x, startPoint.y-sphere.y, startPoint.z-sphere.z};
//std::cerr << "v " << v.x << " " << v.y << " " << v.z << "\n";
double discriminant = (v.x*ray.x+v.y*ray.y+v.z*ray.z)*(v.x*ray.x+v.y*ray.y+v.z*ray.z)-
((v.x*v.x+v.y*v.y+v.z*v.z)-sphere.r*sphere.r);
if(discriminant<0)
return false;
double t1 = -(v.x*ray.x+v.y*ray.y+v.z*ray.z)+sqrt(discriminant);
double t2 = -(v.x*ray.x+v.y*ray.y+v.z*ray.z)-sqrt(discriminant);
double t = 0;
double epsilon = 0.000001;
if(t1<epsilon)
{
if(t2<epsilon)
return false;
else
t = t2;
}
else
if(t2<epsilon)
t = t1;
else
t = (t1>t2)?t2:t1;
//std::cerr << "t " << t << "\n";
intersectionPoint.x = ray.x*t+startPoint.x;
intersectionPoint.y = ray.y*t+startPoint.y;
intersectionPoint.z = ray.z*t+startPoint.z;
return true;
}
//returns closest object number if there is an intersection or -1 otherwise
int intersect(Vector3D startPoint, Vector3D ray, Vector3D& closestIntersectionPoint)
{
//std::cerr << "SP: " << startPoint.x << " " << startPoint.y << " " << startPoint.z << "\n";
//std::cerr << "ray: " << ray.x << " " << ray.y << " " << ray.z << "\n";
int closestObject = -1;
double minDistanceToObstacleSquared = 100000;
for(int i = 0; i<sizeOfLOS; i++)
{
Vector3D intersectionPoint;
if(intersectSphere(intersectionPoint, listOfSpheres[i], ray, startPoint))
{
//std::cerr << "Sphere " << i << "\n";
Vector3D distanceVector = {intersectionPoint.x-startPoint.x,
intersectionPoint.y-startPoint.y,
intersectionPoint.z-startPoint.z
};
double distanceToObstacleSquared = distanceVector.x*distanceVector.x
+ distanceVector.y*distanceVector.y
+ distanceVector.z*distanceVector.z;
closestObject = (minDistanceToObstacleSquared<distanceToObstacleSquared)?closestObject:i;
closestIntersectionPoint = (minDistanceToObstacleSquared<distanceToObstacleSquared)?closestIntersectionPoint:intersectionPoint;
minDistanceToObstacleSquared = (minDistanceToObstacleSquared<distanceToObstacleSquared)?minDistanceToObstacleSquared:distanceToObstacleSquared;
}
}
return closestObject;
}
IntensityRGB illuminationStep(Vector3D point, Vector3D ray, int recursionStep = 0)
{
Vector3D closestIntersectionPoint;
//std::cerr << "first\n";
//find an object we a lookint at
int closestObject = intersect(point, ray, closestIntersectionPoint);
//std::cerr << "CIP: " << closestIntersectionPoint.x << " " << closestIntersectionPoint.y << " " << closestIntersectionPoint.z << "\n";
if(closestObject==-1)
return blackPixel;
IntensityRGB color = blackPixel;
for(int i = 0; i<sizeOfLOLS; i++)
{
//check if the point on the object is illuminated
Vector3D rayToLightSource;
rayToLightSource.x = listOfLightSources[i].x-closestIntersectionPoint.x;
rayToLightSource.y = listOfLightSources[i].y-closestIntersectionPoint.y;
rayToLightSource.z = listOfLightSources[i].z-closestIntersectionPoint.z;
double rayToLightSourceLenght = sqrt(rayToLightSource.x*rayToLightSource.x
+rayToLightSource.y*rayToLightSource.y
+rayToLightSource.z*rayToLightSource.z
);
//std::cerr << "RTS: " << rayToLightSource.x << rayToLightSource.y << rayToLightSource.z << "\n";
rayToLightSource.x /= rayToLightSourceLenght;
rayToLightSource.y /= rayToLightSourceLenght;
rayToLightSource.z /= rayToLightSourceLenght;
//std::cerr << "light distance " << rayToLightSourceLenght << "\n";
Vector3D intersectionPoint;
//optimization potential: do not need closest object here, just check for an obstacle
int obstacle = intersect(closestIntersectionPoint, rayToLightSource, intersectionPoint);
if(obstacle!=-1)
{
//std::cerr << "point " << intersectionPoint.x << " " << intersectionPoint.y << " " << intersectionPoint.z << "\n";
//check if light is closer then the intersected object
intersectionPoint.x -= closestIntersectionPoint.x;
intersectionPoint.y -= closestIntersectionPoint.y;
intersectionPoint.z -= closestIntersectionPoint.z;
double obstacleDistance = sqrt(intersectionPoint.x*intersectionPoint.x
+intersectionPoint.y*intersectionPoint.y
+intersectionPoint.z*intersectionPoint.z);
//std::cerr << "point " << intersectionPoint.x << " " << intersectionPoint.y << " " << intersectionPoint.z << "\n";
//std::cerr << "obstacle distance " << obstacleDistance << "\n";
if(obstacleDistance>rayToLightSourceLenght)
{
// //std::cerr << "What's up?\n";
obstacle=-1;
}
}
//if(recursionStep==0)
if(obstacle==-1)
{
//reflection
Vector3D normal = { closestIntersectionPoint.x-listOfSpheres[closestObject].x,
closestIntersectionPoint.y-listOfSpheres[closestObject].y,
closestIntersectionPoint.z-listOfSpheres[closestObject].z
};
double norm = sqrt(normal.x*normal.x+normal.y*normal.y+normal.z*normal.z);
normal.x /= norm;
normal.y /= norm;
normal.z /= norm;
double cosine = normal.x*(-ray.x)+normal.y*(-ray.y)+normal.z*(-ray.z);
Vector3D reflectedRay = {ray.x+2*cosine*normal.x,
ray.y+2*cosine*normal.y,
ray.z+2*cosine*normal.z
};
cosine = reflectedRay.x*rayToLightSource.x+reflectedRay.y*rayToLightSource.y+reflectedRay.z*rayToLightSource.z;
if(cosine<0)
cosine = 0;
// cosine = 1;
//apply coefficients of the body color to the intensity of the light source
color.red += listOfLightSources[0].color.red*listOfSpheres[closestObject].color.red*cosine;
color.blue += listOfLightSources[0].color.blue*listOfSpheres[closestObject].color.blue*cosine;
color.green += listOfLightSources[0].color.green*listOfSpheres[closestObject].color.green*cosine;
// //std::cerr << "color = " << color.red << " " << color.blue << " " << color.green << "\n";
}
/*if(recursionStep>0)
if(obstacle!=-1)
{
//apply coefficients of the body color to the intensity of the light source
color.red = listOfLightSources[0].color.red*listOfSpheres[closestObject].color.red;
color.blue = listOfLightSources[0].color.blue*listOfSpheres[closestObject].color.blue;
color.green = listOfLightSources[0].color.green*listOfSpheres[closestObject].color.green;
}
*/
}
//apply ambient light
color.red += ambientLight.red*listOfSpheres[closestObject].color.red;
color.blue += ambientLight.blue*listOfSpheres[closestObject].color.blue;
color.green += ambientLight.green*listOfSpheres[closestObject].color.green;
if(recursionStep!=limitOfRecursion)
{
//reflection
Vector3D normal = { closestIntersectionPoint.x-listOfSpheres[closestObject].x,
closestIntersectionPoint.y-listOfSpheres[closestObject].y,
closestIntersectionPoint.z-listOfSpheres[closestObject].z
};
double norm = sqrt(normal.x*normal.x+normal.y*normal.y+normal.z*normal.z);
normal.x /= norm;
normal.y /= norm;
normal.z /= norm;
double cosine = normal.x*(-ray.x)+normal.y*(-ray.y)+normal.z*(-ray.z);
Vector3D reflectedRay = {(ray.x+2*cosine*normal.x),
(ray.y+2*cosine*normal.y),
(ray.z+2*cosine*normal.z)
};
//the followin norming can have no sense
norm = sqrt(reflectedRay.x*reflectedRay.x+reflectedRay.y*reflectedRay.y+reflectedRay.z*reflectedRay.z);
reflectedRay.x /= norm;
reflectedRay.y /= norm;
reflectedRay.z /= norm;
IntensityRGB reflectionColor = illuminationStep(closestIntersectionPoint, reflectedRay, recursionStep+1);
color.red += listOfSpheres[closestObject].color.red*reflectionColor.red;
color.blue += listOfSpheres[closestObject].color.blue*reflectionColor.blue;
color.green += listOfSpheres[closestObject].color.green*reflectionColor.green;
}
// //std::cerr << "color = " << color.red << " " << color.blue << " " << color.green << "\n";
return color;
}
double backgroundSizeX = 4;
double backgroundSizeZ = 4;
double backgroundDistance = 15;
double imagePlaneDistance = 5;
double imagePlaneSizeX;
double imagePlaneSizeZ;
int imagePlaneResolutionX =600;
int imagePlaneResolutionZ = 600;
int colorDepth = 24;
int main()
{
bmpfile_t *bmp;
if((bmp = bmp_create(imagePlaneResolutionX, imagePlaneResolutionZ, colorDepth)) == NULL)
{
//std::cerr << "Wrong parameters to bmp_create\n";
return 1;
}
/*
Sphere ss;
ss.x = 0;
ss.y = 1;
ss.z = 0;
ss.r = 1;
Vector3D vp = {0,0,0};
Vector3D rr = {0, 1, 0};
Vector3D pointt = {-1, -1, -1};
bool res = intersectSphere(pointt, ss, rr, vp);
//std::cerr << "check IS: " << res << " " << pointt.x << " " << pointt.y << " " << pointt.z << "\n";
*/
listOfSpheres[4].x = 0;
listOfSpheres[4].y = 7;
listOfSpheres[4].z = 2;
listOfSpheres[4].r = 1;
listOfSpheres[4].color = bluePixel;
listOfSpheres[3].x = -3;
listOfSpheres[3].y = 11;
listOfSpheres[3].z = -2;
listOfSpheres[3].r = 2;
listOfSpheres[3].color = redPixel;
listOfSpheres[0].x = 0;
listOfSpheres[0].y = 8;
listOfSpheres[0].z = -2;
listOfSpheres[0].r = 1;
listOfSpheres[0].color = greenPixel;
listOfSpheres[2].x = 1.5;
listOfSpheres[2].y = 7;
listOfSpheres[2].z = 0.5;
listOfSpheres[2].r = 1;
listOfSpheres[2].color = whitePixel;
listOfSpheres[5].x = -2;
listOfSpheres[5].y = 6;
listOfSpheres[5].z = 1;
listOfSpheres[5].r = 0.7;
listOfSpheres[5].color = yellowPixel;
listOfSpheres[1].x = 2.2;
listOfSpheres[1].y = 8;
listOfSpheres[1].z = 0.;
listOfSpheres[1].r = 1;
listOfSpheres[1].color = whitePixel;
listOfSpheres[6].x = 4;
listOfSpheres[6].y = 10;
listOfSpheres[6].z = 1;
listOfSpheres[6].r = 0.7;
listOfSpheres[6].color = redPixel;
listOfLightSources[0].x = -15;
listOfLightSources[0].y = -15;
listOfLightSources[0].z = 0;
listOfLightSources[0].color = whitePixel;
listOfLightSources[1].x = 1;
listOfLightSources[1].y = 0;
listOfLightSources[1].z = 1;
listOfLightSources[1].color = bluePixel;
listOfLightSources[2].x = 0;
listOfLightSources[2].y = 6;
listOfLightSources[2].z = -10;
listOfLightSources[2].color = redPixel;
Vector3D viewPoint = zeroPoint;
//for(int i = 0; i<20; i++)
{
viewPoint.y = -20;//*cos(i*3.14/20);
viewPoint.x = 0;//*sin(i*3.14/20);
sizeOfLOS = 7;
sizeOfLOLS = 3
;
imagePlaneSizeX = backgroundSizeX*imagePlaneDistance/backgroundDistance;
imagePlaneSizeZ = backgroundSizeZ*imagePlaneDistance/backgroundDistance;
for(int ix = 0; ix < imagePlaneResolutionX; ix++)
for(int iz = 0; iz < imagePlaneResolutionZ; iz++)
{
// int ix = 0, iz = 0;
//a ray from an eye
Vector3D ray;
ray.x = ix*imagePlaneSizeX/imagePlaneResolutionX-imagePlaneSizeX/2;
ray.z = iz*imagePlaneSizeZ/imagePlaneResolutionZ-imagePlaneSizeZ/2;
ray.y = imagePlaneDistance;
// ray.y = 5;//cos(i*3.14/20);
// ray.x = -.1;//sin(i*3.14/20);
// ray.z = 0;
double rayLength = sqrt(ray.x*ray.x+ray.y*ray.y+ray.z*ray.z);
ray.x /= rayLength;
ray.y /= rayLength;
ray.z /= rayLength;
IntensityRGB color = blackPixel;
//std::cerr << "start\n";
color = illuminationStep(viewPoint, ray);
if(color.red>1)
color.red = 1;
if(color.blue>1)
color.blue = 1;
if(color.green>1)
color.green = 1;
rgb_pixel_t pixel = {255*color.red, 255*color.green, 255*color.blue};
bmp_set_pixel(bmp, ix, iz, pixel);
}
char filename[] = "raytracing00.bmp";
// filename[10] += i/10;
// filename[11] += i%10;
bmp_save(bmp, filename);
}
return 0;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment