Skip to content

Latest commit

 

History

History
331 lines (276 loc) · 7.02 KB

02.vector.md

File metadata and controls

331 lines (276 loc) · 7.02 KB

2. 벡터

우리는 3차원 공간을 구현할 때에 점의 위치, 방향을 수학적으로 계산하기 위해 벡터를 사용할 것이다. 벡터를 이용하면 여러가지 도형, 빛의 위치, 방향을 쉽게 다룰 수 있다. 따라서 벡터의 개념을 잘 이해하지 못했다면 벡터에 대해 간단하게 공부를 하고 오기 바란다. 벡터 공부


2.1. 실습목표

  1. write_color함수 만들기.

  2. 3차원 벡터 구조체 만들기.

  3. 3차원 벡터 유틸리티 함수 만들기.

우리가 만들 레이 트레이서 프로그램은 3차원 유클리드 좌표계(익히 알고 있는 x, y, z 3축으로 된 좌표계)를 사용할 것이다..

이번 단원에서는 우리가 생성하게 될 카메라, 광선, 구체 등의 점, 벡터, 색상 정보를 저장하기 위한 3차원 벡터 구조체를 만들고 벡터 연산을 위한 유틸리티 함수 세트를 만들 것이다.


2.2. write_color 만들고 적용시키기.

#ifndef PRINT_H
# define PRINT_H

# include "stdio.h"
# include "structures.h"

void	write_color(t_color3 pixel_color);

#endif

Code1 : [/include/print.h]

ppm에 color를 출력하는 함수를 넣어줬다.

#include "print.h"

// [0,1] 로 되어있는 rgb 값을 각각 [0,255]에 맵핑 해서 출력.
void	write_color(t_color3 pixel_color)
{
	printf("%d %d %d\n", (int)(255.999 * pixel_color.x),
						(int)(255.999 * pixel_color.y),
						(int)(255.999 * pixel_color.z));
}

Code2 : [/src/print/print.c]

rgb값을 출력하는 함수.

#include <stdio.h>
// 추가
#include "structures.h"
#include "utils.h"
#include "print.h"
// 추가 끝

int	main(void)
{
	// 제거
	int		i;
	int		j;
	double	r;
	double	g;
	double	b;
	int		canvas_width;
	int		canvas_height;
	// 제거 끝
	// 추가
	int			i;
	int			j;
	t_color3	pixel_color;
	int			canvas_width;
	int			canvas_height;
	// 추가 끝
	//캔버스의 가로, 세로 픽셀값
	canvas_width = 256;

	...

	i = 0;
		while (i < canvas_width)
		{
			// 제거
			r = (double)i / (canvas_width - 1);
			g = (double)j / (canvas_height - 1);
			b = 0.25;
			printf("%d %d %d\n", (int)(255.999 * r), (int)(255.999 * g), (int)(255.999 * b));
			// 제거 끝
			// 추가
			pixel_color.x = (double)i / (canvas_width - 1);
			pixel_color.y = (double)j / (canvas_height - 1);
			pixel_color.z = 0.25;
			write_color(pixel_color);
			// 추가 끝
		++i;
		}
	--j;

Code3 : [/src/main.c]

rgb값을 출력하는 함수를 아래에 write_color함수로 따로 만들었기 때문에 변수 rgb값을 출력하는 부분을 제거해줬다.


2.3. 벡터 유틸함수 만들어 적용시키기.

#ifndef STRUCTURES_H
# define STRUCTURES_H

typedef struct s_vec3 t_vec3;
typedef struct s_vec3 t_point3;
typedef struct s_vec3 t_color3;

struct s_vec3
{
	double x;
	double y;
	double z;
};
#endif

Code4 : [/include/structures.h]

구조체는 모두 structure.h에 넣기로 약속하고 벡터가 아닌 점의 위치, color 또한 세개의 변수가 필요하기 때문에 같은 t_vec3 구조체에 이름만 t_point3, t_color3로 정해두었다.

utils.h

#ifndef UTILS_H
# define UTILS_H

# include <math.h>
# include <stdlib.h>
# include <stdio.h>
# include "structures.h"

t_vec3		vec3(double x, double y, double z);
t_point3	point3(double x, double y, double z);
t_point3	color3(double r, double g, double b);
void		vset(t_vec3 *vec, double x, double y, double z);
double		vlength2(t_vec3 vec);
double		vlength(t_vec3 vec);
t_vec3		vplus(t_vec3 vec, t_vec3 vec2);
t_vec3		vplus_(t_vec3 vec, double x, double y, double z);
t_vec3		vminus(t_vec3 vec, t_vec3 vec2);
t_vec3		vminus_(t_vec3 vec, double x, double y, double z);
t_vec3		vmult(t_vec3 vec, double t);
t_vec3		vmult_(t_vec3 vec, t_vec3 vec2);
t_vec3		vdivide(t_vec3 vec, double t);
double		vdot(t_vec3 vec, t_vec3 vec2);
t_vec3		vcross(t_vec3 vec, t_vec3 vec2);
t_vec3		vunit(t_vec3 vec);
t_vec3		vmin(t_vec3 vec1, t_vec3 vec2);

#endif

Code5 : [/include/utils.h]

우리가 만든 벡터구조체에 대한 연산 방법이 정해져있지 않기 때문에 연산함수를 구현해야 한다.

#include "utils.h"

//벡터3 생성자
t_vec3		vec3(double x, double y, double z)
{
	t_vec3 vec;

	vec.x = x;
	vec.y = y;
	vec.z = z;
	return (vec);
}

//포인트3 생성자
t_point3	point3(double x, double y, double z)
{
	t_point3 point;

	point.x = x;
	point.y = y;
	point.z = z;
	return (point);
}

//색상3 생성자
t_point3	color3(double r, double g, double b)
{
	t_color3 color;

	color.x = r;
	color.y = g;
	color.z = b;
	return (color);
}

// 벡터 값 설정
void		vset(t_vec3 *vec, double x, double y, double z)
{
	vec->x = x;
	vec->y = y;
	vec->z = z;
}

// 벡터 길이 제곱
double		vlength2(t_vec3 vec)
{
	return (vec.x * vec.x + vec.y * vec.y + vec.z * vec.z);
}

// 벡터 길이
double		vlength(t_vec3 vec)
{
	return (sqrt(vlength2(vec)));
}

// 벡터합
t_vec3		vplus(t_vec3 vec, t_vec3 vec2)
{
	vec.x += vec2.x;
	vec.y += vec2.y;
	vec.z += vec2.z;
	return (vec);
}

// 벡터합2
t_vec3		vplus_(t_vec3 vec, double x, double y, double z)
{
	vec.x += x;
	vec.y += y;
	vec.z += z;
	return (vec);
}

// 벡터차
t_vec3		vminus(t_vec3 vec, t_vec3 vec2)
{
	vec.x -= vec2.x;
	vec.y -= vec2.y;
	vec.z -= vec2.z;
	return (vec);
}

t_vec3		vminus_(t_vec3 vec, double x, double y, double z)
{
	vec.x -= x;
	vec.y -= y;
	vec.z -= z;
	return (vec);
}

// 벡터 * 스칼라 곱연산
t_vec3		vmult(t_vec3 vec, double t)
{
	vec.x *= t;
	vec.y *= t;
	vec.z *= t;
	return (vec);
}

// 벡터 축 값끼리 곱연산
t_vec3		vmult_(t_vec3 vec, t_vec3 vec2)
{
	vec.x *= vec2.x;
	vec.y *= vec2.y;
	vec.z *= vec2.z;
	return (vec);
}

// 벡터 스칼라 나누기
t_vec3		vdivide(t_vec3 vec, double t)
{
	vec.x *= 1 / t;
	vec.y *= 1 / t;
	vec.z *= 1 / t;

	return vec;
}

// 벡터 내적
double		vdot(t_vec3 vec, t_vec3 vec2)
{
	return (vec.x * vec2.x + vec.y * vec2.y + vec.z * vec2.z);
}

// 벡터 외적
t_vec3		vcross(t_vec3 vec, t_vec3 vec2)
{
	t_vec3 new;

	new.x = vec.y * vec2.z - vec.z * vec2.y;
	new.y = vec.z * vec2.x - vec.x * vec2.z;
	new.z = vec.x * vec2.y - vec.y * vec2.x;
	return (new);
}

// 단위 벡터
t_vec3		vunit(t_vec3 vec)
{
	double len = vlength(vec);
	if (len == 0)
	{
		printf("Error\n:Devider is 0");
		exit(0);
	}
	vec.x /= len;
	vec.y /= len;
	vec.z /= len;
	return (vec);
}

// 두 벡터의 원소를 비교하여 작은 값들만 반환 
t_vec3	vmin(t_vec3 vec1, t_vec3 vec2)
{
	if (vec1.x > vec2.x)
		vec1.x = vec2.x;
	if (vec1.y > vec2.y)
		vec1.y = vec2.y;
	if (vec1.z > vec2.z)
		vec1.z = vec2.z;
	return (vec1);
}

Code6 : [/src/utils/vec3_utils.c]

각 벡터연산의 개념은 벡터의 개념에 대해 이해하면 쉽게 이해할 것이라 믿는다. 여기서 vec3, color3, point3는 같아보이지만 개념적으로 다르다고 생각했기에 다른이름으로 분류해두었다. 단위벡터는 길이가 1인 벡터를 의미하는데 이는 방향벡터를 다룰 때에 편리하기 때문에 사용한다.