Getting the normal of a cone - Raytracing - c

I'm writing a raytracer in C and I'm having trouble perfecting the shadows on my cone. I think the problem I have is in the calculation of the normal of the cone at the intersection point. Here is a rendering of what I currently have.
The scene described as follows:
resolution: 500, 500
scene:
{
light:
{
position: 0, -10, -40
intensity: 20000
color: white
}
camera:
{
position: -5, -7, -40
direction: 0, 0, 1
fov: 50
}
plane:
{
position: 0, 0, 0
direction: 0, 0, 1
color: white
}
cone:
{
position: 0, 0, -2.5
direction: -5, -8, 0
color: white
radius: 5
height: 20
}
cylinder:
{
position: 10, 0, 0
direction: -5, -8, 0
color: white
radius: 5
height: 20
}
}
Note that the light is between the objects and the camera.
The issue there is that I think the cone should be more illuminated, at least, in some areas, as illuminated as the cylinder to the right.
I calculated the normal based on this post's answer as follows:
static void get_cone_normal(t_raytracing_tools *r, t_ray *ray, t_object *obj)
{
//nhit is the normal at hit point.
ray->nhit.x = (ray->hit.x - obj->pos.x) * (obj->height / obj->rad);
ray->nhit.y = obj->rad / obj->height;
ray->nhit.z = (ray->hit.z - obj->pos.z) * (obj->height / obj->rad);
ray->nhit = v_norm(ray->nhit);
}
I also thought of the direction of the normal depending on what side of the cone is hit by the ray. After I solve the quadratic equation and get two potential answers, I test each one to figure out if it is within my finite cone (parametric equation is for infinite cone) and according to how the ray hits the cone, I have an int variable n_dir which is either 1 or -1 which I use to invert the normal if the ray hits the inside of the cone. Here is the code for that part:
bool get_finite_cone_intersection(t_raytracing_tools *r, t_ray *ray, t_object *obj, t_intersection_tools *i)
{
bool r1_too_low;
bool r1_too_high;
bool r2_too_low;
bool r2_too_high;
//i->r1 and i->r2 are the two roots (solutions of quadratic eq.)
r1_too_low = lower_than_min(i->r1, i, obj, ray);
r1_too_high = higher_than_max(i->r1, i, obj, ray);
r2_too_low = lower_than_min(i->r2, i, obj, ray);
r2_too_high = higher_than_max(i->r2, i, obj, ray);
if (r1_too_low)
{
i->r1 = NAN; //I set roots to NAN if they are not valid solutions
if (r2_too_low || r2_too_high)
i->r2 = NAN;
else
i->n_dir = 1;
}
else if (r1_too_high)
{
i->r1 = NAN;
if (r2_too_low || r2_too_high)
i->r2 = NAN;
else
i->n_dir = -1;
}
else if (!r1_too_low && !r1_too_high)
{
i->r2 = NAN;
if (r2_too_low)
i->n_dir = -1;
else
i->n_dir = 1;
}
return (true);
}
bool lower_than_min(double r, t_intersection_tools *i, t_object *obj, t_ray *ray)
{
if (r > 0)
{
if (v_dot(obj->dir, v_sub(v_add(ray->origin, v_scale(ray->dir, r)), obj->pos)) < 0.0)
return (true);
}
return (false);
}
bool higher_than_max(double r, t_intersection_tools *i, t_object *obj, t_ray *ray)
{
if (r > 0)
{
if (v_dot(obj->dir, v_sub(v_add(ray->origin, v_scale(ray->dir, r)),
v_add(obj->pos, v_scale(obj->dir, obj->height)))) > 0.0)
return (true);
}
return (false);
}
Also, what the heck, here's the code for my cone intersection:
bool get_cone_intersection(t_raytracing_tools *r, t_ray *ray, t_object *cone)
{
t_intersection_tools i;
t_vec3 ori_cen;
double k;
int n_dir;
i.n_dir = 1;
k = tan(cone->angle);
ori_cen = v_sub(ray->origin, cone->pos);
i.q.x = v_dot(ray->dir, ray->dir) - (1.0 + k * k) * powf(v_dot(ray->dir, cone->dir), 2.0);
i.q.y = 2 * (v_dot(ray->dir, ori_cen) - (1.0 + k * k) * v_dot(ray->dir, cone->dir)
* v_dot(ori_cen, cone->dir));
i.q.z = v_dot(ori_cen, ori_cen) - (1.0 + k * k) * powf(v_dot(ori_cen,
cone->dir), 2.0);
if (!solve_quadratic(i.q, &i.r1, &i.r2))
return (0);
(i.r2 < i.r1) ? ft_swapd(&i.r1, &i.r2) : 0;
get_finite_cone_intersection(r, ray, cone, &i);
if (i.r1 < 0 || isnan(i.r1)) //the smallest one is negative, thus take the other one
{
i.r1 = i.r2;
}
if (i.r1 < 0 || isnan(i.r1))
return (false);
if (r->t > i.r1)
{
ray->t = i.r1;
if (ray->type == R_PRIMARY)
{
ray->hit_obj = cone;
ray->hit_type = T_CONE;
ray->n_dir = i.n_dir;
}
}
return (true);
}
Hope that's not too much info at once! Again, would love it if someone could shed some light (haha) on the situation.

Related

Rotate Player in Relation to Rotated Rectangle

I'm trying to build a game where the player can stand on rotated rectangles. Take the example if a rectangular platform is rotated 20 degrees, then the player would be standing on the platform at a 20 degree angle as well, and could move along that rotated axis. Perhaps this image will clear this up:
Therefore, I need to:
Make the platform solid so the player can stand on it
Make the player rotate to the same angle as the platform
Make the player move on the rotated axis
I've tried to do this, but I've failed. Here's my code that I tried:
#include "raylib.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define WIDTH 1200
#define HEIGHT 800
typedef struct {
const int width;
const int height;
int FPS;
} Window;
Window window = {
.FPS = 60,
};
typedef struct {
Vector2 pos;
Vector2 acc;
Vector2 vel;
int width;
int height;
double accSpeed;
int maxVel;
double friction;
double rotation;
double scale;
float jumpForce;
float gravity;
bool canJump;
} Player;
Player player = {
.pos = {WIDTH/2, HEIGHT/2},
.acc = {0, 0},
.vel = {0, 0},
.width = 50,
.height = 100,
.accSpeed = 0.15,
.maxVel = 7,
.friction = 0.2,
.rotation = 0,
.scale = 0.5,
.jumpForce = 15,
.gravity = 0.5,
.canJump = true,
};
void movePlayerX();
void movePlayerY();
int rectCollide();
int main() {
InitWindow(WIDTH, HEIGHT, "Window");
SetTargetFPS(window.FPS);
//Rectangle playerArea = {player.pos.x, player.pos.y, playerImg.width*player.scale, playerImg.height*player.scale};
Rectangle playerArea;
Rectangle rect1 = {500, 600, 100, 250};
while (!WindowShouldClose()) {
playerArea = (Rectangle) {
player.pos.x,
player.pos.y,
player.width,
player.height,
};
BeginDrawing();
ClearBackground(RAYWHITE);
DrawRectanglePro(rect1, (Vector2) {0, 0}, 20, BLUE);
DrawRectanglePro(playerArea, (Vector2) {0, 0}, player.rotation, RED);
movePlayerX();
/*if (CheckCollisionRecs(playerArea, rect1)) {
if (player.vel.x < 0) { // If the player moved left and collided with the right side of block
player.pos.x = rect1.x + rect1.width;
} else { // If the player moved right and collided with the left side of block
player.pos.x = rect1.x - playerArea.width;
}
player.vel.x = 0;
}*/
movePlayerY();
if (CheckCollisionRecs(playerArea, rect1)) {
if (player.vel.y < 0) { // If the player hit their head
player.pos.y = rect1.y + rect1.height;
player.vel.y *= -0.5; // Not -1 because collisions are not perfectly elastic
} else {
player.pos.y = rect1.y - player.height;
player.rotation = 20;
player.vel.y = 0;
player.acc.y = 0;
player.canJump = true;
}
}
if (player.pos.y >= HEIGHT - player.height) {
player.canJump = true;
player.pos.y = HEIGHT - player.height;
player.vel.y = 0;
}
EndDrawing();
}
}
void movePlayerX() {
if (IsKeyDown(KEY_LEFT) && player.vel.x > -player.maxVel) {
player.acc.x = -player.accSpeed;
} else if (IsKeyDown(KEY_RIGHT) && player.vel.x < player.maxVel) {
player.acc.x = player.accSpeed;
} else if (abs(player.vel.x) > 0.2) {
if (player.vel.x < 0) {
player.acc.x = player.friction;
} else {
player.acc.x = -player.friction;
}
} else {
player.vel.x = 0;
player.acc.x = 0;
}
player.vel.x += player.acc.x;
player.pos.x += player.vel.x;
}
void movePlayerY() {
if (IsKeyPressed(KEY_UP) && player.vel.y == 0 && player.acc.y == 0 && player.canJump) {
player.canJump = false;
player.vel.y = -player.jumpForce;
}
player.acc.y += player.gravity;
player.vel.y += player.acc.y;
player.pos.y += player.vel.y;
player.acc.y = 0;
}
As can be seen from the code, after I call the player movement functions, movePlayerX() and movePlayerY(), I'm trying to detect if the player is colliding with the rectangle. However, I'm just using the regular built in CheckCollisionRecs() function, which detects collision on a non-rotated rectangle, which won't work.
Therefore, I was wondering: how can I get a function to detect the player's collison on a rotated rectangle, then rotate and move the player upon that rotated angle?
Thanks.

2D Raylib Texture Collisions

I was wondering how to properly handle collisions in Raylib. After setting up the basics, like a window, I would first load in the player texture, like so:
Texture2D playerTexture = LoadTexture("Player.png");
After that, I would draw the texture, with the Raylib function DrawTextureEx which allows me to adjust the rotation and scale of the texture. Then, I would add a simple movement script for the player, and that would be pretty much it.
As for collisions, I would just be testing the player collision on a rectangle. To get the area for the rectangle, I would just create a simple Rectangle struct like this:
Rectangle rect1 = {100, 100, 50, 50};
As for getting the player area, I would make something similar:
Rectangle playerArea = {player.x, player.y, playerTexture.width*player.scale, playerTexture.height*player.scale} //Values are stored in Player struct
However, when I try to check the collisons like this, nothing happens:
if (CheckCollisionRecs(playerArea, rect1)) {
DrawText("Collided", 5, 5, 25, BLACK);
}
Here's my full code, if needed:
#include "raylib.h"
#include <stdio.h>
#include <stdlib.h>
#define WIDTH 1200
#define HEIGHT 800
typedef struct {
const int width;
const int height;
int FPS;
} Window;
Window window = {
.FPS = 60,
};
typedef struct {
Vector2 pos;
Vector2 acc;
Vector2 vel;
int width;
int height;
double accSpeed;
int maxVel;
double friction;
double rotation;
double scale;
} Player;
Player player = {
.pos = {WIDTH/2, HEIGHT/2},
.acc = {0, 0},
.vel = {0, 0},
.width = 25,
.height = 25,
.accSpeed = 0.15,
.maxVel = 7,
.friction = 0.2,
.rotation = 0,
.scale = 0.5,
};
void movePlayer();
int rectCollide();
int main() {
InitWindow(WIDTH, HEIGHT, "Window");
SetTargetFPS(window.FPS);
Texture2D playerImg = LoadTexture("Player.png");
Rectangle playerArea = {player.pos.x, player.pos.y, playerImg.width*player.scale, playerImg.height*player.scale};
Rectangle rect1 = {100, 100, 50, 50};
Camera2D camera = { 0 };
camera.target = (Vector2){ player.pos.x + 20.0f, player.pos.y + 20.0f };
camera.offset = (Vector2){WIDTH/2.0f, HEIGHT/2.0f };
camera.rotation = 0.0f;
camera.zoom = 1.0f;
if (CheckCollisionRecs(playerArea, rect1)) {
DrawText("Collided", 5, 5, 25, BLACK);
}
while (!WindowShouldClose()) {
BeginDrawing();
ClearBackground(SKYBLUE);
movePlayer();
camera.target = (Vector2){ player.pos.x + 20, player.pos.y + 20 };
BeginMode2D(camera);
DrawRectangle(100, 100, 50, 50, BLACK);
DrawTextureEx(playerImg, player.pos, player.rotation, player.scale, RAYWHITE);
EndMode2D();
EndDrawing();
}
UnloadTexture(playerImg);
CloseWindow();
return 0;
}
void movePlayer() {
if (IsKeyDown(KEY_LEFT) && player.vel.x > -player.maxVel) {
player.acc.x = -player.accSpeed;
} else if (IsKeyDown(KEY_RIGHT) && player.vel.x < player.maxVel) {
player.acc.x = player.accSpeed;
} else if (abs(player.vel.x) > 0.2) {
if (player.vel.x < 0) {
player.acc.x = player.friction;
} else {
player.acc.x = -player.friction;
}
} else {
player.vel.x = 0;
player.acc.x = 0;
}
player.vel.x += player.acc.x;
player.pos.x += player.vel.x;
if (IsKeyDown(KEY_UP) && player.vel.y > -player.maxVel) {
player.acc.y = -player.accSpeed;
} else if (IsKeyDown(KEY_DOWN) && player.vel.x < player.maxVel) {
player.acc.y = player.accSpeed;
} else if (abs(player.vel.y) > 0.2) {
if (player.vel.y < 0) {
player.acc.y = player.friction;
} else {
player.acc.y = -player.friction;
}
} else {
player.vel.y = 0;
player.acc.y = 0;
}
player.vel.y += player.acc.y;
player.pos.y += player.vel.y;
}
int rectCollide(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2) {
return x1 + w1 > x2 && x1 < x2 + w2 && y1 + h1 > y2 && y1 < y2 + h2;
}
And so, I was wondering: first of all, is there a better way to get the area of the texture, without having to create a Rectangle struct for each texture, and multiply the scale by the texture width and height? Secondly, I was wondering why my collisions aren't being detected. What is wrong with my code?
The collision check
if (CheckCollisionRecs(playerArea, rect1))
precedes the event loop.
Even moving it inside the loop will not have any effect, as playerArea is never updated in your event loop.
A quick fix would be to update the collision box after moving the player.
(example snippet of main, without images)
Rectangle playerArea;
Rectangle rect1 = {100, 100, 50, 50};
while (!WindowShouldClose()) {
movePlayer();
playerArea = (Rectangle) {
player.pos.x,
player.pos.y,
player.width,
player.height,
};
camera.target = (Vector2){ player.pos.x + 20, player.pos.y + 20 };
BeginDrawing();
ClearBackground(SKYBLUE);
BeginMode2D(camera);
DrawRectangleRec(rect1, RED);
DrawRectangle(player.pos.x, player.pos.y, player.width, player.height, RAYWHITE);
EndMode2D();
if (CheckCollisionRecs(playerArea, rect1))
DrawText("Collided", 5, 5, 25, BLACK);
EndDrawing();
}

C Triangle Rasterizer rendering problems

Im trying to write an Software Renderer using this tutorial series: https://www.youtube.com/watch?v=2U-4_vpw1lQ&list=PLEETnX-uPtBUbVOok816vTl1K9vV1GgH5&index=13
But the problem is I try to render a Ico Sphere but it doesn't look right. See image: Rendered Sphere
The code for the rasterizer is:
void GRE_Edge(GTE_Vec4* MinVertY, GTE_Vec4* MaxVertY, GRE_EdgeData* Data)
{
Data->EdgeStartY = (uint32_t)ceilf(MinVertY->y);
Data->EdgeEndY = (uint32_t)ceilf(MaxVertY->y);
Data->EdgeStepX = (MaxVertY->x - MinVertY->x) / (MaxVertY->y - MinVertY->y);
Data->EdgeCurX = MinVertY->x + (Data->EdgeStartY - MinVertY->y) * Data->EdgeStepX;
}
void GRE_ScanEdge(GRE_EdgeData* a, GRE_EdgeData* b, bool Handedness, GRE_Framebuffer* Framebuffer)
{
GRE_EdgeData Left = *a;
GRE_EdgeData Right = *b;
if (Handedness)
{
GRE_EdgeData Temp = Left;
Left = Right;
Right = Temp;
}
for (uint32_t y = b->EdgeStartY; y < b->EdgeEndY; y++)
{
for (uint32_t x = (uint32_t)ceilf(Left.EdgeCurX); x < (uint32_t)ceilf(Right.EdgeCurX); x++)
GRE_DrawPixel(x, y, 255, 0, 255, Framebuffer);
Left.EdgeCurX += Left.EdgeStepX;
Right.EdgeCurX += Right.EdgeStepX;
}
}
void GRE_ScanTriangle(GTE_Vec4* MinVertY, GTE_Vec4* MidVertY, GTE_Vec4* MaxVertY, bool Handedness, GRE_Framebuffer* Framebuffer)
{
GRE_EdgeData TopToBottom;
GRE_Edge(MinVertY, MaxVertY, &TopToBottom);
GRE_EdgeData TopToMiddle;
GRE_Edge(MinVertY, MidVertY, &TopToMiddle);
GRE_EdgeData MiddleToBottom;
GRE_Edge(MidVertY, MaxVertY, &MiddleToBottom);
GRE_ScanEdge(&TopToBottom, &TopToMiddle, Handedness, Framebuffer);
GRE_ScanEdge(&TopToBottom, &MiddleToBottom, Handedness, Framebuffer);
}
float GRE_TriangleAreaTimesTwo(GTE_Vec4* a, GTE_Vec4* b, GTE_Vec4* c)
{
return ((b->x - a->x) * (c->y - a->y) - (c->x - a->x) * (b->y - a->y));
}
void GRE_FillTriangle(GTE_Vec4* v1, GTE_Vec4* v2, GTE_Vec4* v3, GRE_Framebuffer* Framebuffer)
{
GTE_Mat4 ScreenSpaceMatrix;
GTE_Mat4LoadScreenSpaceTransform(&ScreenSpaceMatrix, Framebuffer->Width * 0.5, Framebuffer->Height * 0.5);
GTE_Vec4 MinVertY;
GTE_Vec4MultiplyMat4(v1, &ScreenSpaceMatrix, &MinVertY);
GTE_Vec4PerspectiveDivide(&MinVertY);
GTE_Vec4 MidVertY;
GTE_Vec4MultiplyMat4(v2, &ScreenSpaceMatrix, &MidVertY);
GTE_Vec4PerspectiveDivide(&MidVertY);
GTE_Vec4 MaxVertY;
GTE_Vec4MultiplyMat4(v3, &ScreenSpaceMatrix, &MaxVertY);
GTE_Vec4PerspectiveDivide(&MaxVertY);
//Backface Culling
if (GRE_TriangleAreaTimesTwo(&MinVertY, &MaxVertY, &MidVertY) >= 0)
return;
GTE_Vec4 TmpVec;
if (MaxVertY.y < MidVertY.y)
{
TmpVec = MaxVertY;
MaxVertY = MidVertY;
MidVertY = TmpVec;
}
if (MidVertY.y < MinVertY.y)
{
TmpVec = MidVertY;
MidVertY = MinVertY;
MinVertY = TmpVec;
}
if (MaxVertY.y < MidVertY.y)
{
TmpVec = MaxVertY;
MaxVertY = MidVertY;
MidVertY = TmpVec;
}
GRE_ScanTriangle(&MinVertY, &MidVertY, &MaxVertY, GRE_TriangleAreaTimesTwo(&MinVertY, &MaxVertY, &MidVertY) >= 0, Framebuffer);
}
I can't find any problems with this code, so I hope someone can help me.

Why IsKeyDown always returns true?

I was working in a University C project (first sem), in which our group wanted to make a simple pong game, we decided to use raylib, as it seemed easy. But here is the problem, in the following code:
void UpdatePad(Pad* pad)
{
int height = GetScreenHeight();
if (IsKeyDown(pad->Scheme.DownButton)) {
printf("Down = %d\n", pad->Scheme.DownButton);
pad->Position.y += GetFrameTime() * pad->Speed;
if ( pad->Position.y + pad->Size.y/2 > height ) {
pad->Position.y = height - pad->Size.y /2;
}
}
if (IsKeyDown(pad->Scheme.UpButton)) {
printf("Up = %d\n", pad->Scheme.UpButton);
pad->Position.y -= GetFrameTime() * pad -> Speed;
if (pad->Position.y - pad->Size.y/2 < 0 ) {
pad->Position.y = pad->Size.y /2;
}
}
}
The function IsKeyDown of raylib always returns true, whatever I do. Even if I replace pad->Scheme.DownButton to KEY_UP or something, it always returns true and executes the code block, Is there any solution for this?
Full script is:
#include <raylib.h>
#include <stdio.h>
#include "pad.h"
#include "main.h"
void DrawPad(Pad* pad);
void UpdatePad(Pad* pad);
void Update();
void DrawUpdate();
void Loop();
int main()
{
int screenWidth = 800;
int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "Table Tennis");
SetTargetFPS(12);
Loop();
return 0;
}
void Loop()
{
while (!WindowShouldClose()) {
DrawUpdate();
}
}
void UpdatePad(Pad* pad)
{
int height = GetScreenHeight();
if (IsKeyDown(pad->Scheme.DownButton)) {
printf("Down = %d\n", pad->Scheme.DownButton);
pad->Position.y += GetFrameTime() * pad->Speed;
if ( pad->Position.y + pad->Size.y/2 > height ) {
pad->Position.y = height - pad->Size.y /2;
}
}
if (IsKeyDown(pad->Scheme.UpButton)) {
printf("Up = %d\n", pad->Scheme.UpButton);
pad->Position.y -= GetFrameTime() * pad -> Speed;
if (pad->Position.y - pad->Size.y/2 < 0 ) {
pad->Position.y = pad->Size.y /2;
}
}
}
void DrawPad(Pad* pad)
{
DrawRectangle(pad->Position.x, pad->Position.y - (pad->Size.y /2), pad->Size.x, pad->Size.y, WHITE);
}
void DrawUpdate()
{
const char* scoreLeft = TextFormat("%d", 10);
int scoreSizeLeft = MeasureText(scoreLeft, 20);
InputScheme Input = { .DownButton = KEY_S, .UpButton = KEY_W };
Vector2 paddySize = { .x = 5, .y = 50 };
Vector2 paddyPos = { .x = GetScreenWidth() - paddySize.x , .y = GetScreenHeight() - paddySize.y };
Pad pad = { .Size = paddySize, .Speed = 50, .Scheme = Input , .Position = paddyPos };
Vector2 from = {.x = (GetScreenWidth() / (float) 2), .y = 5};
Vector2 to = { .x = (GetScreenWidth() / (float) 2), .y = ( GetScreenHeight() - (float) 5 ) };
UpdatePad(&pad);
BeginDrawing();
ClearBackground(BLACK);
DrawLineEx(from, to, 2, LIGHTGRAY);
DrawText(scoreLeft, (GetScreenWidth()/2) - 10 -scoreSizeLeft, 10, 20, LIGHTGRAY);
DrawPad(&pad);
EndDrawing();
}
The pad is:-
#include <raylib.h>
typedef struct {
int UpButton;
int DownButton;
} InputScheme;
typedef struct {
InputScheme Scheme;
int Score;
float Speed;
Vector2 Position;
Vector2 Size;
} Pad;

Raytracing Rotations

I'm currently coding a simple raytracer in C. Everything is working fine, except for the rotations. I'm trying to rotate my objects (cylinders in that matter). The cylinders rotates, but the shading are completely off, and the object only rotates between 0° and 90°, and goes back to normal at 360° (which is obvious). I'd appreciate if anyone could give me a hint on what I'm doing wrong. Here's some sample code.
Function that find intersections for cylinders :
double mininter;
double inter;
t_vect *normal;
t_color *c;
t_cyl *cyl;
cyl = e->scene.cyls;
mininter = -1;
while (cyl != NULL && limiter-- != 0)
{
ray = rotate_eye(ray, cyl->rotate, -1);
inter = cylinder_inter(cyl, ray);
if (inter > ACCURACY && (inter < mininter || mininter == -1))
{
mininter = inter;
p = vect_add(ray->og, vect_mult(ray->dir, inter));
ray = rotate_eye(ray, cyl->rotate, 1);
normal = cylinder_normal(cyl->og, p);
c = cyl->color;
}
cyl = cyl->next;
}
return (new_inter(normal, mininter, c, p));
My rotation.c file :
static t_vect *x(t_vect *v, double rot, int stage)
{
rot = DEG_TO_RAD(rot * stage);
v->y = v->y * cos(rot) + v->z * -sin(rot);
v->z = v->y * sin(rot) + v->z * cos(rot);
return (v);
}
static t_vect *y(t_vect *v, double rot, int stage)
{
rot = DEG_TO_RAD(rot * stage);
v->x = v->x * cos(rot) + v->z * sin(rot);
v->z = v->x * -sin(rot) + v->z * cos(rot);
return (v);
}
static t_vect *z(t_vect *v, double rot, int stage)
{
rot = DEG_TO_RAD(rot * stage);
v->x = v->x * cos(rot) + v->y * -sin(rot);
v->y = v->x * sin(rot) + v->y * cos(rot);
return (v);
}
t_ray *rotate_eye(t_ray *ray, t_vect *rot, int stage)
{
ray->og = x(ray->og, rot->z, stage);
ray->og = y(ray->og, rot->y, stage);
ray->og = z(ray->og, rot->x, stage);
ray->dir = x(ray->dir, rot->z, stage);
ray->dir = y(ray->dir, rot->y, stage);
ray->dir = z(ray->dir, rot->x, stage);
return (ray);
}
The shadow/color file :
static double shadows(t_env *e, t_inter *inter)
{
t_ray *iray;
t_vect *v;
t_vect *l;
l = e->scene.spot->pos;
v = new_vector(l->x - inter->point->x, l->y - inter->point->y,
l->z - inter->point->z);
iray = new_ray(inter->point, l);
return (calc_inter(e, iray)->dist);
}
t_color *find_color_at(t_env *e, t_ray *ray)
{
t_color *result;
t_inter *mininter;
t_vect *dist_l;
double shade;
mininter = calc_inter(e, ray);
if (mininter->dist > ACCURACY)
{
dist_l = normalize(vect_add(e->scene.spot->pos, negative(ray->og)));
shade = dot_product(dist_l, mininter->normal);
if (shadows(e, mininter) > ACCURACY)
result = color_scalar(AMBIENTLIGHT * shadows(e, mininter),
mininter->color);
else
result = shade < 0 ? color_scalar(AMBIENTLIGHT + DIFFUSELIGHT *
0, mininter->color) : color_scalar(AMBIENTLIGHT +
DIFFUSELIGHT * shade, mininter->color);
}
else
result = new_color(0, 0, 0);
return (result);
}
Some screeshots.
Scene file : 0° rotation
camera:
pos:
0, 0, 100
dir:
0, 0, 0
----
spheres:
new:
pos:
20, 0, 20
radius:
30
color:
42, 255, 255
----
----
cylinders:
new:
pos:
-20, 0, -30
radius:
20
color:
255, 42, 23
rotate:
0, 0, 0
----
----
spot:
pos:
50, 0, 150
----
END
https://gyazo.com/6ab10dbfba27a889ac6397c30aa4adda
Scene file : 42° rotation
camera:
pos:
0, 0, 100
dir:
0, 0, 0
----
spheres:
new:
pos:
20, 0, 20
radius:
30
color:
42, 255, 255
----
----
cylinders:
new:
pos:
-20, 0, -30
radius:
20
color:
255, 42, 23
rotate:
42, 0, 0
----
----
spot:
pos:
50, 0, 150
----
END
https://gyazo.com/f244f6c7e2d2a81b6001fc175c16c289
Scene file : 91° rotation
camera:
pos:
0, 0, 100
dir:
0, 0, 0
----
spheres:
new:
pos:
20, 0, 20
radius:
30
color:
42, 255, 255
----
----
cylinders:
new:
pos:
-20, 0, -30
radius:
20
color:
255, 42, 23
rotate:
91, 0, 0
----
----
spot:
pos:
50, 0, 150
----
END
https: //gyazo.com/86cda440cfca079d07e04d1ef19b8a21
Anything will help, thanks in advance !
Consider your rotation around the x axis:
static t_vect *x(t_vect *v, double rot, int stage)
{
rot = DEG_TO_RAD(rot * stage);
v->y = v->y * cos(rot) + v->z * -sin(rot);
v->z = v->y * sin(rot) + v->z * cos(rot);
return (v);
}
Notice that the y coordinate of the input vector contributes to both the y and z coordinates of the result vector. Now notice that what you actually use in the computation of the resulting z coordinate is not the input y, but rather the computed result y. This is erroneous.
Similar applies to your other rotation functions.

Resources