MA-software-rendering/Sourse/Data/sourse/primitives/ray.cpp

122 lines
2.5 KiB
C++

#include "ray.h"
#include "MaMath.h"
float trig_area(vec3f* p1, vec3f* p2, vec3f* p3) {
vec3f v1 = vec3f(p2);
vec3f v2 = vec3f(p3);
v1 -= *p1;
v2 -= *p1;
vec3f cross_prd;
v1.cross(&v2, &cross_prd);
return cross_prd.mod() / 2.f;
}
Ray::Ray()
{
intersect = false;
obj = nullptr;
}
Ray::~Ray()
{
}
void apply_transformation(vec3f *vec, vec3f* iv, vec3f* jv, vec3f* kv, vec3f *pos) {
vec3f i = vec3f(iv);
vec3f j = vec3f(jv);
vec3f k = vec3f(kv);
i *= vec->x;
j *= vec->y;
k *= vec->z;
*vec = (k += (i += j));
*vec += *pos;
}
void norm(vec3f* v1, vec3f* v2, vec3f* v3, vec3f* out)
{
vec3f vec1 = vec3f(v2);
vec3f vec2 = vec3f(v3);
vec1 -= v1;
vec2 -= v1;
vec1.cross(&vec2, out);
*out /= out->mod();
}
void Ray::shoot(_DA_MeshObjects* DA_MeshObjects) {
float magnitude = INF;
vec3f trig_norm = vec3f();
vec3f intersect_point = vec3f(Dir);
_DAI_Object* Obj = nullptr;
int Objlen = DA_MeshObjects->Obj_GetLength();
for (int obj_idx = 0; obj_idx < Objlen; obj_idx++) {
_DAI_Object* tmp_Obj = DA_MeshObjects->Obj_GetItem(obj_idx);
int triglen = tmp_Obj->Mesh.DA_Trigs->DA_Trigs_GetLength();
for (int trig_idx = 0; trig_idx < triglen; trig_idx++) {
_DAI_Trig* trig = tmp_Obj->Mesh.DA_Trigs->DAI_Trig_GetItem(trig_idx);
vec3f v1 = vec3f(trig->v1->vec);
vec3f v2 = vec3f(trig->v2->vec);
vec3f v3 = vec3f(trig->v3->vec);
apply_transformation(&v1, &tmp_Obj->unit_vx, &tmp_Obj->unit_vy, &tmp_Obj->unit_vz, &tmp_Obj->Position);
apply_transformation(&v2, &tmp_Obj->unit_vx, &tmp_Obj->unit_vy, &tmp_Obj->unit_vz, &tmp_Obj->Position);
apply_transformation(&v3, &tmp_Obj->unit_vx, &tmp_Obj->unit_vy, &tmp_Obj->unit_vz, &tmp_Obj->Position);
vec3f tmp_trig_norm = vec3f();
norm(&v1, &v2, &v3, &tmp_trig_norm);
if (tmp_trig_norm * Dir >= 0) {
tmp_trig_norm.invert();
}
vec3f tmp = vec3f(Pos);
tmp -= v1;
float tmp_magnitude = (tmp_trig_norm * tmp) / -(tmp_trig_norm * Dir);
vec3f tmp_intrsect_p = vec3f(Dir);
tmp_intrsect_p *= tmp_magnitude;
tmp_intrsect_p += Pos;
if (trig_area(&v1, &v2, &v3) >=
trig_area(&tmp_intrsect_p, &v2, &v3) +
trig_area(&v1, &tmp_intrsect_p, &v3) +
trig_area(&v1, &v2, &tmp_intrsect_p) - 0.00001f) {
if (magnitude > tmp_magnitude && tmp_magnitude > 0)
{
Obj = tmp_Obj;
trig_norm = tmp_trig_norm;
intersect_point = tmp_intrsect_p;
magnitude = tmp_magnitude;
}
}
}
}
if (magnitude == INF) {
intersect = false;
return;
}
intersect = true;
obj = Obj;
intersect_p = intersect_point;
Norm = trig_norm;
}