Raytracing Rotations - c

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.

Related

Leaflet map renderer L.svg changed already existing canvas markers

I have set renderer value L.svg with a padding of 100 for map as shown below
Before setting this option canvas markers were visible like this
After setting renderer option markers are visible like this
Code to render canvas marker is as follows
(function () {
var proto = L.Canvas.prototype;
var prev = proto._updateCircle;
proto._updateCircle = function (layer) {
// only circleMARKER, not the standard circle
if (layer instanceof L.Circle)
return prev.call(this, layer);
if (!this._drawing || layer._empty()) {
return;
}
var p = layer._point,
ctx = this._ctx,
r = Math.max(Math.round(layer._radius), 1)
//,s = (Math.max(Math.round(layer._radiusY), 1) || r) / r;
var options = layer.options;
var scale = Math.pow(2, this._map.getZoom()) * 256 / Math.PI / 6378137;
scale = Math.pow(scale, options.boostExp) * options.boostScale;
r = r * scale;
if (!options.boostType) {
ctx.beginPath();
ctx.arc(p.x, p.y, r, 0, Math.PI * 2, false);
this._fillStroke(ctx, layer);
}
else switch (options.boostType) {
case 'ball':
if (options.fill) {
if (options.stroke && options.weight !== 0)
r = r + options.weight * 0.5 * scale;
let grd = ctx.createRadialGradient(p.x - r / 2, p.y - r / 2, 0, p.x, p.y, 1.5 * r);
grd.addColorStop(0, options.fillColor);
grd.addColorStop(1, options.color);
ctx.beginPath();
ctx.fillStyle = grd;
ctx.arc(p.x, p.y, r, 0, Math.PI * 2, false);
ctx.fill(options.fillRule || 'evenodd');
}
break;
case 'balloon':
if (options.fill) {
if (options.stroke && options.weight !== 0)
r = r + options.weight * 0.5 * scale;
// this condition is used to identify if employee is at suggested location and draw a star on top of marker
let grd = ctx.createRadialGradient(p.x - r / 2, p.y - r / 2 - 2 * r, 0, p.x, p.y - 2 * r, 2.5 * r);
grd.addColorStop(0, options.fillColor);
grd.addColorStop(1, options.color);
ctx.beginPath();
ctx.fillStyle = grd;
ctx.moveTo(p.x, p.y);
ctx.lineTo(p.x - r, p.y - 2 * r);
ctx.lineTo(p.x + r, p.y - 2 * r);
ctx.lineTo(p.x, p.y);
ctx.arc(p.x, p.y - 2 * r, r, 0, Math.PI * 2, false);
ctx.closePath();
ctx.fill(options.fillRule = 'nonzero');
if(options.suggestedLocation)
drawStar(p.x, p.y - 2 * r, 5, 3, 1.5, ctx);
}
break;
case 'borderedball':
if (options.fill) {
if (options.stroke && options.weight !== 0)
r = r + options.weight * 0.5 * scale;
let grd = ctx.createRadialGradient(p.x - r / 2, p.y - r / 2, 0, p.x, p.y, 1.5 * r);
grd.addColorStop(0, options.fillColor);
grd.addColorStop(1, options.color);
ctx.beginPath();
drawStar(p.x, p.y, 5, r, r, ctx);
ctx.fillStyle = grd;
ctx.arc(p.x, p.y, r, 0, Math.PI * 2, false);
ctx.fill(options.fillRule || 'evenodd');
}
break;
default:
if (options.stroke && options.weight !== 0) {
ctx.beginPath();
ctx.arc(p.x, p.y, r + options.weight * 0.5 * scale, 0, Math.PI * 2, false);
ctx.fillStyle = options.color;
ctx.fill(options.fillRule || 'evenodd');
}
if (options.fill) {
ctx.beginPath();
ctx.arc(p.x, p.y, r - ((options.stroke && options.weight !== 0) ? options.weight * 0.5 * scale : 0), 0, Math.PI * 2, false);
ctx.fillStyle = options.fillColor || options.color;
ctx.fill(options.fillRule || 'evenodd');
}
}
};
var xproto = L.CircleMarker.prototype;
var xprev = xproto._containsPoint;
xproto._containsPoint = function (p) {
if (this instanceof L.Circle)
return xprev.call(this, p);
var r = this._radius;
var options = this.options;
var scale = Math.pow(2, this._map.getZoom()) * 256 / Math.PI / 6378137;
scale = Math.pow(scale, options.boostExp) * options.boostScale;
r = r * scale;
r = r + (this.options.stroke ? this.options.weight * scale / 2 : 0);
if (options.boostType === 'balloon')
p = new L.Point(p.x, p.y + 2 * r);
return p.distanceTo(this._point) <= r + this._clickTolerance();
// clickTolerance only for mobile! (seems to be fixed with LL1.4)
// return p.distanceTo(this._point) <= r + ((L.Browser.touch && L.Browser.mobile) ? 10 : 0);
};
var cproto = L.Layer.prototype;
var cprev = cproto._openPopup;
cproto._openPopup = function (e) {
var layer = e.layer || e.target;
if (!(layer instanceof L.CircleMarker) || (layer instanceof L.Circle))
return cprev.call(this, e);
if (!this._popup) {
return;
}
if (!this._map) {
return;
}
// prevent map click
L.DomEvent.stop(e);
// treat it like a marker and figure out
// if we should toggle it open/closed
if (this._map.hasLayer(this._popup) && this._popup._source === layer) {
this.closePopup();
} else {
this.openPopup(layer._latlng);
layer.on('preclick', L.DomEvent.stopPropagation);
}
};
var pproto = L.Popup.prototype;
var p_getAnchor = pproto._getAnchor;
pproto._getAnchor = function () {
if (!(this._source instanceof L.CircleMarker) || this._source instanceof L.Circle)
return p_getAnchor.call(this);
var r = this._source._radius;
var options = this._source.options;
//var zoomScale;
var scale = Math.pow(2, this._map.getZoom()) * 256 / Math.PI / 6378137;
scale = Math.pow(scale, options.boostExp) * options.boostScale;
if (options.boostType === 'balloon')
r = 2.5 * r * scale;
else
r = 0.5 * r * scale;
// Where should we anchor the popup on the source layer?
return L.point(this._source && this._source._getPopupAnchor ? this._source._getPopupAnchor() : [0, -r]);
};
})();
function drawDiamond(context, x, y, width, height) {
context.moveTo(x, y);
// top left edge
context.lineTo(x - width / 2, y + height / 2);
// bottom left edge
context.lineTo(x, y + height);
// bottom right edge
context.lineTo(x + width / 2, y + height / 2);
}
function drawStar(cx, cy, spikes, outerRadius, innerRadius, ctx) {
var rot = Math.PI / 2 * 3;
var x = cx;
var y = cy;
var step = Math.PI / spikes;
ctx.beginPath();
ctx.moveTo(cx, cy - outerRadius)
for (let i = 0; i < spikes; i++) {
x = cx + Math.cos(rot) * outerRadius;
y = cy + Math.sin(rot) * outerRadius;
ctx.lineTo(x, y)
rot += step
x = cx + Math.cos(rot) * innerRadius;
y = cy + Math.sin(rot) * innerRadius;
ctx.lineTo(x, y)
rot += step
}
ctx.lineTo(cx, cy - outerRadius);
ctx.closePath();
ctx.lineWidth = 5;
ctx.strokeStyle = 'blue';
ctx.stroke();
ctx.fillStyle = 'skyblue';
ctx.fill();
}
Please suggest a solution to render canvas markers as they were before setting renderer value to L.svg.

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

OpenGL in C language add another object

I need help adding another object to my "drawing".
With the help of my college teacher code with Google I was able to create a face shape.
I want to add a smile to the face
What to add another shape to the drawing?
I tried to append to the void face() something like:
glVertex2f(100, 125);
glVertex2f(400, 125);
This is the code in C language:
#include <GL/glut.h>
#include <math.h>
#include<Windows.h>
#include <GL/gl.h>
#include <GL/GLU.h>
#include <stdlib.h>
float counter = 200;
static GLfloat spin = 0.0;
static GLfloat R = 0.2;
static GLfloat G = 0.9;
static GLfloat B = 0.8;
float carx = 500, cary = 50, fr = 0, fl = 0, fo = 0, fu = 0, mx = 0, my = 0;
void initOpenGl()
{
glClearColor(0.0, 0.0, 1.8, 0); //Background Color
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, 1500, 0, 500);
glMatrixMode(GL_MODELVIEW);
}
void eye(int x, int y)
{
float th;
glBegin(GL_POLYGON);
glColor3f(0, 0, 0);
for (int i = 0; i < 360; i++)
{
th = i * (3.1416 / 180);
glVertex2f(x + 25 * cos(th), y + 20 * sin(th));
}
glEnd();
}
void face()
{
glLoadIdentity();//Bottom Par
counter = counter - 0.03;
if (fr > 0)
carx += fr;
if (fl > 0)
carx -= fl;
if (fu > 0)
cary += fu;
if (fo > 0)
cary -= fo;
if (mx > 0)
carx += mx;
if (my > 0)
carx -= my;
glTranslated(carx, cary, 0.0);
glBegin(GL_POLYGON); //Top Part
glVertex2f(100, 125);
glVertex2f(400, 125);
glVertex2f(400, 300);
glVertex2f(100, 300);
glEnd();
eye(165, 230);
eye(315, 230);
}
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.5, 0.9, 0.33); //Push and pop matrix for separating circle object from Background
face();
pa();
glutSwapBuffers();
glFlush();
}
void mouse(int button)
{
switch (button) {
case GLUT_LEFT_BUTTON: mx = 0.3;
break;
case GLUT_RIGHT_BUTTON:my = 0.2;
break;
default:
break;
}
}
void keyFunc(unsigned char key, int x, int y)
{
switch (key) {
case 'w': fu = 0.3, fo = 0, fr = 0, fl = 0;
break;
case 's': fu = 0, fo = 0.2, fr = 0, fl = 0;
break;
case 'a': fu = 0.01, fo = 0, fr = 0, fl = 0.2;
break;
case 'd': fu = 0.01, fo = 0, fr = 0.2, fl = 0;
break;
case 'z': fu = 0, fo = 0.2, fr = 0, fl = 0.2;
break;
case 'c': fu = 0, fo = 0.2, fr = 0.2, fl = 0;
break;
default:
break;
}
glutPostOverlayRedisplay();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(1500, 700);
glutInitWindowPosition(0, 0);
glutCreateWindow("Shai Goldenebrg");
initOpenGl();
glutDisplayFunc(display);
glutMouseFunc(mouse);
glutKeyboardFunc(keyFunc);
glutIdleFunc(display);
glutMainLoop();
return 0;
}
A smiling mouth is a Concave polygon. I recommend to use a GL_TRIANGLE_STRIP primitive to generate the mouth. e.g:
void mouth(int x, int y)
{
float th, s, c;
glBegin(GL_TRIANGLE_STRIP);
glColor3f(0, 0, 0);
for (int i = 240; i < 300; i++)
{
th = i * (3.1416 / 180);
c = cos(th);
s = sin(th);
glVertex2f(x + 90 * cos(th), y + 100 + 90 * sin(th));
glVertex2f(x + 110 * cos(th), y + 100 + 110 * sin(th));
}
glEnd();
}
void face()
{
// [...]
eye(165, 230);
eye(315, 230);
mouth(240, 150);
}

Getting the normal of a cone - Raytracing

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.

Get pixel color at mouse position fastest way

So actually i got a very fast and nice code from "Vodemki" in here -
Get Pixel color fastest way?
But only problem it scans the whole image while i need to scan only
my current mouse position
Here's the code -
HDC hdc, hdcTemp;
RECT rect;
BYTE* bitPointer;
int x, y;
int red, green, blue, alpha;
while(true)
{
hdc = GetDC(HWND_DESKTOP);
GetWindowRect(hWND_Desktop, &rect);
int MAX_WIDTH = rect.right;
int MAX_HEIGHT = rect.bottom;
hdcTemp = CreateCompatibleDC(hdc);
BITMAPINFO bitmap;
bitmap.bmiHeader.biSize = sizeof(bitmap.bmiHeader);
bitmap.bmiHeader.biWidth = MAX_WIDTH;
bitmap.bmiHeader.biHeight = MAX_HEIGHT;
bitmap.bmiHeader.biPlanes = 1;
bitmap.bmiHeader.biBitCount = 32;
bitmap.bmiHeader.biCompression = BI_RGB;
bitmap.bmiHeader.biSizeImage = MAX_WIDTH * 4 * MAX_HEIGHT;
bitmap.bmiHeader.biClrUsed = 0;
bitmap.bmiHeader.biClrImportant = 0;
HBITMAP hBitmap2 = CreateDIBSection(hdcTemp, &bitmap, DIB_RGB_COLORS, (void**)(&bitPointer), NULL, NULL);
SelectObject(hdcTemp, hBitmap2);
BitBlt(hdcTemp, 0, 0, MAX_WIDTH, MAX_HEIGHT, hdc, 0, 0, SRCCOPY);
for (int i=0; i<(MAX_WIDTH * 4 * MAX_HEIGHT); i+=4)
{
red = (int)bitPointer[i];
green = (int)bitPointer[i+1];
blue = (int)bitPointer[i+2];
alpha = (int)bitPointer[i+3];
x = i / (4 * MAX_HEIGHT);
y = i / (4 * MAX_WIDTH);
if (red == 255 && green == 0 && blue == 0)
{
SetCursorPos(x,y);
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
Sleep(50);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
Sleep(25);
}
}
}
I'm not familiar with BitBlt, So if anyone can help me modify that code i'll appreciate it
Thanks!
Alright I made it finally.
I still got problem with the timing, makes my puter very slow...
I'll work for it later...
Here's the code -
//Globals
int sX, sY, x, y;
BYTE* sData = 0;
POINT cursorPos;
HDC hScreen;
HDC hdcMem;
HBITMAP hBitmap;
HGDIOBJ hOld;
void PixelFunction(); // Get the pixel rgb function
int main()
{
PixelFunction();
ReleaseDC(NULL, hScreen);
DeleteDC(hdcMem);
return 0;
}
void PixelFunction()
{
int Red, Green, Blue;
hScreen = GetDC(NULL);
sX = GetDeviceCaps(hScreen, HORZRES);
sY = GetDeviceCaps(hScreen, VERTRES);
hdcMem = CreateCompatibleDC (hScreen);
hBitmap = CreateCompatibleBitmap(hScreen, sX, sY);
BITMAPINFOHEADER bm = {0};
bm.biSize = sizeof(BITMAPINFOHEADER);
bm.biPlanes = 1;
bm.biBitCount = 32;
bm.biWidth = sX;
bm.biHeight = -sY;
bm.biCompression = BI_RGB;
bm.biSizeImage = 0; // 3 * sX * sY;
while (1) {
hOld = SelectObject(hdcMem, hBitmap);
BitBlt(hdcMem, 0, 0, sX, sY, hScreen, 0, 0, SRCCOPY);
SelectObject(hdcMem, hOld);
free(sData);
sData = (BYTE*)malloc(4 * sX * sY);
GetDIBits(hdcMem, hBitmap, 0, sY, sData, (BITMAPINFO*)&bm, DIB_RGB_COLORS);
GetCursorPos(&cursorPos);
x = cursorPos.x;
y = cursorPos.y;
Red = sData[4 * ( (y * sX) + x) +2];
Green = sData[4 * ( ( y * sX) + x) +1];
Blue = sData[4 * ( (y * sX) + x)];
// Check for color
if (Red == 255 && Green == 0 && Blue == 0) {
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
Sleep(5);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
}
Sleep(10);
}
}
Hope it helped!

Resources