merge latest public version from Ninestars
This commit is contained in:
parent
5e45050e83
commit
0cf9a6c9af
|
@ -10,8 +10,13 @@ include(Fxconv)
|
|||
find_package(Gint 2.1 REQUIRED)
|
||||
|
||||
set(SOURCES
|
||||
src/Geometry.cpp
|
||||
src/main.cpp
|
||||
src/windmill.cpp
|
||||
src/windmill_load.cpp
|
||||
src/windmill_draw.cpp
|
||||
src/windmill_clip.cpp
|
||||
src/windmill_transform.cpp
|
||||
src/windmill_utility.cpp
|
||||
src/map.cpp
|
||||
src/scene_map.cpp
|
||||
src/camera.cpp
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
#include "Geometry.hpp"
|
||||
|
||||
// VECTOR3D
|
||||
Vector3D::Vector3D()
|
||||
{
|
||||
x = 0;
|
||||
y = 0;
|
||||
z = 0;
|
||||
}
|
||||
|
||||
Vector3D::Vector3D(float _x, float _y, float _z)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
z = _z;
|
||||
}
|
||||
|
||||
Vector3D Vector3D::Add(Vector3D vector)
|
||||
{
|
||||
return Vector3D(x + vector.x, y + vector.y, z + vector.z);
|
||||
}
|
||||
|
||||
Vector3D Vector3D::Substract(Vector3D vector)
|
||||
{
|
||||
return Vector3D(x - vector.x, y - vector.y, z - vector.z);
|
||||
}
|
||||
|
||||
Vector3D Vector3D::Multiply(float value)
|
||||
{
|
||||
return Vector3D(x * value, y * value, z * value);
|
||||
}
|
||||
|
||||
Vector3D Vector3D::Divide(float value)
|
||||
{
|
||||
float inv = 1 / value;
|
||||
return Vector3D(x * inv, y * inv, z * inv);
|
||||
}
|
||||
|
||||
float Vector3D::Dot(Vector3D vector)
|
||||
{
|
||||
return x * vector.x + y * vector.y + z * vector.z;
|
||||
}
|
||||
|
||||
Vector3D Vector3D::Cross(Vector3D vector)
|
||||
{
|
||||
return Vector3D(x * vector.y - y * vector.x, y * vector.z - z * vector.y, z * vector.x - x * vector.z);
|
||||
}
|
||||
|
||||
Point3D Vector3D::ToPoint3D()
|
||||
{
|
||||
return Point3D(x, y, z);
|
||||
}
|
||||
|
||||
bool Vector3D::Null()
|
||||
{
|
||||
return (x == 0 and y == 0 and z == 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// POINT3D
|
||||
Point3D::Point3D()
|
||||
{
|
||||
x = 0;
|
||||
y = 0;
|
||||
z = 0;
|
||||
}
|
||||
|
||||
Point3D::Point3D(float _x, float _y, float _z)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
z = _z;
|
||||
}
|
||||
|
||||
Point3D Point3D::Add(Vector3D vector)
|
||||
{
|
||||
return Point3D(x + vector.x, y + vector.y, z + vector.z);
|
||||
}
|
||||
|
||||
Point3D Point3D::Substract(Vector3D vector)
|
||||
{
|
||||
return Point3D(x - vector.x, y - vector.y, z - vector.z);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
#ifndef DEF_GEOMETRY
|
||||
#define DEF_GEOMETRY
|
||||
|
||||
class Point3D;
|
||||
class Vector3D;
|
||||
|
||||
|
||||
class Vector3D
|
||||
{
|
||||
public:
|
||||
Vector3D();
|
||||
Vector3D(float _x, float _y, float _z);
|
||||
|
||||
Vector3D Add(Vector3D vector);
|
||||
Vector3D Substract(Vector3D vector);
|
||||
Vector3D Multiply(float value);
|
||||
Vector3D Divide(float value);
|
||||
|
||||
float Dot(Vector3D vector);
|
||||
Vector3D Cross(Vector3D vector);
|
||||
|
||||
Point3D ToPoint3D();
|
||||
bool Null();
|
||||
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
|
||||
};
|
||||
|
||||
class Point3D
|
||||
{
|
||||
public:
|
||||
Point3D();
|
||||
Point3D(float _x, float _y, float _z);
|
||||
|
||||
Point3D Add(Vector3D vector);
|
||||
Point3D Substract(Vector3D vector);
|
||||
Point3D Rotate(Vector3D rotation, float angle);
|
||||
|
||||
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -10,19 +10,23 @@ Camera::Camera()
|
|||
z = 0;
|
||||
yaw = 0;
|
||||
pitch = 0;
|
||||
fov = 50;
|
||||
near = 1;
|
||||
|
||||
fov = 50; // degrés
|
||||
near = 5;
|
||||
far = 1000;
|
||||
|
||||
float fov_rad = to_rad(fov);
|
||||
scale_coef = 64 * near * tanf(fov_rad);
|
||||
cos_fov = SCALE_AI * cosf(fov_rad);
|
||||
scale_coef = 128 / 2 * tanf(to_rad(fov)); // = 64 * 1 * 1,19 = 76,27
|
||||
//scale_coef2 = tanf(to_rad(fov)); // = 1 * 1,19 = 1.19
|
||||
|
||||
//cos_fov = SCALE_AI * cosf(fov_rad);
|
||||
//sin_fov = SCALE_AI * sinf(fov_rad);
|
||||
sin_fov = sinf(fov_rad);
|
||||
cos_fov_square = cosf(fov_rad) * cosf(fov_rad);
|
||||
//sin_fov = sinf(fov_rad);
|
||||
//cos_fov_square = cosf(fov_rad) * cosf(fov_rad);
|
||||
//near_coef = - far / float(far - near);
|
||||
//far_coef = - far * near * 128 / (far - near);
|
||||
|
||||
|
||||
setup_frustrum();
|
||||
}
|
||||
|
||||
|
||||
|
@ -52,11 +56,11 @@ void Camera::set(Camera* _camera)
|
|||
//-----------------------------------------------------------------------------
|
||||
void Camera::update()
|
||||
{
|
||||
if (look_at_duration)
|
||||
/*if (look_at_duration)
|
||||
{
|
||||
yaw = (yaw * (look_at_duration - 1) + look_at_yaw) / look_at_duration;
|
||||
look_at_duration -= 1;
|
||||
}
|
||||
}*/
|
||||
|
||||
cos_yaw = cosf(yaw);
|
||||
sin_yaw = sinf(yaw);
|
||||
|
@ -86,7 +90,7 @@ void Camera::update()
|
|||
a9 = SCALE_AI * cos_pitch;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
//-----------------------------------------------------------------------------
|
||||
// NORMAL_VECTOR
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -169,4 +173,53 @@ void Camera::look_at(float look_at_x, float look_at_y, float look_at_z, float du
|
|||
//look_at_pitch = atan2(look_at_z - z, look_at_x - x);
|
||||
// calcule de sqrt ??
|
||||
look_at_duration = duration;
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
void Camera::setup_frustrum()
|
||||
{
|
||||
float angle_horizontal = to_rad(fov);
|
||||
float angle_vertical = to_rad(fov / 2);
|
||||
int sh = sinf(angle_horizontal) * 1000;
|
||||
int sv = sinf(angle_vertical) * 1000;
|
||||
int ch = cosf(angle_horizontal) * 1000;
|
||||
int cv = cosf(angle_vertical) * 1000;
|
||||
|
||||
// z-near clipping plane
|
||||
frustrum.sides[0].normal_x = 0;
|
||||
frustrum.sides[0].normal_y = 0;
|
||||
frustrum.sides[0].normal_z = 1;
|
||||
frustrum.sides[0].distance = -near * 1000;
|
||||
// right
|
||||
frustrum.sides[1].normal_x = -ch;
|
||||
frustrum.sides[1].normal_y = 0;
|
||||
frustrum.sides[1].normal_z = sh;
|
||||
frustrum.sides[1].distance = 0;
|
||||
// top
|
||||
frustrum.sides[2].normal_x = 0;
|
||||
frustrum.sides[2].normal_y = cv;
|
||||
frustrum.sides[2].normal_z = sv;
|
||||
frustrum.sides[2].distance = 0;
|
||||
// left
|
||||
frustrum.sides[3].normal_x = ch;
|
||||
frustrum.sides[3].normal_y = 0;
|
||||
frustrum.sides[3].normal_z = sh;
|
||||
frustrum.sides[3].distance = 0;
|
||||
// bottom
|
||||
frustrum.sides[4].normal_x = 0;
|
||||
frustrum.sides[4].normal_y = -cv;
|
||||
frustrum.sides[4].normal_z = sv;
|
||||
frustrum.sides[4].distance = 0;
|
||||
|
||||
// z-far clipping plane
|
||||
//frustrum.z_far.normal.x = 0;
|
||||
//frustrum.z_far.normal.y = 0;
|
||||
//frustrum.z_far.normal.z = -1;
|
||||
//frustrum.z_far.distance = 1000;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -43,15 +43,37 @@
|
|||
|
||||
#include <math.h>
|
||||
#include <gint/defs/util.h>
|
||||
#include "Geometry.hpp"
|
||||
|
||||
|
||||
//#define PI 3.1415
|
||||
#define DEG 180.0
|
||||
#define to_rad(x) M_PI / DEG * x
|
||||
#define to_deg(x) DEG / M_PI * x
|
||||
//#define DEG 180.0
|
||||
#define to_rad(x) 3.1415f / 180.0f * x
|
||||
#define to_deg(x) 180.0f / 3.1415f * x
|
||||
#define SCALE_AI 128
|
||||
|
||||
|
||||
|
||||
class Plane
|
||||
{
|
||||
public:
|
||||
int id;
|
||||
//Vector3D normal;
|
||||
int normal_x;
|
||||
int normal_y;
|
||||
int normal_z;
|
||||
float distance;
|
||||
};
|
||||
|
||||
class Frustrum
|
||||
{
|
||||
public:
|
||||
Plane sides[5];
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class Camera
|
||||
{
|
||||
public:
|
||||
|
@ -77,6 +99,8 @@ public:
|
|||
|
||||
void turn(float _yaw, float _pitch);
|
||||
|
||||
void setup_frustrum();
|
||||
|
||||
//int min(int a, int b);
|
||||
//int max(int a, int b);
|
||||
|
||||
|
@ -86,6 +110,9 @@ public:
|
|||
float yaw, pitch;
|
||||
|
||||
public:
|
||||
|
||||
Frustrum frustrum;
|
||||
|
||||
int look_at_type;
|
||||
float look_at_yaw;
|
||||
float look_at_pitch;
|
||||
|
@ -98,22 +125,25 @@ public:
|
|||
float cos_pitch, sin_pitch;
|
||||
|
||||
float fov;
|
||||
int cos_fov;
|
||||
//int cos_fov;
|
||||
//int sin_fov;
|
||||
float sin_fov;
|
||||
float cos_fov_square;
|
||||
//float sin_fov;
|
||||
//float cos_fov_square;
|
||||
|
||||
int scale_coef;
|
||||
//float scale_coef2;
|
||||
int near;
|
||||
int far;
|
||||
float near_coef;
|
||||
int far_coef;
|
||||
//float near_coef;
|
||||
//int far_coef;
|
||||
|
||||
float normal_x, normal_y, normal_z;
|
||||
//float normal_x, normal_y, normal_z;
|
||||
|
||||
int a1, a2, a3, a4, a5, a6, a7, a8, a9;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
20
src/game.cpp
20
src/game.cpp
|
@ -1,5 +1,8 @@
|
|||
#include "game.hpp"
|
||||
|
||||
extern Map map_exemple;
|
||||
extern Map map_moulin;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GAME
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -15,19 +18,6 @@ Game::Game()
|
|||
void Game::new_game()
|
||||
{
|
||||
// pour exemple
|
||||
//map = &map_exemple;
|
||||
//map = &map_interieur_forgeron; // ICI LAUNCH GAME
|
||||
player.teleport(0,0,0,0,0);
|
||||
//player.dissociate_camera = true;
|
||||
//scene_map.camera.set(-14,25,5,90,0); // de face
|
||||
//player.teleport(25,-50,0,90,0);
|
||||
//scene_map.camera.set(-14,1,5,-20,0); // de biais
|
||||
|
||||
//map = &map_village;
|
||||
|
||||
//scene_map.load_map();
|
||||
//player.teleport(-85.7, -77.5, 0, 40, 0);
|
||||
//player.teleport(0, -5, 0, 0, 0);
|
||||
//player.teleport(250.7, -110.7, 0, 26.8, 15.4); // bug chevauchement clip depth
|
||||
//player.teleport(250.7, -110.7, 0, 319.6, 53.55);
|
||||
map = &map_moulin;
|
||||
player.teleport(-100,0,player.height,0,10);
|
||||
}
|
||||
|
|
|
@ -71,7 +71,6 @@ public:
|
|||
//Object* get_object(int id);
|
||||
|
||||
//Collision_flag collision(float* new_x, float* new_y, float* new_z);
|
||||
//bool CollisionDroiteSeg(Vecteur wall, Vecteur player);
|
||||
|
||||
|
||||
Map *map;
|
||||
|
|
170
src/main.cpp
170
src/main.cpp
|
@ -1,61 +1,161 @@
|
|||
#include "main.hpp"
|
||||
/*
|
||||
LISTE DES IDEES
|
||||
|
||||
O - objets dynamiques et statics
|
||||
O - gérer la sphere qui chevauche pas pour simplifier le clipping
|
||||
O - rotation n'importe quel axe
|
||||
X - sprite de gint -> pas possible
|
||||
O - compatibilité couleur
|
||||
|
||||
*/
|
||||
|
||||
#include "main.hpp"
|
||||
#include <fxlibc/printf.h>
|
||||
|
||||
Game game;
|
||||
Windmill windmill;
|
||||
Scene_Map scene_map;
|
||||
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
__printf_enable_fp();
|
||||
|
||||
// Ecran principal
|
||||
extern bopti_image_t img_windmill;
|
||||
|
||||
dclear(C_WHITE);
|
||||
dimage(16, 0, &img_windmill);
|
||||
|
||||
int key = 0;
|
||||
|
||||
while(key != KEY_EXE)
|
||||
{
|
||||
dupdate();
|
||||
|
||||
key = getkey().key;
|
||||
}
|
||||
|
||||
dclear(C_BLACK);
|
||||
dprint_opt(64, 40, C_BLACK, C_WHITE, DTEXT_MIDDLE, DTEXT_BOTTOM, "Jour 26");
|
||||
int key = 0;
|
||||
while(key != KEY_EXE)
|
||||
{
|
||||
dupdate();
|
||||
key = getkey().key;
|
||||
}
|
||||
dclear(C_BLACK);
|
||||
dupdate();
|
||||
|
||||
scene_map.launch();
|
||||
|
||||
while(1)
|
||||
{
|
||||
/* (LEPHE) */
|
||||
clearevents();
|
||||
if (keydown(KEY_EXIT))
|
||||
break;
|
||||
if (keydown(KEY_MENU))
|
||||
gint_osmenu();
|
||||
|
||||
scene_map.draw();
|
||||
scene_map.update();
|
||||
}
|
||||
scene_map.terminate();
|
||||
// initialise le moteur de jeu
|
||||
game.new_game();
|
||||
scene_map.launch();
|
||||
int timer = timer_configure(TIMER_ANY, 25*1000, GINT_CALL(callback_tick));
|
||||
timer_start(timer);
|
||||
|
||||
scene_map.update();
|
||||
|
||||
// boucle principale
|
||||
while (1)
|
||||
{
|
||||
clearevents();
|
||||
if (keydown(KEY_EXIT))
|
||||
break;
|
||||
if (keydown(KEY_MENU))
|
||||
gint_osmenu();
|
||||
|
||||
scene_map.draw();
|
||||
}
|
||||
|
||||
timer_stop(timer);
|
||||
scene_map.terminate();
|
||||
|
||||
getkey();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int callback_tick()
|
||||
{
|
||||
scene_map.update();
|
||||
return TIMER_CONTINUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void debug_pop(char const *fmt, ...)
|
||||
{
|
||||
dclear(C_WHITE);
|
||||
static int id = 0;
|
||||
id ++;
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
char str[256];
|
||||
vsnprintf(str, 256, fmt, args);
|
||||
va_end(args);
|
||||
dclear(C_WHITE);
|
||||
|
||||
dtext(1, 1, C_BLACK, str);
|
||||
dupdate();
|
||||
getkey();
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
char str[256];
|
||||
vsnprintf(str, 256, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
char substr[256];
|
||||
|
||||
int line = 0;
|
||||
int i = 0;
|
||||
int subi = 0;
|
||||
while (str[i] != '\0')
|
||||
{
|
||||
substr[subi] = str[i];
|
||||
|
||||
if (str[i] == '\n')
|
||||
{
|
||||
substr[subi] = '\0';
|
||||
dprint(1, 1+9*line, C_BLACK, substr);
|
||||
line ++;
|
||||
subi = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
subi++;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
substr[subi] = '\0';
|
||||
dprint(1, 1+9*line, C_BLACK, substr);
|
||||
dprint_opt(124, 60, C_BLACK, C_WHITE, DTEXT_RIGHT, DTEXT_BOTTOM, "%i", id);
|
||||
|
||||
dupdate();
|
||||
getkey();
|
||||
}
|
||||
|
||||
void debug_display(char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
char str[256];
|
||||
vsnprintf(str, 256, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
char substr[256];
|
||||
|
||||
int line = 0;
|
||||
int i = 0;
|
||||
int subi = 0;
|
||||
while (str[i] != '\0')
|
||||
{
|
||||
substr[subi] = str[i];
|
||||
|
||||
if (str[i] == '\n')
|
||||
{
|
||||
substr[subi] = '\0';
|
||||
dprint(1, 1+9*line, C_BLACK, substr);
|
||||
line ++;
|
||||
subi = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
subi++;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
substr[subi] = '\0';
|
||||
dprint(1, 1+9*line, C_BLACK, substr);
|
||||
|
||||
dupdate();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
#include <gint/display.h>
|
||||
#include <gint/keyboard.h>
|
||||
#include <gint/gint.h>
|
||||
#include <gint/clock.h>
|
||||
#include <gint/timer.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "game.hpp"
|
||||
#include "windmill.hpp"
|
||||
#include "scene_map.hpp"
|
||||
|
||||
|
||||
static int callback_tick();
|
||||
void debug_pop(char const *fmt, ...);
|
1630
src/map.cpp
1630
src/map.cpp
File diff suppressed because it is too large
Load Diff
|
@ -1,18 +1,19 @@
|
|||
#include "scene_map.hpp"
|
||||
|
||||
void debug_pop(char const *fmt, ...);
|
||||
void debug_display(char const *fmt, ...);
|
||||
|
||||
|
||||
extern Game game;
|
||||
extern Windmill windmill;
|
||||
|
||||
// import des map
|
||||
extern Map map_village;
|
||||
extern Map map_interieur_forgeron;
|
||||
extern Map map_exemple;
|
||||
extern Map map_moulin;
|
||||
|
||||
// import des objets
|
||||
extern Object chaumiere1;
|
||||
extern Object panneau1;
|
||||
extern Object forgeron1;
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// CONSTRUCTOR
|
||||
|
@ -20,7 +21,7 @@ extern Object forgeron1;
|
|||
Scene_Map::Scene_Map()
|
||||
{
|
||||
// debug
|
||||
show_repere = false;
|
||||
show_repere = true;
|
||||
show_coordinates = false;
|
||||
// histoire
|
||||
vue_horloge = false;
|
||||
|
@ -35,6 +36,8 @@ Scene_Map::Scene_Map()
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
void Scene_Map::launch()
|
||||
{
|
||||
if (game.map == NULL) return;
|
||||
|
||||
time_scene = 0;
|
||||
|
||||
load_map();
|
||||
|
@ -47,13 +50,11 @@ void Scene_Map::launch()
|
|||
|
||||
void Scene_Map::load_map()
|
||||
{
|
||||
// (LEPHE)
|
||||
game.map = &map_village;
|
||||
|
||||
// mise a jour de la map pour la scene
|
||||
windmill.load_map(game.map);
|
||||
windmill.set_map(game.map);
|
||||
|
||||
// creation des bouding box 3D
|
||||
/*
|
||||
// creation des bouding box 3D pour les collisions
|
||||
//delete bbox;
|
||||
free(bbox);
|
||||
//bbox = new Bbox3D[game.map->list_object_length];
|
||||
|
@ -76,12 +77,12 @@ void Scene_Map::load_map()
|
|||
for (int k=0; k<current_modele->type; k++)
|
||||
{
|
||||
Point point = windmill.get_point(current_modele, k);
|
||||
current_bbox->x1 = min((int)current_bbox->x1, point.x);
|
||||
current_bbox->y1 = min((int)current_bbox->y1, point.y);
|
||||
current_bbox->z1 = min((int)current_bbox->z1, point.z);
|
||||
current_bbox->x2 = max((int)current_bbox->x2, point.x);
|
||||
current_bbox->y2 = max((int)current_bbox->y2, point.y);
|
||||
current_bbox->z2 = max((int)current_bbox->z2, point.z);
|
||||
current_bbox->x1 = min(current_bbox->x1, point.x);
|
||||
current_bbox->y1 = min(current_bbox->y1, point.y);
|
||||
current_bbox->z1 = min(current_bbox->z1, point.z);
|
||||
current_bbox->x2 = max(current_bbox->x2, point.x);
|
||||
current_bbox->y2 = max(current_bbox->y2, point.y);
|
||||
current_bbox->z2 = max(current_bbox->z2, point.z);
|
||||
}
|
||||
}
|
||||
if (current_object->axe == Z_BILLBOARD)
|
||||
|
@ -89,7 +90,7 @@ void Scene_Map::load_map()
|
|||
current_bbox->radius = max(current_bbox->y1, current_bbox->y2);
|
||||
}
|
||||
|
||||
}
|
||||
}*/
|
||||
|
||||
// mise a zero du temps sur la map
|
||||
time_scene = 0;
|
||||
|
@ -101,38 +102,10 @@ void Scene_Map::load_map()
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
void Scene_Map::draw()
|
||||
{
|
||||
//ML_clear_vram();
|
||||
dclear(C_WHITE);
|
||||
|
||||
windmill.draw();
|
||||
|
||||
// MAP VILLAGE
|
||||
if (game.map == &map_village)
|
||||
{
|
||||
if (vue_panneau_moulin)
|
||||
{
|
||||
//ML_rectangle(34, 15, 95, 50, 0, ML_WHITE, ML_WHITE);
|
||||
//PrintXY(34, 20, "MOULIN DES", 0);
|
||||
//PrintXY(52, 30, "RIBES", 0);
|
||||
//PrintMini(45, 45, "NineStars", 0);
|
||||
}
|
||||
}
|
||||
|
||||
// MAP INTERIEUR FORGERON
|
||||
if (game.map == &map_interieur_forgeron)
|
||||
{
|
||||
if (parle_avec_forgeron)
|
||||
{
|
||||
//Point point_ancrage = windmill.get_point(&forgeron1.modele, 0);
|
||||
|
||||
//ML_rectangle(50, 10, 118, 54, 1, ML_BLACK, ML_WHITE);
|
||||
}
|
||||
}
|
||||
|
||||
if (show_repere) windmill.show_repere();
|
||||
if (show_coordinates) windmill.show_coordinates();
|
||||
|
||||
//ML_display_vram();
|
||||
dupdate();
|
||||
}
|
||||
|
||||
|
@ -169,6 +142,11 @@ void Scene_Map::update()
|
|||
show_coordinates = !show_coordinates;
|
||||
}*/
|
||||
|
||||
if (keydown(KEY_LOG))
|
||||
{
|
||||
windmill.log = !windmill.log;
|
||||
}
|
||||
|
||||
// action du joueur sur la map
|
||||
player_action();
|
||||
|
||||
|
@ -186,75 +164,28 @@ void Scene_Map::update()
|
|||
camera.set(game.player.x, game.player.y, game.player.z + game.player.height, game.player.yaw, game.player.pitch);
|
||||
}
|
||||
|
||||
//debug_display(id(windmill.object_cursor), 3);
|
||||
//debug_display(windmill.poly_cursor, 4);
|
||||
}
|
||||
|
||||
|
||||
void Scene_Map::player_action()
|
||||
{
|
||||
// MAP VILLAGE
|
||||
if (game.map == &map_village)
|
||||
{
|
||||
/*if (input_trigger(K_EXE))
|
||||
{
|
||||
if (action_object(object(20)))
|
||||
{
|
||||
|
||||
if (vue_panneau_moulin)
|
||||
{
|
||||
game.player.can_move = true;
|
||||
game.player.dissociate_camera = false;
|
||||
windmill.set_camera(&camera);
|
||||
} else {
|
||||
game.player.can_move = false;
|
||||
game.player.dissociate_camera = true;
|
||||
look(&panneau1, 0, 8, 17, 270, -10);
|
||||
windmill.set_camera(&camera_look);
|
||||
}
|
||||
vue_panneau_moulin = not vue_panneau_moulin;
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
||||
|
||||
// MAP INTERIEUR FORGERON
|
||||
if (game.map == &map_interieur_forgeron)
|
||||
{
|
||||
/*if (input_trigger(K_EXE))
|
||||
{
|
||||
// interaction avec le forgeron
|
||||
if (parle_avec_forgeron)
|
||||
{
|
||||
parle_avec_forgeron = false;
|
||||
game.player.can_move = true;
|
||||
game.player.dissociate_camera = false;
|
||||
} else {
|
||||
if (action_object(&forgeron1))
|
||||
{
|
||||
parle_avec_forgeron = true;
|
||||
game.player.can_move = false;
|
||||
game.player.dissociate_camera = true;
|
||||
camera.set(-23, 4, game.player.height, 198, 0);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Scene_Map::animation()
|
||||
{
|
||||
// MAP VILLAGE
|
||||
if (game.map == &map_village)
|
||||
if (game.map == &map_moulin)
|
||||
{
|
||||
object(6)->angle -= 1;
|
||||
game.map->object[1]->angle += 0.6;
|
||||
game.map->object[2]->angle += 0.6;
|
||||
game.map->object[3]->angle += 0.6;
|
||||
game.map->object[4]->angle += 0.6;
|
||||
game.map->object[5]->angle += 0.6;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Scene_Map::player_move()
|
||||
{
|
||||
///////////// METTRE DANS PLAYER ET RETURN LE FLAG
|
||||
|
@ -263,20 +194,15 @@ void Scene_Map::player_move()
|
|||
float new_z = game.player.z;
|
||||
|
||||
// deplacement
|
||||
float front, side;
|
||||
/* (LEPHE) */
|
||||
// input_move(&front, &side);
|
||||
front = 2 * (keydown(KEY_5) != 0);
|
||||
side = 2 * ((keydown(KEY_6) != 0) - (keydown(KEY_4) != 0));
|
||||
|
||||
// si des touches sont pressees
|
||||
int front = (keydown(KEY_5) != 0) - (keydown(KEY_2) != 0);
|
||||
int side = (keydown(KEY_4) != 0) - (keydown(KEY_6) != 0);
|
||||
if (side != 0 or front != 0)
|
||||
{
|
||||
game.player.moving = true;
|
||||
//game.player.translation_speed = min(game.player.translation_speed + 0.25, game.player.translation_speed_max);
|
||||
// acceleration player
|
||||
if (game.player.translation_speed < game.player.translation_speed_max)
|
||||
{
|
||||
game.player.translation_speed += game.player.translation_acceleration; // acceleration
|
||||
game.player.translation_speed += game.player.translation_acceleration;
|
||||
} else {
|
||||
game.player.translation_speed = game.player.translation_speed_max;
|
||||
}
|
||||
|
@ -291,7 +217,15 @@ void Scene_Map::player_move()
|
|||
game.player.translation_speed = 0;
|
||||
}
|
||||
|
||||
// vole
|
||||
int vertical = (keydown(KEY_PLUS) != 0) - (keydown(KEY_MINUS) != 0);
|
||||
if (vertical != 0)
|
||||
{
|
||||
new_z += vertical;
|
||||
}
|
||||
|
||||
// saut
|
||||
/*
|
||||
if (keydown(KEY_8) and not game.player.jumping)
|
||||
{
|
||||
game.player.jump_speed = game.player.jump_speed_max;
|
||||
|
@ -299,8 +233,9 @@ void Scene_Map::player_move()
|
|||
} else {
|
||||
game.player.jump_speed -= 0.981; // gravite
|
||||
}
|
||||
new_z += game.player.jump_speed;
|
||||
new_z += game.player.jump_speed;*/
|
||||
|
||||
/*
|
||||
// collision
|
||||
flag = collision(&new_x, &new_y, &new_z);
|
||||
|
||||
|
@ -314,8 +249,8 @@ void Scene_Map::player_move()
|
|||
// hors terrain
|
||||
if (flag.type == COLLISION_BOUND)
|
||||
{
|
||||
//debug_display("trop loin", 2);
|
||||
}
|
||||
// trop loin
|
||||
}*/
|
||||
|
||||
game.player.x = new_x;
|
||||
game.player.y = new_y;
|
||||
|
@ -328,10 +263,10 @@ void Scene_Map::player_turn()
|
|||
float yaw = 0;
|
||||
float pitch = 0;
|
||||
|
||||
if (keydown(KEY_RIGHT)) yaw = -1;
|
||||
if (keydown(KEY_LEFT)) yaw = 1;
|
||||
if (keydown(KEY_DOWN)) pitch = -0.5;
|
||||
if (keydown(KEY_UP)) pitch = 0.5;
|
||||
if (keydown(KEY_RIGHT)) yaw = -0.5;
|
||||
if (keydown(KEY_LEFT)) yaw = 0.5;
|
||||
if (keydown(KEY_DOWN)) pitch = -0.25;
|
||||
if (keydown(KEY_UP)) pitch = 0.25;
|
||||
|
||||
if (yaw != 0 or pitch != 0)
|
||||
{
|
||||
|
@ -367,7 +302,7 @@ void Scene_Map::player_turn()
|
|||
// 4 z_billboard
|
||||
// 5 hors terrain
|
||||
//-----------------------------------------------------------------------------
|
||||
Collision_flag Scene_Map::collision(float* new_x, float* new_y, float* new_z)
|
||||
/*Collision_flag Scene_Map::collision(float* new_x, float* new_y, float* new_z)
|
||||
{
|
||||
Collision_flag flag;
|
||||
|
||||
|
@ -383,7 +318,7 @@ Collision_flag Scene_Map::collision(float* new_x, float* new_y, float* new_z)
|
|||
flag.type = COLLISION_GROUND;
|
||||
}
|
||||
|
||||
for (int i = 0; i<game.map->list_object_length; i++)
|
||||
for (int i = 0; i<game.map->object_length; i++)
|
||||
{
|
||||
Object* current_object = game.map->object[i];
|
||||
|
||||
|
@ -536,7 +471,9 @@ Collision_flag Scene_Map::collision(float* new_x, float* new_y, float* new_z)
|
|||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
/*Collision_flag Scene_Map::collision(float* new_x, float* new_y, float* new_z)
|
||||
{
|
||||
Collision_flag flag;
|
||||
|
@ -711,7 +648,7 @@ Collision_flag Scene_Map::collision(float* new_x, float* new_y, float* new_z)
|
|||
return flag;
|
||||
}*/
|
||||
|
||||
|
||||
/*
|
||||
void Scene_Map::look(Object* object, float x, float y, float z, float yaw, float pitch)
|
||||
{
|
||||
Vertex vertex;
|
||||
|
@ -762,9 +699,9 @@ int Scene_Map::id(Object* object)
|
|||
}
|
||||
debug_pop("ERROR object not found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
}*/
|
||||
|
||||
/*
|
||||
bool Scene_Map::action_object(Object* object, int poly_id)
|
||||
{
|
||||
if (look_object(object, poly_id) == false) return false;
|
||||
|
@ -804,7 +741,7 @@ bool Scene_Map::look_object(Object* object, int poly_id)
|
|||
return (object == windmill.object_cursor and poly_id == windmill.poly_cursor);
|
||||
}
|
||||
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
@ -821,36 +758,3 @@ Scene_Map::~Scene_Map()
|
|||
{
|
||||
// rien
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
1790
src/windmill.cpp
1790
src/windmill.cpp
File diff suppressed because it is too large
Load Diff
218
src/windmill.hpp
218
src/windmill.hpp
|
@ -7,22 +7,32 @@
|
|||
#include <stdlib.h>
|
||||
#include <gint/defs/util.h>
|
||||
#include "camera.hpp"
|
||||
#include "Geometry.hpp"
|
||||
#include <stdio.h>
|
||||
|
||||
#define get_vram_address() ((char *)gint_vram)
|
||||
|
||||
// parametrage de Windmill
|
||||
#define MIN_AREA_CLIP 5
|
||||
#define DECORATION_OFFSET 50
|
||||
#define MAX_DEPTH_Z_BUFFER 0xffff
|
||||
|
||||
enum {N, X, Y, Z, Z_BILLBOARD};
|
||||
enum {N, RX, RY, RZ, Z_BILLBOARD};
|
||||
//#define N {0, 0, 0}
|
||||
//#define RX {1, 0, 0}
|
||||
//#define RY {0, 1, 0}
|
||||
//#define RZ {0, 0, 1}
|
||||
|
||||
#define LB {0, 1}
|
||||
#define RB {1, 1}
|
||||
#define LT {0, 0}
|
||||
#define RT {1, 0}
|
||||
#define MB {0.5, 1}
|
||||
#define MT {0.5, 0}
|
||||
#define LM {0, 0.5}
|
||||
#define RM {1, 0.5}
|
||||
|
||||
#define FRONT 1
|
||||
#define BACK -1
|
||||
#define RIEN 0
|
||||
#define TRIANGLE 3
|
||||
#define RECTANGLE 4
|
||||
#define PARA 0
|
||||
#define TRAP 1
|
||||
|
||||
#define INTERIEUR true
|
||||
#define EXTERIEUR false
|
||||
|
@ -37,36 +47,22 @@ enum {N, X, Y, Z, Z_BILLBOARD};
|
|||
|
||||
|
||||
// definition des structures
|
||||
struct Point
|
||||
{
|
||||
int x, y, z;
|
||||
};
|
||||
|
||||
class Vecteur
|
||||
{
|
||||
public:
|
||||
float x1, y1, x2, y2;
|
||||
};
|
||||
|
||||
struct Sphere
|
||||
{
|
||||
int x, y, z;
|
||||
int radius;
|
||||
int x, y, z;
|
||||
int radius;
|
||||
int square_radius;
|
||||
};
|
||||
|
||||
class Vertex
|
||||
struct VertexPoint
|
||||
{
|
||||
public:
|
||||
int x, y, z;
|
||||
float w, h;
|
||||
unsigned short z_normalized;
|
||||
|
||||
Vertex();
|
||||
void set_xyz(int _x, int _y, int _z);
|
||||
void set_wh(float _w, float _h);
|
||||
float length(int x, int y, int z);
|
||||
int x, y, z;
|
||||
};
|
||||
|
||||
struct TexturePoint
|
||||
{
|
||||
float u, v;
|
||||
};
|
||||
|
||||
struct Texture
|
||||
{
|
||||
|
@ -74,49 +70,85 @@ struct Texture
|
|||
const unsigned char* mask;
|
||||
const char pixel_width;
|
||||
const char pixel_height;
|
||||
const char real_width;
|
||||
const char real_height;
|
||||
const float offset;
|
||||
const bool transparent;
|
||||
const bool decoration;
|
||||
const bool mirror;
|
||||
const int real_height;
|
||||
const int real_width;
|
||||
};
|
||||
|
||||
|
||||
struct Modele
|
||||
struct Face
|
||||
{
|
||||
const int type;
|
||||
const Texture* texture_front;
|
||||
const Texture* texture_back;
|
||||
const short x0, y0, z0;
|
||||
const short x1, y1, z1;
|
||||
const short x2, y2, z2;
|
||||
const char option;
|
||||
unsigned char v[3];
|
||||
unsigned char t[3];
|
||||
bool visible = true;
|
||||
};
|
||||
|
||||
class Vertex
|
||||
{
|
||||
public:
|
||||
int x, y, z;
|
||||
float u, v;
|
||||
int inv_z;
|
||||
unsigned short z_normalized;
|
||||
|
||||
Vertex();
|
||||
Vertex(int _x, int _y, int _z);
|
||||
Vertex(int _x, int _y, int _z, float _u, float _v);
|
||||
void set_texture(TexturePoint t);
|
||||
void set_xyz(int _x, int _y, int _z);
|
||||
};
|
||||
|
||||
struct Mesh
|
||||
{
|
||||
const VertexPoint* v;
|
||||
const int v_length;
|
||||
const TexturePoint* t;
|
||||
const int t_length;
|
||||
const Face* f;
|
||||
const int f_length;
|
||||
};
|
||||
|
||||
class WMesh
|
||||
{
|
||||
public:
|
||||
Vertex* v;
|
||||
int v_length;
|
||||
int v_length_allocated;
|
||||
TexturePoint* t;
|
||||
int t_length;
|
||||
int t_length_allocated;
|
||||
Face* f;
|
||||
int f_length;
|
||||
int f_length_allocated;
|
||||
|
||||
void from_mesh(const Mesh* mesh, int margin);
|
||||
void free_memory();
|
||||
void add_vertex(Vertex vertex);
|
||||
};
|
||||
|
||||
struct Object
|
||||
{
|
||||
short x, y, z;
|
||||
// bool static = STATIC / DYNAMIC -> transform_model_to_world au chargement
|
||||
const Mesh* mesh;
|
||||
Point3D position;
|
||||
//Vector3D rotation;
|
||||
//short x, y, z;
|
||||
char axe;
|
||||
float angle;
|
||||
const Modele* modele;
|
||||
const int modele_size;
|
||||
// ajouter ici
|
||||
const char collision;
|
||||
//const char for_collision;
|
||||
//const char type_collision;
|
||||
bool hidden;
|
||||
bool on_screen;
|
||||
Sphere sphere;
|
||||
int distance_to_camera;
|
||||
};
|
||||
//Vector3D rotation;
|
||||
|
||||
char collision = ALL;
|
||||
bool visible = true;
|
||||
|
||||
Sphere sphere;
|
||||
WMesh* shadow;
|
||||
//bool on_screen;
|
||||
};
|
||||
|
||||
struct Map
|
||||
{
|
||||
Object** object;
|
||||
int list_object_length;
|
||||
int object_length;
|
||||
bool horizon;
|
||||
bool ground;
|
||||
// ajouter ici
|
||||
|
@ -128,65 +160,50 @@ struct Viewport
|
|||
};
|
||||
|
||||
|
||||
float distance(float dx, float dy, float dz);
|
||||
int compare_object(void const *a, void const *b);
|
||||
|
||||
|
||||
class Windmill
|
||||
{
|
||||
public:
|
||||
// initialisation et parametrage
|
||||
// initialisation, parametrage et pre calcul
|
||||
Windmill();
|
||||
void set_camera(Camera* _camera);
|
||||
void set_viewport(int viewport_x1, int viewport_y1, int viewport_x2, int viewport_y2);
|
||||
void load_map(Map* _map);
|
||||
void set_map(Map* _map);
|
||||
void set_objects();
|
||||
void compute_bouding_sphere();
|
||||
void compute_shadows();
|
||||
void compute_shadows_hull(Point3D* points, int points_size);
|
||||
int compute_shadows_hull_orientation(Point3D a, Point3D b, Point3D c);
|
||||
|
||||
// dessin
|
||||
void draw();
|
||||
void draw_horizon();
|
||||
void draw_shadows();
|
||||
void draw_ground();
|
||||
void draw_objects();
|
||||
void draw_post_treatment();
|
||||
void draw_body();
|
||||
|
||||
// transformation 3D des vertex
|
||||
void transform_model_to_world(Vertex vertex[], int vertex_length, Object* object, int cosinus, int sinus);
|
||||
void transform_model_to_world(Object* object, Vertex vertex[], int vertex_length);
|
||||
void transform_world_to_camera(Vertex vertex[], int vertex_length);
|
||||
void transform_camera_to_screen(Vertex vertex[], int vertex_length);
|
||||
void transform_camera_to_screen2(Vertex vertex[], int vertex_length);
|
||||
|
||||
// text visiblilite
|
||||
bool fast_check(Vertex vertex_list[], int vertex_list_length);
|
||||
// test visiblilite
|
||||
bool object_in_frustrum(Object* object);
|
||||
void clip_frustrum(WMesh* mesh);
|
||||
bool inside_frustrum(Vertex vertex, Plane plane, int offset = 0);
|
||||
Vertex clip_plane(Vertex vertex[], int vertex_length);
|
||||
Vertex clip_onto_plane(Vertex vertexA, Vertex vertexB, Plane plane);
|
||||
bool inside_viewport(int x, int y);
|
||||
int visible_face(Vertex* a, Vertex* b, Vertex* c);
|
||||
|
||||
void clip_depth(Vertex vertex_list_input[], int* vertex_list_input_length);
|
||||
void clip_depth_edge(Vertex* vertex_in, Vertex* vertex_out, Vertex* vertex_set);
|
||||
bool clip_depth_inside_edge(Vertex* vertex);
|
||||
|
||||
void clip_viewport(Vertex vertex_list_input[], int* vertex_list_input_length);
|
||||
void clip_viewport_edge(Vertex* vertex_in, Vertex* vertex_out, Vertex* vertex_set, int edge);
|
||||
bool clip_viewport_inside_edge(Vertex* vertex, int edge);
|
||||
int get_visible_face(Vertex* a, Vertex* b, Vertex* c);
|
||||
|
||||
// dessin des triangles
|
||||
void render_triangle(Vertex* vertex1, Vertex* vertex2, Vertex* vertex3, const Texture *texture);
|
||||
void render_triangles(WMesh mesh);
|
||||
void render_triangle_texture(Vertex* vertex1, Vertex* vertex2, Vertex* vertex3, const Texture* texture);
|
||||
void render_triangle_black(Vertex* vertex0, Vertex* vertex1, Vertex* vertex2);
|
||||
void render_triangle_white(Vertex* vertex0, Vertex* vertex1, Vertex* vertex2);
|
||||
void render_triangle_transparent(Vertex* vertex1, Vertex* vertex2, Vertex* vertex3, const Texture* texture);
|
||||
|
||||
// manipulation
|
||||
Point get_point(const Modele* poly, int i);
|
||||
Point get_center_poly(const Modele* poly);
|
||||
void compute_object_angle(Object* object, int* cosinus, int* sinus);
|
||||
void extract_vertex_from_poly(const Modele* poly, Vertex* vertex, int* vertex_length, int* width, int* height);
|
||||
void texture_coordinates(const Modele* poly, Vertex* vertex, const Texture* texture, int visible, int width, int height);
|
||||
void swap_vertex(Vertex* vertexA, Vertex* vertexB);
|
||||
void copy_vertex(Vertex* vertex_source, Vertex* vertex_dest);
|
||||
|
||||
// sphere
|
||||
Sphere transform_sphere_to_world(Sphere* sphere, Object* object, int cosinus, int sinus);
|
||||
bool sphere_in_cone(Sphere* sphere);
|
||||
void render_triangle_color(Vertex* vertex0, Vertex* vertex1, Vertex* vertex2, color_t color);
|
||||
|
||||
// divers
|
||||
void copy_camera();
|
||||
|
@ -196,14 +213,13 @@ public:
|
|||
int edge_start(Vertex* a, Vertex* b, int px, int py);
|
||||
int edge_step_x(Vertex* a, Vertex* b);
|
||||
int edge_step_y(Vertex* a, Vertex* b);
|
||||
float distance(float dx, float dy, float dz);
|
||||
|
||||
// utilitaires
|
||||
void pixel_on_cursor(int x, int y);
|
||||
void show_coordinates();
|
||||
void show_repere();
|
||||
//void show_fps();
|
||||
|
||||
// destructeurr
|
||||
// destructeur
|
||||
~Windmill();
|
||||
|
||||
private:
|
||||
|
@ -215,8 +231,10 @@ private:
|
|||
Map* map;
|
||||
|
||||
// liste objets triee
|
||||
Object** object;
|
||||
int list_object_length;
|
||||
Object* objects;
|
||||
|
||||
// ombres
|
||||
Point3D sun;
|
||||
|
||||
// z_buffer
|
||||
int shift_x, shift_y;
|
||||
|
@ -229,22 +247,14 @@ private:
|
|||
int i;
|
||||
int j;
|
||||
|
||||
// variables temporaire pour eviter de lire la valeur en cours de calcul
|
||||
int temp_nb_object_on_screen;
|
||||
Object* temp_object_cursor;
|
||||
int temp_poly_cursor;
|
||||
|
||||
public:
|
||||
// fenetre de visualisation
|
||||
Viewport viewport;
|
||||
|
||||
// utilitaires
|
||||
bool loading;
|
||||
int nb_object_on_screen;
|
||||
Object* object_cursor;
|
||||
int poly_cursor;
|
||||
int cursor_x;
|
||||
int cursor_y;
|
||||
|
||||
bool log = false;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,283 @@
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// WINDMILL
|
||||
//
|
||||
// version : 2.0
|
||||
// Moteur de rendu 3D base sur la methode de rasterisation avec buffer de profondeur
|
||||
//
|
||||
// Cree par Olivier Lanneau, alias NineStars
|
||||
// Planet-casio.fr
|
||||
//
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "windmill.hpp"
|
||||
|
||||
void debug_pop(char const *fmt, ...);
|
||||
void debug_display(char const *fmt, ...);
|
||||
|
||||
extern Texture tex_white;
|
||||
extern Texture tex_light;
|
||||
extern Texture tex_dark;
|
||||
extern Texture tex_black;
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// CLIPPING
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool Windmill::object_in_frustrum(Object* object)
|
||||
{
|
||||
Vertex centre(object->sphere.x, object->sphere.y, object->sphere.z);
|
||||
// calcul des coordonnees dans le repère monde apres rotation et translation du centre de l objet
|
||||
transform_model_to_world(object, ¢re, 1);
|
||||
|
||||
// calcul des coordonnees du centre dans le repère camera apres rotation et translation de la camera
|
||||
transform_world_to_camera(¢re, 1);
|
||||
|
||||
// si la camera est dans la sphere
|
||||
if (centre.x*centre.x + centre.y*centre.y + centre.z*centre.z < object->sphere.square_radius)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// si la sphere est dans le frustrum
|
||||
for (int p = 0; p<5 ; p++)
|
||||
{
|
||||
Plane plane = camera.frustrum.sides[p];
|
||||
|
||||
if (inside_frustrum(centre, plane, object->sphere.radius) == false) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
// A GARDER CAR PAS MAL OPTI
|
||||
/*
|
||||
int cone_offset = sphere->radius * camera.sin_fov;
|
||||
|
||||
int nx = camera.nx;
|
||||
int ny = camera.ny;
|
||||
int nz = camera.nz;
|
||||
|
||||
Point3D cone;
|
||||
cone.x = int(camera.x) - (nx * cone_offset);
|
||||
cone.y = int(camera.y) - (ny * cone_offset);
|
||||
cone.z = int(camera.z) - (nz * cone_offset);
|
||||
|
||||
int sx = sphere->x - cone.x;
|
||||
int sy = sphere->y - cone.y;
|
||||
int sz = sphere->z - cone.z;
|
||||
int ss = sx*sx + sy*sy + sz*sz;
|
||||
|
||||
// si sommet du cone dans la sphere
|
||||
if (ss <= sphere->radius * sphere->radius)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// si sphere dans le cone
|
||||
int ns = ((nx * sx) >> 7) + ((ny * sy) >> 7) + ((nz * sz) >> 7);
|
||||
|
||||
if (ns > 0 and ns*ns > camera.cos_fov_square * ss)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;*/
|
||||
}
|
||||
|
||||
void Windmill::clip_frustrum(WMesh* mesh)
|
||||
{
|
||||
for (int p = 0; p<5 ; p++)
|
||||
{
|
||||
Plane plane = camera.frustrum.sides[p];
|
||||
|
||||
int init_f_length = mesh->f_length; // car sinon on va faire du clipping sur des points nouveaux issues du clipping...
|
||||
|
||||
// pour chaque triangle
|
||||
for (int f=0; f<init_f_length; f++)
|
||||
{
|
||||
// triangle en cours
|
||||
Face triangle = mesh->f[f];
|
||||
|
||||
if (triangle.visible)
|
||||
{
|
||||
int S = 3 - 1;
|
||||
|
||||
// indice vertex pour face
|
||||
int v_ok[4];
|
||||
int t_ok[4];
|
||||
int ok_indice = 0;
|
||||
|
||||
// pour chaque segment
|
||||
for (int E = 0; E<3; E++)
|
||||
{
|
||||
Vertex vertexE(mesh->v[triangle.v[E]].x, mesh->v[triangle.v[E]].y, mesh->v[triangle.v[E]].z, mesh->t[triangle.t[E]].u,mesh->t[triangle.t[E]].v);
|
||||
Vertex vertexS(mesh->v[triangle.v[S]].x, mesh->v[triangle.v[S]].y, mesh->v[triangle.v[S]].z, mesh->t[triangle.t[S]].u,mesh->t[triangle.t[S]].v);
|
||||
|
||||
if (inside_frustrum(vertexE, plane) == true)
|
||||
{
|
||||
if (inside_frustrum(vertexS, plane) == false)
|
||||
{
|
||||
v_ok[ok_indice] = mesh->v_length;
|
||||
t_ok[ok_indice] = mesh->t_length;
|
||||
ok_indice++;
|
||||
|
||||
mesh->add_vertex(clip_onto_plane(vertexE, vertexS, plane));
|
||||
}
|
||||
|
||||
v_ok[ok_indice] = triangle.v[E];
|
||||
t_ok[ok_indice] = triangle.t[E];
|
||||
ok_indice++;
|
||||
}
|
||||
else if (inside_frustrum(vertexS, plane) == true)
|
||||
{
|
||||
v_ok[ok_indice] = mesh->v_length;
|
||||
t_ok[ok_indice] = mesh->t_length;
|
||||
ok_indice++;
|
||||
|
||||
mesh->add_vertex(clip_onto_plane(vertexE, vertexS, plane));
|
||||
}
|
||||
|
||||
S = E;
|
||||
}
|
||||
|
||||
// aucun point dans le frustrum
|
||||
if (ok_indice == 0)
|
||||
{
|
||||
mesh->f[f].visible = false;
|
||||
}
|
||||
|
||||
// soit les 3 points à l'intérieur du triangle, soit 2 point ouside -> on modifie la face en cours
|
||||
if (ok_indice >= 3)
|
||||
{
|
||||
Face edited_triangle;
|
||||
edited_triangle.texture_front = triangle.texture_front;
|
||||
edited_triangle.texture_back = triangle.texture_back;
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
edited_triangle.v[i] = v_ok[i];
|
||||
edited_triangle.t[i] = t_ok[i];
|
||||
}
|
||||
mesh->f[f] = edited_triangle; // pas de verif d'overflow
|
||||
}
|
||||
|
||||
// 1 point en dehors = 2 triangles -> on modifie face en cours, et on ajoute une face
|
||||
if (ok_indice == 4)
|
||||
{
|
||||
// ajout triangle
|
||||
Face new_triangle;
|
||||
new_triangle.texture_front = triangle.texture_front;
|
||||
new_triangle.texture_back = triangle.texture_back;
|
||||
new_triangle.v[0] = v_ok[0];
|
||||
new_triangle.t[0] = t_ok[0];
|
||||
new_triangle.v[1] = v_ok[2];
|
||||
new_triangle.t[1] = t_ok[2];
|
||||
new_triangle.v[2] = v_ok[3];
|
||||
new_triangle.t[2] = t_ok[3];
|
||||
|
||||
mesh->f[mesh->f_length] = new_triangle; // pas de verif d'overflow
|
||||
mesh->f_length++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*debug_pop("FIN CYCLE\nplan %i\nil y a %i triangles\nil y a %i vertex", p, mesh->f_length, mesh->v_length);
|
||||
for (int i=0; i<mesh->f_length; i++)
|
||||
{
|
||||
debug_pop("f %i %i %i", mesh->f[i].v[0], mesh->f[i].v[1], mesh->f[i].v[2]);
|
||||
}
|
||||
for (int i=0; i<mesh->v_length; i++)
|
||||
{
|
||||
debug_pop("v\nx %i\ny %i\nz %i", mesh->v[i].x, mesh->v[i].y, mesh->v[i].z);
|
||||
}*/
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Windmill::inside_frustrum(Vertex vertex, Plane plane, int offset)
|
||||
{
|
||||
/*if (plane.id == NEAR)
|
||||
{
|
||||
return vertex.z > camera.near;
|
||||
}
|
||||
if (plane.id == RIGHT)
|
||||
{
|
||||
return vertex.x * camera.scale_coef2 < vertex.z; // MULT float !
|
||||
}
|
||||
if (plane.id == TOP)
|
||||
{
|
||||
return -vertex.y * camera.scale_coef2 / 2.0 < vertex.z;
|
||||
}
|
||||
if (plane.id == LEFT)
|
||||
{
|
||||
return -vertex.x * camera.scale_coef2 < vertex.z;
|
||||
}
|
||||
if (plane.id == BOTTOM)
|
||||
{
|
||||
return vertex.y * camera.scale_coef2 / 2.0 < vertex.z;
|
||||
}*/
|
||||
|
||||
int dot = vertex.x * plane.normal_x + vertex.y * plane.normal_y + vertex.z * plane.normal_z - plane.distance+ (offset * 1000);
|
||||
return dot > 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Vertex Windmill::clip_onto_plane(Vertex vertexA, Vertex vertexB, Plane plane)
|
||||
{/*
|
||||
int x, y, z, u, v;
|
||||
float t;
|
||||
|
||||
if (plane == NEAR)
|
||||
{
|
||||
t = float(camera.near - vertexA->z) / float(vertexB->z - vertexA->z);
|
||||
//x = vertexA->x + t * (vertexB->x - vertexA->x);
|
||||
//y = vertexA->y + t * (vertexB->y - vertexA->y);
|
||||
//z = camera.near;
|
||||
}
|
||||
|
||||
if (plane == RIGHT)
|
||||
{
|
||||
t = float(camera.near - vertexA->z) / float(vertexB->z - vertexA->z);
|
||||
}
|
||||
|
||||
x = vertexA->x + t * (vertexB->x - vertexA->x);
|
||||
y = vertexA->y + t * (vertexB->y - vertexA->y);
|
||||
z = vertexA->z + t * (vertexB->z - vertexA->z);
|
||||
u = vertexA->u + t * (vertexB->u - vertexA->u);
|
||||
v = vertexA->v + t * (vertexB->v - vertexA->v);
|
||||
|
||||
return Vertex(x, y, z, u, v);*/
|
||||
|
||||
//return Vertex(0, 0, 0, 0, 0);
|
||||
|
||||
float dotA = vertexA.x * plane.normal_x + vertexA.y * plane.normal_y + vertexA.z * plane.normal_z - plane.distance;
|
||||
float dotB = vertexB.x * plane.normal_x + vertexB.y * plane.normal_y + vertexB.z * plane.normal_z - plane.distance;
|
||||
|
||||
float t = dotA / (dotA - dotB); // intersection factor (between 0 and 1)
|
||||
|
||||
|
||||
int x = vertexA.x + t * (vertexB.x - vertexA.x);
|
||||
int y = vertexA.y + t * (vertexB.y - vertexA.y);
|
||||
int z = vertexA.z + t * (vertexB.z - vertexA.z);
|
||||
float u = vertexA.u + t * (vertexB.u - vertexA.u);
|
||||
float v = vertexA.v + t * (vertexB.v - vertexA.v);
|
||||
|
||||
return Vertex(x, y, z, u, v);
|
||||
}
|
||||
|
||||
|
||||
bool Windmill::inside_viewport(int x, int y)
|
||||
{
|
||||
return (x < viewport.x2 and y >= viewport.y1 and x >= viewport.x1 and y < viewport.y2);
|
||||
}
|
||||
|
||||
int Windmill::get_visible_face(Vertex* a, Vertex* b, Vertex* c)
|
||||
{
|
||||
return (c->x - a->x) * (b->y - a->y) - (c->y - a->y) * (b->x - a->x) > 0 ? FRONT : BACK;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,946 @@
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// WINDMILL
|
||||
//
|
||||
// version : 2.0
|
||||
// Moteur de rendu 3D base sur la methode de rasterisation avec buffer de profondeur
|
||||
//
|
||||
// Cree par Olivier Lanneau, alias NineStars
|
||||
// Planet-casio.fr
|
||||
//
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "windmill.hpp"
|
||||
|
||||
void debug_pop(char const *fmt, ...);
|
||||
void debug_display(char const *fmt, ...);
|
||||
|
||||
extern Texture tex_white;
|
||||
extern Texture tex_light;
|
||||
extern Texture tex_dark;
|
||||
extern Texture tex_black;
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// DESSIN
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void Windmill::draw()
|
||||
{
|
||||
// quitte si pas de camera, de map, d objet ou de z_buffer
|
||||
if(camera2 == NULL or map == NULL or/* object == NULL or */z_buffer == NULL) return;
|
||||
|
||||
// mets a jour les variables de la camera
|
||||
camera2->update();
|
||||
|
||||
// cree une camera temporaire pour eviter les problemes de desynchronisation
|
||||
copy_camera();
|
||||
|
||||
// fonction principale, l'ordre d'appel des fonctions suivantes est important
|
||||
clear_z_buffer();
|
||||
|
||||
// trie les objets pour optimiser l affichage
|
||||
sort_object();
|
||||
|
||||
// affiche le trait d'horizon
|
||||
if (map->horizon) draw_horizon();
|
||||
|
||||
// affiche les ombres
|
||||
// draw_shadows();
|
||||
|
||||
// affiche le sol
|
||||
if (map->ground) draw_ground();
|
||||
|
||||
// affiche les objets de la scene
|
||||
draw_objects();
|
||||
|
||||
// post traitement pour afficher les angles vifs
|
||||
// draw_post_treatment();
|
||||
|
||||
// affiche le corps du personnage
|
||||
//draw_body();
|
||||
|
||||
// affiche des informations debug
|
||||
if (log)
|
||||
{
|
||||
//show_fps();
|
||||
//show_coordinates();
|
||||
show_repere();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Windmill::draw_horizon()
|
||||
{
|
||||
int distance = 1000;
|
||||
int hx = camera.x + distance * camera.cos_yaw;
|
||||
int hy = camera.y + distance * camera.sin_yaw;
|
||||
|
||||
Vertex horizon = Vertex(hx, hy, 0);
|
||||
|
||||
transform_world_to_camera(&horizon, 1);
|
||||
transform_camera_to_screen(&horizon, 1);
|
||||
if (inside_viewport(horizon.x, horizon.y))
|
||||
{
|
||||
dline(viewport.x1, horizon.y, viewport.x2, horizon.y, C_BLACK);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Windmill::draw_ground()
|
||||
{
|
||||
int distance = 50;
|
||||
int esp = 20;
|
||||
int nb = 6;
|
||||
int nb2 = nb * nb;
|
||||
float cx = camera.x + distance * camera.cos_yaw;
|
||||
float cy = camera.y + distance * camera.sin_yaw;
|
||||
int dx = int(cx) - int(cx)%esp;
|
||||
int dy = int(cy) - int(cy)%esp;
|
||||
|
||||
for (int i=-nb; i<nb; i++)
|
||||
{
|
||||
for (int j=-nb; j<nb; j++)
|
||||
{
|
||||
if (i*i + j*j < nb2) // arrondi le carre en cercle
|
||||
{
|
||||
int x = dx + i*esp;
|
||||
int y = dy + j*esp;
|
||||
|
||||
Vertex ground = Vertex(x, y, 0);
|
||||
transform_world_to_camera(&ground, 1);
|
||||
if (ground.z > 0)
|
||||
{
|
||||
transform_camera_to_screen(&ground, 1);
|
||||
if (inside_viewport(ground.x, ground.y) == true)
|
||||
{
|
||||
dpixel(ground.x, ground.y, C_BLACK);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Windmill::draw_objects()
|
||||
{
|
||||
for(i=0; i<map->object_length; i++)
|
||||
{
|
||||
// récupère l'objet en cours
|
||||
Object* object = map->object[i];
|
||||
//Object* object = objects[i];
|
||||
|
||||
//int f_visible = 0;
|
||||
|
||||
// si l'objet est totalement ou partie dans le frustrum
|
||||
if (object-> visible && object_in_frustrum(object))
|
||||
{
|
||||
// copie le mesh avec plus de memoires disponible pour possiblement ajouter des points au clipping
|
||||
WMesh mesh; mesh.from_mesh(object->mesh, 10);
|
||||
|
||||
// calcul des coordonnees dans le repère monde apres rotation et translation de l objet
|
||||
transform_model_to_world(object, mesh.v, mesh.v_length);
|
||||
|
||||
// calcul des coordonnees dans le repère camera apres rotation et translation de la camera
|
||||
transform_world_to_camera(mesh.v, mesh.v_length);
|
||||
|
||||
// coupe 3D selon le frustrum de la camera
|
||||
clip_frustrum(&mesh); // SI OBJECT IN FRUSTRUM DIT QUE L'OBJET EST PARTEILLEMENT DANS FRUSTRUM
|
||||
|
||||
// calcul des coordonnes apres perspective et decalage au centre de l ecran
|
||||
transform_camera_to_screen(mesh.v, mesh.v_length);
|
||||
|
||||
if (log)
|
||||
{
|
||||
for (int v = 0; v<mesh.v_length; v++)
|
||||
{
|
||||
dpixel(mesh.v[v].x, mesh.v[v].y, C_BLACK);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// dessine tous les triangles
|
||||
render_triangles(mesh);
|
||||
}
|
||||
|
||||
/*if (log)
|
||||
{
|
||||
debug_pop("LOG MODE\nf_length = %i", mesh.f_length);
|
||||
for (int i=0; i<mesh.f_length; i++)
|
||||
{
|
||||
debug_pop("f%i\n%i %i %i\n%i %i %i", i, mesh.f[i].v[0], mesh.f[i].v[1], mesh.f[i].v[2], mesh.f[i].t[0], mesh.f[i].t[1],mesh.f[i].t[2]);
|
||||
}
|
||||
debug_pop("LOG MODE\nv_length = %i", mesh.v_length);
|
||||
for (int i=0; i<mesh.v_length; i++)
|
||||
{
|
||||
debug_pop("v%i\nx %i\ny %i\nz %i", i, mesh.v[i].x, mesh.v[i].y, mesh.v[i].z);
|
||||
}
|
||||
debug_pop("LOG MODE\nt_length = %i", mesh.t_length);
|
||||
for (int i=0; i<mesh.t_length; i++)
|
||||
{
|
||||
debug_pop("t%i\nu %f\nv %f", i, mesh.t[i].u, mesh.t[i].v);
|
||||
}
|
||||
|
||||
log = false;
|
||||
}*/
|
||||
|
||||
mesh.free_memory();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Windmill::draw_post_treatment()
|
||||
{
|
||||
char* vram = get_vram_address();
|
||||
unsigned char mask;
|
||||
int current, right, bottom;
|
||||
|
||||
for (int y = viewport.y1; y<viewport.y2-1; y++)
|
||||
{
|
||||
for (int x = viewport.x1; x<viewport.x2-1; x++)
|
||||
{
|
||||
int address = x + y * z_buffer_width + z_buffer_offset;
|
||||
current = z_buffer[address];
|
||||
right = z_buffer[address + 1];
|
||||
bottom = z_buffer[address + z_buffer_width];
|
||||
if (current == MAX_DEPTH_Z_BUFFER)
|
||||
{
|
||||
if (right < MAX_DEPTH_Z_BUFFER)
|
||||
{
|
||||
mask = 128 >> ((x+1) & 7);
|
||||
vram[address>>3] |= mask;
|
||||
|
||||
//ML_pixel(x+1, y, ML_BLACK);
|
||||
}
|
||||
if (bottom < MAX_DEPTH_Z_BUFFER)
|
||||
{
|
||||
dpixel(x, y+1, C_BLACK);
|
||||
//ML_pixel(x, y+1, ML_BLACK);
|
||||
}
|
||||
} else {
|
||||
if (right == MAX_DEPTH_Z_BUFFER or bottom == MAX_DEPTH_Z_BUFFER)
|
||||
{
|
||||
dpixel(x, y+1, C_BLACK);
|
||||
//ML_pixel(x, y, ML_BLACK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // 21 fps 21,5 fps*/
|
||||
|
||||
/*left = z_buffer[0];
|
||||
for (int i = 1; i<z_buffer_size; i++)
|
||||
{
|
||||
left = current;
|
||||
current = z_buffer[i];
|
||||
//bottom = z_buffer[i+128];
|
||||
if (current < MAX_DEPTH_Z_BUFFER)
|
||||
{
|
||||
//left = z_buffer[i-1];
|
||||
if (left == MAX_DEPTH_Z_BUFFER)
|
||||
{
|
||||
//ML_pixel((i+1)%128, (i+1)/128, ML_BLACK);
|
||||
mask = 128 >> (i & 7);
|
||||
vram[(i - z_buffer_offset)>>3] |= mask;
|
||||
}
|
||||
} else {
|
||||
if (left < MAX_DEPTH_Z_BUFFER)
|
||||
{
|
||||
mask = 128 >> ((i-1) & 7);
|
||||
vram[(i - 1 - z_buffer_offset)>>3] |= mask;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
// sans rien 28 fps
|
||||
// avec le i+1 : 24 fps
|
||||
// avec le i : 25 fps
|
||||
// calculer left = Z_buffer[i-1] dans if : 24 fps
|
||||
// avec les deux cote : 24 fps ! */
|
||||
|
||||
bool flag = false;
|
||||
for (int i = 0; i<z_buffer_size; i+=2)
|
||||
{
|
||||
current = z_buffer[i];
|
||||
if (current == MAX_DEPTH_Z_BUFFER)
|
||||
{
|
||||
if (flag == true)
|
||||
{
|
||||
if (z_buffer[i-1] == MAX_DEPTH_Z_BUFFER)
|
||||
{
|
||||
// il y avait rien juste a gauche
|
||||
mask = 128 >> ((i-2) & 7);
|
||||
vram[(i - 2 - z_buffer_offset)>>3] |= mask;
|
||||
flag = false;
|
||||
} else {
|
||||
// l objet commencait en fait 1 pixel a gauche
|
||||
mask = 128 >> ((i-1) & 7);
|
||||
vram[(i - 1 - z_buffer_offset)>>3] |= mask;
|
||||
flag = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (flag == false)
|
||||
{
|
||||
if (z_buffer[i-1] == MAX_DEPTH_Z_BUFFER)
|
||||
{
|
||||
// il y avait rien juste a gauche
|
||||
mask = 128 >> (i & 7);
|
||||
vram[(i - z_buffer_offset)>>3] |= mask;
|
||||
flag = true;
|
||||
} else {
|
||||
// l objet commencait en fait 1 pixel a gauche
|
||||
mask = 128 >> ((i-1) & 7);
|
||||
vram[(i - 1 - z_buffer_offset)>>3] |= mask;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // 24 fps
|
||||
// avec astuce +=2 : 25 fps
|
||||
|
||||
/*bool flag = false;
|
||||
char i_mod_8;
|
||||
for (int i = 0; i<z_buffer_size; i++)
|
||||
{
|
||||
i_mod_8 = i & 7;
|
||||
current = z_buffer[i];
|
||||
if (current == MAX_DEPTH_Z_BUFFER)
|
||||
{
|
||||
if (flag == true)
|
||||
{
|
||||
mask |= 128 >> i_mod_8;//((i-1) & 7);
|
||||
flag = false;
|
||||
}
|
||||
} else {
|
||||
if (flag == false)
|
||||
{
|
||||
mask |= 128 >> i_mod_8;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
if (i_mod_8 == 7)
|
||||
{
|
||||
//if (mask > 0)
|
||||
vram[i>>3] |= mask;
|
||||
mask = 0;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
void Windmill::draw_body()
|
||||
{
|
||||
/*int x = camera.x;
|
||||
int y = camera.y;
|
||||
int z = camera.z;
|
||||
|
||||
Vertex v0, v1, v2, v3;
|
||||
set_vertex_xyz()
|
||||
METTRE DIRECT LES VERTEX DANS LE REPERE SCREEN PUIS RENDER...
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// DESSIN DES TRIANGLES
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void Windmill::render_triangles(WMesh mesh)
|
||||
{
|
||||
for (int f = 0; f<mesh.f_length; f++)
|
||||
{
|
||||
Face triangle = mesh.f[f];
|
||||
|
||||
if (triangle.visible)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
mesh.v[triangle.v[i]].set_texture(mesh.t[triangle.t[i]]);
|
||||
}
|
||||
|
||||
// determine quelle face du triangle est visible
|
||||
int visible_face = get_visible_face(&mesh.v[triangle.v[0]], &mesh.v[triangle.v[1]], &mesh.v[triangle.v[2]]);
|
||||
|
||||
// choisi la texture visible
|
||||
const Texture* visible_texture = (visible_face == FRONT) ? triangle.texture_front : triangle.texture_back;
|
||||
|
||||
// selectionne l'ordre d'affichage
|
||||
int a = 0, b = 1, c = 2;
|
||||
if (visible_face != FRONT) {b = 2; c = 1;}
|
||||
|
||||
// pour chaque type de texture
|
||||
if (visible_texture == NULL)
|
||||
{
|
||||
// ne rien faire
|
||||
}
|
||||
else if (visible_texture == &tex_white)
|
||||
{
|
||||
render_triangle_color(&mesh.v[triangle.v[a]], &mesh.v[triangle.v[b]], &mesh.v[triangle.v[c]], C_WHITE);
|
||||
}
|
||||
else if (visible_texture == &tex_light)
|
||||
{
|
||||
render_triangle_color(&mesh.v[triangle.v[a]], &mesh.v[triangle.v[b]], &mesh.v[triangle.v[c]], C_LIGHT);
|
||||
}
|
||||
else if (visible_texture == &tex_dark)
|
||||
{
|
||||
render_triangle_color(&mesh.v[triangle.v[a]], &mesh.v[triangle.v[b]], &mesh.v[triangle.v[c]], C_DARK);
|
||||
}
|
||||
else if (visible_texture == &tex_black)
|
||||
{
|
||||
render_triangle_color(&mesh.v[triangle.v[a]], &mesh.v[triangle.v[b]], &mesh.v[triangle.v[c]], C_BLACK);
|
||||
}
|
||||
else
|
||||
{
|
||||
render_triangle_texture(&mesh.v[triangle.v[a]], &mesh.v[triangle.v[b]], &mesh.v[triangle.v[c]], visible_texture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Windmill::render_triangle_texture(Vertex* vertexA, Vertex* vertexB, Vertex* vertexC, const Texture* texture)
|
||||
{
|
||||
// calcul de l'aire du triangle
|
||||
int area = edge(vertexA, vertexB, vertexC);
|
||||
if (area <= MIN_AREA_CLIP) return;
|
||||
|
||||
// calcul du rectangle circonscrit au triangle
|
||||
int min_x = max(viewport.x1, min(vertexA->x, min(vertexB->x, vertexC->x)));
|
||||
int max_x = min(viewport.x2-1, max(vertexA->x, max(vertexB->x, vertexC->x)));
|
||||
int min_y = max(viewport.y1, min(vertexA->y, min(vertexB->y, vertexC->y)));
|
||||
int max_y = min(viewport.y2-1, max(vertexA->y, max(vertexB->y, vertexC->y)));
|
||||
|
||||
// ajustement des coordonnees des textures a la taille en pixel
|
||||
vertexA->u *= texture->pixel_width;
|
||||
vertexA->v *= texture->pixel_height;
|
||||
vertexB->u *= texture->pixel_width;
|
||||
vertexB->v *= texture->pixel_height;
|
||||
vertexC->u *= texture->pixel_width;
|
||||
vertexC->v *= texture->pixel_height;
|
||||
|
||||
// pre-calcul des coordonnees de la texture << 13 => tex_w * 8192 / x
|
||||
int w0 = vertexA->u * vertexA->inv_z; int h0 = vertexA->v * vertexA->inv_z;
|
||||
int w1 = vertexB->u * vertexB->inv_z; int h1 = vertexB->v * vertexB->inv_z;
|
||||
int w2 = vertexC->u * vertexC->inv_z; int h2 = vertexC->v * vertexC->inv_z;
|
||||
|
||||
// calcul des produits vectoriels
|
||||
int u0_start = edge_start(vertexB, vertexC, min_x, min_y);
|
||||
int u0_step_x = edge_step_x(vertexB, vertexC);
|
||||
int u0_step_y = edge_step_y(vertexB, vertexC);
|
||||
int u1_start = edge_start(vertexC, vertexA, min_x, min_y);
|
||||
int u1_step_x = edge_step_x(vertexC, vertexA);
|
||||
int u1_step_y = edge_step_y(vertexC, vertexA);
|
||||
int u2_start = edge_start(vertexA, vertexB, min_x, min_y);
|
||||
int u2_step_x = edge_step_x(vertexA, vertexB);
|
||||
int u2_step_y = edge_step_y(vertexA, vertexB);
|
||||
|
||||
// << 15
|
||||
int z_num_start = (u0_start * vertexA->z_normalized + u1_start * vertexB->z_normalized + u2_start * vertexC->z_normalized) / area;
|
||||
int z_num_step_x = (u0_step_x * vertexA->z_normalized + u1_step_x * vertexB->z_normalized + u2_step_x * vertexC->z_normalized) / area;
|
||||
int z_num_step_y = (u0_step_y * vertexA->z_normalized + u1_step_y * vertexB->z_normalized + u2_step_y * vertexC->z_normalized) / area;
|
||||
|
||||
// << 13
|
||||
int z_div_start = u0_start * vertexA->inv_z + u1_start * vertexB->inv_z + u2_start * vertexC->inv_z;
|
||||
int z_div_step_x = u0_step_x * vertexA->inv_z + u1_step_x * vertexB->inv_z + u2_step_x * vertexC->inv_z;
|
||||
int z_div_step_y = u0_step_y * vertexA->inv_z + u1_step_y * vertexB->inv_z + u2_step_y * vertexC->inv_z;
|
||||
|
||||
// rapprochement artificiel si texture de type decoration
|
||||
int decoration = 0;//(texture->decoration ? DECORATION_OFFSET : 0);
|
||||
|
||||
// acces a la vram
|
||||
//char* vram = get_vram_address();
|
||||
unsigned char mask_vram, mask_w;
|
||||
int offset_vram;
|
||||
int address;
|
||||
|
||||
int u0, u1, u2;
|
||||
int z_num, z_div;
|
||||
int w, h;
|
||||
|
||||
// pre-calcul largeur en octet des tableaux
|
||||
int nbw_tex = ((texture->pixel_width - 1) >> 3) + 1;
|
||||
char loop_w_tex = texture->pixel_width-1;
|
||||
char loop_h_tex = texture->pixel_height-1;
|
||||
|
||||
// parcours en ligne
|
||||
for(int x=min_x; x<=max_x; x++)
|
||||
{
|
||||
u0 = u0_start; u1 = u1_start; u2 = u2_start;
|
||||
z_num = z_num_start;
|
||||
z_div = z_div_start;
|
||||
offset_vram = x >> 3;
|
||||
mask_vram = 128 >> (x & 7);
|
||||
// parcours en colonne
|
||||
for(int y=min_y; y<=max_y; y++)
|
||||
{
|
||||
// si le pixel (x;y) est dans le triangle
|
||||
if ((u0 | u1 | u2) > 0)
|
||||
{
|
||||
// addresse du z-buffer
|
||||
address = x + y * z_buffer_width + z_buffer_offset;
|
||||
// si le pixel (x;y) est plus proche qu'avant
|
||||
if (z_num <= z_buffer[address] + decoration)
|
||||
{
|
||||
// calcul des coordonnees pour la texture
|
||||
w = ((u0 * w0 + u1 * w1 + u2 * w2) / z_div) & loop_w_tex;
|
||||
h = ((u0 * h0 + u1 * h1 + u2 * h2) / z_div) & loop_h_tex;
|
||||
// calcul du masque pour l'octet
|
||||
mask_w = 128 >> (w & 7);
|
||||
if (texture->mask == NULL)
|
||||
{
|
||||
// enregistre la profondeur du pixel dans le z buffer
|
||||
z_buffer[address] = z_num;
|
||||
|
||||
if (texture->sprite[(w >> 3) + (h * nbw_tex)] & mask_w)
|
||||
{
|
||||
// afficher pixel noir
|
||||
dpixel(x, y, C_BLACK);
|
||||
//vram[(y << 4) + offset_vram] |= mask_vram;
|
||||
}else{
|
||||
// afficher pixel blanc
|
||||
dpixel(x, y, C_WHITE);
|
||||
//vram[(y << 4) + offset_vram] &= ~mask_vram;
|
||||
}
|
||||
// curseur
|
||||
//pixel_on_cursor(x, y);
|
||||
}/* else {
|
||||
int alpha = (w >> 3) + (h * nbw_tex);
|
||||
if ((texture->mask[alpha] & mask_w))
|
||||
{
|
||||
// enregistre la profondeur du pixel dans le z buffer
|
||||
z_buffer[address] = z_num;
|
||||
if ((texture->sprite[alpha] & mask_w))
|
||||
{
|
||||
// afficher pixel noir
|
||||
vram[(y << 4) + offset_vram] |= mask_vram;
|
||||
}else{
|
||||
// afficher pixel blanc
|
||||
vram[(y << 4) + offset_vram] &= ~mask_vram;
|
||||
}
|
||||
// curseur
|
||||
//pixel_on_cursor(x, y);
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
||||
}
|
||||
u0 += u0_step_y; u1 += u1_step_y; u2 += u2_step_y;
|
||||
z_num += z_num_step_y;
|
||||
z_div += z_div_step_y;
|
||||
}
|
||||
u0_start += u0_step_x; u1_start += u1_step_x; u2_start += u2_step_x;
|
||||
z_num_start += z_num_step_x;
|
||||
z_div_start += z_div_step_x;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Windmill::render_triangle_color(Vertex* vertexA, Vertex* vertexB, Vertex* vertexC, color_t color)
|
||||
{
|
||||
// calcul de l'aire du triangle
|
||||
int area = edge(vertexA, vertexB, vertexC);
|
||||
if (area <= MIN_AREA_CLIP) return;
|
||||
|
||||
// calcul du rectangle circonscrit au triangle
|
||||
int min_x = max(viewport.x1, min(vertexA->x, min(vertexB->x, vertexC->x)));
|
||||
int max_x = min(viewport.x2-1, max(vertexA->x, max(vertexB->x, vertexC->x)));
|
||||
int min_y = max(viewport.y1, min(vertexA->y, min(vertexB->y, vertexC->y)));
|
||||
int max_y = min(viewport.y2-1, max(vertexA->y, max(vertexB->y, vertexC->y)));
|
||||
|
||||
// calcul des produits vectoriels
|
||||
int u0_start = edge_start(vertexB, vertexC, min_x, min_y);
|
||||
int u0_step_x = edge_step_x(vertexB, vertexC);
|
||||
int u0_step_y = edge_step_y(vertexB, vertexC);
|
||||
int u1_start = edge_start(vertexC, vertexA, min_x, min_y);
|
||||
int u1_step_x = edge_step_x(vertexC, vertexA);
|
||||
int u1_step_y = edge_step_y(vertexC, vertexA);
|
||||
int u2_start = edge_start(vertexA, vertexB, min_x, min_y);
|
||||
int u2_step_x = edge_step_x(vertexA, vertexB);
|
||||
int u2_step_y = edge_step_y(vertexA, vertexB);
|
||||
|
||||
int z_num_start = (u0_start * vertexA->z_normalized + u1_start * vertexB->z_normalized + u2_start * vertexC->z_normalized) / area;
|
||||
int z_num_step_x = (u0_step_x * vertexA->z_normalized + u1_step_x * vertexB->z_normalized + u2_step_x * vertexC->z_normalized) / area;
|
||||
int z_num_step_y = (u0_step_y * vertexA->z_normalized + u1_step_y * vertexB->z_normalized + u2_step_y * vertexC->z_normalized) / area;
|
||||
|
||||
// acces a la vram
|
||||
char* vram = get_vram_address();
|
||||
|
||||
unsigned char mask_vram;
|
||||
int offset_vram;
|
||||
int address;
|
||||
|
||||
int u0, u1, u2;
|
||||
int z_num;
|
||||
|
||||
// parcours en ligne
|
||||
for(int x=min_x; x<=max_x; x++)
|
||||
{
|
||||
u0 = u0_start; u1 = u1_start; u2 = u2_start;
|
||||
z_num = z_num_start;
|
||||
offset_vram = x >> 3;
|
||||
mask_vram = 128 >> (x & 7);
|
||||
// parcours en colonne
|
||||
for(int y=min_y; y<=max_y; y++)
|
||||
{
|
||||
// si le pixel (x;y) est dans le triangle
|
||||
if ((u0 | u1 | u2) > 0)
|
||||
{
|
||||
// addresse du z-buffer
|
||||
address = x + y * z_buffer_width + z_buffer_offset;
|
||||
// si le pixel (x;y) est plus proche qu'avant
|
||||
if (z_num <= z_buffer[address])
|
||||
{
|
||||
// enregistre la profondeur du pixel dans le z buffer
|
||||
z_buffer[address] = z_num;
|
||||
// afficher pixel
|
||||
dpixel(x, y, color);
|
||||
}
|
||||
}
|
||||
u0 += u0_step_y; u1 += u1_step_y; u2 += u2_step_y;
|
||||
z_num += z_num_step_y;
|
||||
}
|
||||
u0_start += u0_step_x; u1_start += u1_step_x; u2_start += u2_step_x;
|
||||
z_num_start += z_num_step_x;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*void Windmill::render_triangle_black(Vertex* vertexA, Vertex* vertexB, Vertex* vertexC)
|
||||
{
|
||||
// calcul du rectangle circonscrit au triangle
|
||||
int min_x = max(viewport.x1, min(vertexA->x, min(vertexB->x, vertexC->x)));
|
||||
int max_x = min(viewport.x2-1, max(vertexA->x, max(vertexB->x, vertexC->x)));
|
||||
int min_y = max(viewport.y1, min(vertexA->y, min(vertexB->y, vertexC->y)));
|
||||
int max_y = min(viewport.y2-1, max(vertexA->y, max(vertexB->y, vertexC->y)));
|
||||
|
||||
// calcul de l'aire du triangle
|
||||
int area = edge(vertexA, vertexB, vertexC);
|
||||
// termine si la taille du triangle est trop petite
|
||||
if (area <= MIN_AREA_CLIP) return;
|
||||
|
||||
// calcul des produits vectoriels
|
||||
int u0_start = edge_start(vertexB, vertexC, min_x, min_y);
|
||||
int u0_step_x = edge_step_x(vertexB, vertexC);
|
||||
int u0_step_y = edge_step_y(vertexB, vertexC);
|
||||
int u1_start = edge_start(vertexC, vertexA, min_x, min_y);
|
||||
int u1_step_x = edge_step_x(vertexC, vertexA);
|
||||
int u1_step_y = edge_step_y(vertexC, vertexA);
|
||||
int u2_start = edge_start(vertexA, vertexB, min_x, min_y);
|
||||
int u2_step_x = edge_step_x(vertexA, vertexB);
|
||||
int u2_step_y = edge_step_y(vertexA, vertexB);
|
||||
|
||||
int z_num_start = (u0_start * vertexA->z_normalized + u1_start * vertexB->z_normalized + u2_start * vertexC->z_normalized) / area;
|
||||
int z_num_step_x = (u0_step_x * vertexA->z_normalized + u1_step_x * vertexB->z_normalized + u2_step_x * vertexC->z_normalized) / area;
|
||||
int z_num_step_y = (u0_step_y * vertexA->z_normalized + u1_step_y * vertexB->z_normalized + u2_step_y * vertexC->z_normalized) / area;
|
||||
|
||||
// acces a la vram
|
||||
char* vram = get_vram_address();
|
||||
|
||||
unsigned char mask_vram;
|
||||
int offset_vram;
|
||||
int address;
|
||||
|
||||
int u0, u1, u2;
|
||||
int z_num;
|
||||
|
||||
// parcours en ligne
|
||||
for(int x=min_x; x<=max_x; x++)
|
||||
{
|
||||
u0 = u0_start; u1 = u1_start; u2 = u2_start;
|
||||
z_num = z_num_start;
|
||||
offset_vram = x >> 3;
|
||||
mask_vram = 128 >> (x & 7);
|
||||
// parcours en colonne
|
||||
for(int y=min_y; y<=max_y; y++)
|
||||
{
|
||||
// si le pixel (x;y) est dans le triangle
|
||||
if ((u0 | u1 | u2) > 0)
|
||||
{
|
||||
// addresse du z-buffer
|
||||
address = x + y * z_buffer_width + z_buffer_offset;
|
||||
// si le pixel (x;y) est plus proche qu'avant
|
||||
if (z_num <= z_buffer[address])
|
||||
{
|
||||
// enregistre la profondeur du pixel dans le z buffer
|
||||
z_buffer[address] = z_num;
|
||||
// afficher pixel noir
|
||||
vram[(y << 4) + offset_vram] |= mask_vram;
|
||||
// curseur
|
||||
pixel_on_cursor(x, y);
|
||||
}
|
||||
}
|
||||
u0 += u0_step_y; u1 += u1_step_y; u2 += u2_step_y;
|
||||
z_num += z_num_step_y;
|
||||
}
|
||||
u0_start += u0_step_x; u1_start += u1_step_x; u2_start += u2_step_x;
|
||||
z_num_start += z_num_step_x;
|
||||
}
|
||||
}*/
|
||||
|
||||
/*
|
||||
void Windmill::render_triangle_black(Vertex* vertexA, Vertex* vertexB, Vertex* vertexC)
|
||||
{
|
||||
// calcul du rectangle circonscrit au triangle
|
||||
int min_x = max(viewport.x1, min(vertexA->x, min(vertexB->x, vertexC->x)));
|
||||
int max_x = min(viewport.x2-1, max(vertexA->x, max(vertexB->x, vertexC->x)));
|
||||
int min_y = max(viewport.y1, min(vertexA->y, min(vertexB->y, vertexC->y)));
|
||||
int max_y = min(viewport.y2-1, max(vertexA->y, max(vertexB->y, vertexC->y)));
|
||||
|
||||
// calcul de l'aire du triangle
|
||||
int area = edge(vertexA, vertexB, vertexC);
|
||||
// termine si la taille du triangle est trop petite
|
||||
if (area <= MIN_AREA_CLIP) return;
|
||||
|
||||
// calcul des produits vectoriels
|
||||
int u0_start = edge_start(vertexB, vertexC, min_x, min_y);
|
||||
int u0_step_x = edge_step_x(vertexB, vertexC);
|
||||
int u0_step_y = edge_step_y(vertexB, vertexC);
|
||||
int u1_start = edge_start(vertexC, vertexA, min_x, min_y);
|
||||
int u1_step_x = edge_step_x(vertexC, vertexA);
|
||||
int u1_step_y = edge_step_y(vertexC, vertexA);
|
||||
int u2_start = edge_start(vertexA, vertexB, min_x, min_y);
|
||||
int u2_step_x = edge_step_x(vertexA, vertexB);
|
||||
int u2_step_y = edge_step_y(vertexA, vertexB);
|
||||
|
||||
int z_num_start = (u0_start * vertexA->z_normalized + u1_start * vertexB->z_normalized + u2_start * vertexC->z_normalized) / area;
|
||||
int z_num_step_x = (u0_step_x * vertexA->z_normalized + u1_step_x * vertexB->z_normalized + u2_step_x * vertexC->z_normalized) / area;
|
||||
int z_num_step_y = (u0_step_y * vertexA->z_normalized + u1_step_y * vertexB->z_normalized + u2_step_y * vertexC->z_normalized) / area;
|
||||
|
||||
// acces a la vram
|
||||
// char* vram = get_vram_address();
|
||||
unsigned char mask_vram;
|
||||
int offset_vram;
|
||||
int address;
|
||||
|
||||
int u0, u1, u2;
|
||||
int z_num;
|
||||
|
||||
// parcours en ligne
|
||||
for(int x=min_x; x<=max_x; x++)
|
||||
{
|
||||
u0 = u0_start; u1 = u1_start; u2 = u2_start;
|
||||
z_num = z_num_start;
|
||||
offset_vram = x >> 3;
|
||||
mask_vram = 128 >> (x & 7);
|
||||
// parcours en colonne
|
||||
for(int y=min_y; y<=max_y; y++)
|
||||
{
|
||||
// si le pixel (x;y) est dans le triangle
|
||||
if ((u0 | u1 | u2) > 0)
|
||||
{
|
||||
// addresse du z-buffer
|
||||
address = x + y * z_buffer_width + z_buffer_offset;
|
||||
// si le pixel (x;y) est plus proche qu'avant
|
||||
if (z_num <= z_buffer[address])
|
||||
{
|
||||
// enregistre la profondeur du pixel dans le z buffer
|
||||
z_buffer[address] = z_num;
|
||||
// afficher pixel noir
|
||||
// vram[(y << 4) + offset_vram] |= mask_vram;
|
||||
// curseur
|
||||
pixel_on_cursor(x, y);
|
||||
}
|
||||
}
|
||||
u0 += u0_step_y; u1 += u1_step_y; u2 += u2_step_y;
|
||||
z_num += z_num_step_y;
|
||||
}
|
||||
u0_start += u0_step_x; u1_start += u1_step_x; u2_start += u2_step_x;
|
||||
z_num_start += z_num_step_x;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*void Windmill::render_triangle_white(Vertex* vertexA, Vertex* vertexB, Vertex* vertexC)
|
||||
{
|
||||
// calcul du rectangle circonscrit au triangle
|
||||
int min_x = max(viewport.x1, min(vertexA->x, min(vertexB->x, vertexC->x)));
|
||||
int max_x = min(viewport.x2-1, max(vertexA->x, max(vertexB->x, vertexC->x)));
|
||||
int min_y = max(viewport.y1, min(vertexA->y, min(vertexB->y, vertexC->y)));
|
||||
int max_y = min(viewport.y2-1, max(vertexA->y, max(vertexB->y, vertexC->y)));
|
||||
|
||||
// calcul de l'aire du triangle
|
||||
int area = edge(vertexA, vertexB, vertexC);
|
||||
// termine si la taille du triangle est trop petite
|
||||
if (area <= MIN_AREA_CLIP) return;
|
||||
|
||||
// calcul des produits vectoriels
|
||||
int u0_start = edge_start(vertexB, vertexC, min_x, min_y);
|
||||
int u0_step_x = edge_step_x(vertexB, vertexC);
|
||||
int u0_step_y = edge_step_y(vertexB, vertexC);
|
||||
int u1_start = edge_start(vertexC, vertexA, min_x, min_y);
|
||||
int u1_step_x = edge_step_x(vertexC, vertexA);
|
||||
int u1_step_y = edge_step_y(vertexC, vertexA);
|
||||
int u2_start = edge_start(vertexA, vertexB, min_x, min_y);
|
||||
int u2_step_x = edge_step_x(vertexA, vertexB);
|
||||
int u2_step_y = edge_step_y(vertexA, vertexB);
|
||||
|
||||
int z_num_start = (u0_start * vertexA->z_normalized + u1_start * vertexB->z_normalized + u2_start * vertexC->z_normalized) / area;
|
||||
int z_num_step_x = (u0_step_x * vertexA->z_normalized + u1_step_x * vertexB->z_normalized + u2_step_x * vertexC->z_normalized) / area;
|
||||
int z_num_step_y = (u0_step_y * vertexA->z_normalized + u1_step_y * vertexB->z_normalized + u2_step_y * vertexC->z_normalized) / area;
|
||||
|
||||
// acces a la vram
|
||||
char* vram = get_vram_address();
|
||||
unsigned char mask_vram;
|
||||
int offset_vram;
|
||||
int address;
|
||||
|
||||
int u0, u1, u2;
|
||||
int z_num;
|
||||
|
||||
// parcours en ligne
|
||||
for(int x=min_x; x<=max_x; x++)
|
||||
{
|
||||
u0 = u0_start; u1 = u1_start; u2 = u2_start;
|
||||
z_num = z_num_start;
|
||||
offset_vram = x >> 3;
|
||||
mask_vram = 128 >> (x & 7);
|
||||
// parcours en colonne
|
||||
for(int y=min_y; y<=max_y; y++)
|
||||
{
|
||||
// si le pixel (x;y) est dans le triangle
|
||||
if ((u0 | u1 | u2) > 0)
|
||||
{
|
||||
// addresse du z-buffer
|
||||
address = x + y * z_buffer_width + z_buffer_offset;
|
||||
// si le pixel (x;y) est plus proche qu'avant
|
||||
if (z_num <= z_buffer[address])
|
||||
{
|
||||
// enregistre la profondeur du pixel dans le z buffer
|
||||
z_buffer[address] = z_num;
|
||||
// afficher pixel blanc
|
||||
vram[(y << 4) + offset_vram] &= ~mask_vram;
|
||||
// curseur
|
||||
pixel_on_cursor(x, y);
|
||||
}
|
||||
}
|
||||
u0 += u0_step_y; u1 += u1_step_y; u2 += u2_step_y;
|
||||
z_num += z_num_step_y;
|
||||
}
|
||||
u0_start += u0_step_x; u1_start += u1_step_x; u2_start += u2_step_x;
|
||||
z_num_start += z_num_step_x;
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
/*void Windmill::render_triangle_transparent(Vertex* vertexA, Vertex* vertexB, Vertex* vertexC, const Texture* texture)
|
||||
{
|
||||
// calcul du rectangle circonscrit au triangle
|
||||
int min_x = max(viewport.x1, min(vertexA->x, min(vertexB->x, vertexC->x)));
|
||||
int max_x = min(viewport.x2-1, max(vertexA->x, max(vertexB->x, vertexC->x)));
|
||||
int min_y = max(viewport.y1, min(vertexA->y, min(vertexB->y, vertexC->y)));
|
||||
int max_y = min(viewport.y2-1, max(vertexA->y, max(vertexB->y, vertexC->y)));
|
||||
|
||||
// calcul de l'aire du triangle
|
||||
int area = edge(vertexA, vertexB, vertexC);
|
||||
// termine si la taille du triangle est trop petite
|
||||
if (area <= MIN_AREA_CLIP) return;
|
||||
|
||||
// pre-calcul des coordonnees de la texture
|
||||
int w0 = vertexA->w * vertexA->z; int h0 = vertexA->h * vertexA->z;
|
||||
int w1 = vertexB->w * vertexB->z; int h1 = vertexB->h * vertexB->z;
|
||||
int w2 = vertexC->w * vertexC->z; int h2 = vertexC->h * vertexC->z;
|
||||
|
||||
// calcul des produits vectoriels
|
||||
int u0_start = edge_start(vertexB, vertexC, min_x, min_y);
|
||||
int u0_step_x = edge_step_x(vertexB, vertexC);
|
||||
int u0_step_y = edge_step_y(vertexB, vertexC);
|
||||
int u1_start = edge_start(vertexC, vertexA, min_x, min_y);
|
||||
int u1_step_x = edge_step_x(vertexC, vertexA);
|
||||
int u1_step_y = edge_step_y(vertexC, vertexA);
|
||||
int u2_start = edge_start(vertexA, vertexB, min_x, min_y);
|
||||
int u2_step_x = edge_step_x(vertexA, vertexB);
|
||||
int u2_step_y = edge_step_y(vertexA, vertexB);
|
||||
|
||||
int z_num_start = (u0_start * vertexA->z_normalized + u1_start * vertexB->z_normalized + u2_start * vertexC->z_normalized) / area;
|
||||
int z_num_step_x = (u0_step_x * vertexA->z_normalized + u1_step_x * vertexB->z_normalized + u2_step_x * vertexC->z_normalized) / area;
|
||||
int z_num_step_y = (u0_step_y * vertexA->z_normalized + u1_step_y * vertexB->z_normalized + u2_step_y * vertexC->z_normalized) / area;
|
||||
|
||||
int z_div_start = u0_start * vertexA->z + u1_start * vertexB->z + u2_start * vertexC->z;
|
||||
int z_div_step_x = u0_step_x * vertexA->z + u1_step_x * vertexB->z + u2_step_x * vertexC->z;
|
||||
int z_div_step_y = u0_step_y * vertexA->z + u1_step_y * vertexB->z + u2_step_y * vertexC->z;
|
||||
|
||||
// acces a la vram
|
||||
char* vram = get_vram_address();
|
||||
|
||||
// pre-calcul largeur en octet des tableaux
|
||||
int nbw_tex = ((texture->pixel_width - 1) >> 3) + 1;
|
||||
char loop_w_tex = texture->pixel_width-1;
|
||||
char loop_h_tex = texture->pixel_height-1;
|
||||
|
||||
// parcours en ligne
|
||||
for(int x=min_x; x<=max_x; x++)
|
||||
{
|
||||
int u0 = u0_start; int u1 = u1_start; int u2 = u2_start;
|
||||
int z_num = z_num_start;
|
||||
int z_div = z_div_start;
|
||||
int offset_vram = x >> 3;
|
||||
char mask_vram = 128 >> (x & 7);
|
||||
// parcours en colonne
|
||||
for(int y=min_y; y<=max_y; y++)
|
||||
{
|
||||
// si le pixel (x;y) est dans le triangle
|
||||
if ((u0 | u1 | u2) > 0)
|
||||
{
|
||||
// addresse du z-buffer
|
||||
int address = x + y * z_buffer_width + z_buffer_offset;
|
||||
// si le pixel (x;y) est plus proche qu'avant
|
||||
if (z_num <= z_buffer[address])
|
||||
{
|
||||
// calcul des coordonnees pour la texture
|
||||
unsigned int w = ((u0 * w0 + u1 * w1 + u2 * w2) / z_div) & loop_w_tex;
|
||||
unsigned int h = ((u0 * h0 + u1 * h1 + u2 * h2) / z_div) & loop_h_tex;
|
||||
// calcul du masque pour l'octet
|
||||
unsigned char mask_w = 128 >> (w & 7);
|
||||
if ((texture->sprite[(w >> 3) + (h * nbw_tex)] & mask_w))
|
||||
{
|
||||
// afficher pixel noir
|
||||
vram[(y << 4) + offset_vram] |= mask_vram;
|
||||
// enregistre la profondeur du pixel dans le z buffer
|
||||
z_buffer[address] = z_num;
|
||||
}
|
||||
}
|
||||
}
|
||||
u0 += u0_step_y; u1 += u1_step_y; u2 += u2_step_y;
|
||||
z_num += z_num_step_y;
|
||||
z_div += z_div_step_y;
|
||||
}
|
||||
u0_start += u0_step_x; u1_start += u1_step_x; u2_start += u2_step_x;
|
||||
z_num_start += z_num_step_x;
|
||||
z_div_start += z_div_step_x;
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// UTILITAIRES
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
||||
int Windmill::edge(Vertex* a, Vertex* b, Vertex* c)
|
||||
{
|
||||
return (c->x - a->x) * (b->y - a->y) - (c->y - a->y) * (b->x - a->x);
|
||||
}
|
||||
|
||||
|
||||
int Windmill::edge_start(Vertex* a, Vertex* b, int px, int py)
|
||||
{
|
||||
return (b->y - a->y) * (px - a->x) - (b->x - a->x) * (py - a->y);
|
||||
}
|
||||
|
||||
|
||||
int Windmill::edge_step_x(Vertex* a, Vertex* b)
|
||||
{
|
||||
return b->y - a->y;
|
||||
}
|
||||
|
||||
|
||||
int Windmill::edge_step_y(Vertex* a, Vertex* b)
|
||||
{
|
||||
return a->x - b->x;
|
||||
}
|
|
@ -0,0 +1,257 @@
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// WINDMILL
|
||||
//
|
||||
// version : 2.0
|
||||
// Moteur de rendu 3D base sur la methode de rasterisation avec buffer de profondeur
|
||||
//
|
||||
// Cree par Olivier Lanneau, alias NineStars
|
||||
// Planet-casio.fr
|
||||
//
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "windmill.hpp"
|
||||
|
||||
void debug_pop(char const *fmt, ...);
|
||||
void debug_display(char const *fmt, ...);
|
||||
|
||||
|
||||
extern Texture tex_white;
|
||||
extern Texture tex_light;
|
||||
extern Texture tex_dark;
|
||||
extern Texture tex_black;
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// INITIALISATION
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
Windmill::Windmill()
|
||||
{
|
||||
camera2 = NULL;
|
||||
map = NULL;
|
||||
//object = NULL;
|
||||
z_buffer = NULL;
|
||||
set_viewport(0, 0, 128, 64);
|
||||
|
||||
sun = {0, 0, 100};
|
||||
}
|
||||
|
||||
|
||||
Windmill::~Windmill()
|
||||
{
|
||||
free(z_buffer);
|
||||
//free(object);
|
||||
}
|
||||
|
||||
|
||||
void Windmill::set_camera(Camera* _camera)
|
||||
{
|
||||
camera2 = _camera;
|
||||
}
|
||||
|
||||
|
||||
void Windmill::set_viewport(int viewport_x1, int viewport_y1, int viewport_x2, int viewport_y2)
|
||||
{
|
||||
viewport.x1 = max(0, viewport_x1);
|
||||
viewport.y1 = max(0, viewport_y1);
|
||||
viewport.x2 = min(viewport_x2, DWIDTH);
|
||||
viewport.y2 = min(viewport_y2, DHEIGHT);
|
||||
|
||||
//if (z_buffer != NULL) free(z_buffer);
|
||||
free(z_buffer);
|
||||
shift_x = (viewport.x1 + viewport.x2) / 2;
|
||||
shift_y = (viewport.y1 + viewport.y2) / 2;
|
||||
|
||||
z_buffer_size = (viewport.x2 - viewport.x1) * (viewport.y2 - viewport.y1);
|
||||
z_buffer = (unsigned short*) calloc(z_buffer_size, 2);
|
||||
//if (z_buffer == NULL) debug_pop("ERROR ptr z_buffer NULL");
|
||||
z_buffer_width = viewport.x2 - viewport.x1;
|
||||
z_buffer_offset = - viewport.x1 - viewport.y1 * DWIDTH;
|
||||
clear_z_buffer();
|
||||
}
|
||||
|
||||
|
||||
void Windmill::set_map(Map* _map)
|
||||
{
|
||||
loading = true;
|
||||
|
||||
if (map != _map)
|
||||
{
|
||||
// free les anciennes ombres
|
||||
// ...
|
||||
|
||||
// attribution de la map
|
||||
map = _map;
|
||||
|
||||
// enregistrement d'une liste triable
|
||||
//set_objects();
|
||||
|
||||
// calcul des spheres englobantes de chaque objet
|
||||
compute_bouding_sphere();
|
||||
|
||||
// calcul des ombres projetees au sol par chaque objet
|
||||
//compute_shadows();
|
||||
}
|
||||
|
||||
loading = false;
|
||||
}
|
||||
|
||||
/*void Windmill::set_objects()
|
||||
{
|
||||
//objects = new Object* [map->object_length];
|
||||
objects = (Object**) malloc(map->object_length * sizeof(Object));
|
||||
if (objects == NULL) debug_pop("ERROR ptr object NULL");
|
||||
|
||||
for (int i = 0; i<map->object_length; i++)
|
||||
{
|
||||
objects[i] = map->object[i];
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
void Windmill::compute_bouding_sphere()
|
||||
{
|
||||
// calcul des spheres englobantes pour chaque objet
|
||||
for (int i = 0; i<map->object_length; i++)
|
||||
{
|
||||
Object* object = map->object[i];
|
||||
int nb_point = 0;
|
||||
int barycenter_x = 0;
|
||||
int barycenter_y = 0;
|
||||
int barycenter_z = 0;
|
||||
|
||||
// calcul du barycentre
|
||||
for (int v = 0; v<object->mesh->v_length; v++)
|
||||
{
|
||||
VertexPoint vp = object->mesh->v[v];
|
||||
barycenter_x += vp.x;
|
||||
barycenter_y += vp.y;
|
||||
barycenter_z += vp.z;
|
||||
|
||||
nb_point++;
|
||||
}
|
||||
barycenter_x /= nb_point;
|
||||
barycenter_y /= nb_point;
|
||||
barycenter_z /= nb_point;
|
||||
|
||||
// recherche du point le plus eloigne du barycentre
|
||||
int square_radius_max = 0;
|
||||
for (int v = 0; v<object->mesh->v_length; v++)
|
||||
{
|
||||
VertexPoint vp = object->mesh->v[v];
|
||||
int dx = vp.x - barycenter_x;
|
||||
int dy = vp.y - barycenter_y;
|
||||
int dz = vp.z - barycenter_z;
|
||||
int square_radius = dx*dx + dy*dy + dz*dz;
|
||||
if (square_radius > square_radius_max)
|
||||
{
|
||||
square_radius_max = square_radius;
|
||||
}
|
||||
}
|
||||
|
||||
// enregistrement
|
||||
object->sphere.x = barycenter_x;
|
||||
object->sphere.y = barycenter_y;
|
||||
object->sphere.z = barycenter_z;
|
||||
object->sphere.radius = sqrtf(square_radius_max) + 1;
|
||||
object->sphere.square_radius = square_radius_max + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*WMesh Windmill::compute_shadows()
|
||||
{
|
||||
// pout chaque objet
|
||||
for (int i = 0; i<map->object_length; i++)
|
||||
{
|
||||
Object* object = map->object[i];
|
||||
|
||||
list_shadows_length = get_points_size(object;
|
||||
//debug_pop("sh %i", list_shadows_length);
|
||||
shadows = (Point*) malloc(list_shadows_length * sizeof(Point));
|
||||
int index = 0;
|
||||
|
||||
// pour chaque poly
|
||||
for (int j = 0; j<object->modele_size; j++)
|
||||
{
|
||||
const Modele* current_poly = &object->modele[j];
|
||||
for (int k = 0; k<current_poly->type; k++)
|
||||
{
|
||||
Point point = get_point(current_poly, k);
|
||||
Point shadow_point = {(sun.x * point.z - sun.z * point.x) / (point.z - sun.z), (sun.y * point.z - sun.z * point.y) / (point.z - sun.z), 0};
|
||||
|
||||
shadows[index] = shadow_point;
|
||||
index ++;
|
||||
//debug_pop("p %i %i %i", point.x, point.y, point.z);
|
||||
//debug_pop("s %i %i %i", shadow_point.x, shadow_point.y, shadow_point.z);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Gift Wrapping algorithme
|
||||
void Windmill::compute_shadows_hull(Point3D* points, int points_size)
|
||||
{
|
||||
if (points_size < 3) return;
|
||||
|
||||
Point3D* temp_hull = (Point3D*) malloc(list_shadows_length * sizeof(Point3D));
|
||||
int temp_hull_length = 0;
|
||||
|
||||
// commencer par le point le plus a gauche
|
||||
int left = 0;
|
||||
for (int i = 1; i<points_size; i++)
|
||||
{
|
||||
if (points[i].x < points[left].x)
|
||||
{
|
||||
left = i;
|
||||
}
|
||||
}
|
||||
|
||||
// calcul de la coque
|
||||
int p = left, q;
|
||||
do
|
||||
{
|
||||
// conserver point p
|
||||
temp_hull[temp_hull_length] = points[p];
|
||||
temp_hull_length ++;
|
||||
|
||||
q = (p+1)%points_size;
|
||||
|
||||
for (int i = 0; i < points_size; i++)
|
||||
{
|
||||
if (compute_shadows_hull_orientation(points[p], points[i], points[q]) == 2) // clockwise
|
||||
{
|
||||
q = i;
|
||||
}
|
||||
p = q;
|
||||
}
|
||||
|
||||
} while (p != left);
|
||||
|
||||
|
||||
free(temp_hull);
|
||||
|
||||
int hull_length = temp_hull_length;
|
||||
|
||||
Point3D* hull = (Point3D*) malloc(hull_length * sizeof(Point3D));
|
||||
memcpy(hull, temp_hull, hull_length * sizeof(Point3D));
|
||||
|
||||
for (int i = 0; i<temp_hull_length; i++)
|
||||
{
|
||||
//dprint(0, 8*i)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int Windmill::compute_shadows_hull_orientation(Point3D a, Point3D b, Point3D c)
|
||||
{
|
||||
int val = (b.y - a.y) * (c.x - b.x) - (b.x - a.x) * (c.y - b.y);
|
||||
if (val == 0) return 0; // colineaire
|
||||
return (val > 0)? 1 : 2; // clock ou counterclock wise
|
||||
}*/
|
|
@ -0,0 +1,133 @@
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// WINDMILL
|
||||
//
|
||||
// version : 2.0
|
||||
// Moteur de rendu 3D base sur la methode de rasterisation avec buffer de profondeur
|
||||
//
|
||||
// Cree par Olivier Lanneau, alias NineStars
|
||||
// Planet-casio.fr
|
||||
//
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "windmill.hpp"
|
||||
|
||||
void debug_pop(char const *fmt, ...);
|
||||
|
||||
extern Texture tex_white;
|
||||
extern Texture tex_light;
|
||||
extern Texture tex_dark;
|
||||
extern Texture tex_black;
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// TRANSFORMATION 3D
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void Windmill::transform_model_to_world(Object* object, Vertex vertex[], int vertex_length)
|
||||
{
|
||||
int cos = 0, sin = 0;
|
||||
|
||||
// precalcul de cos et sin
|
||||
// /!\ CHANGEMENT D'ECHELLE : cos et sin << 10
|
||||
/*if (object->axe == Z_BILLBOARD)
|
||||
{
|
||||
float angle_look_at_camera = atan2f(camera.y - object->y, camera.x - object->x);
|
||||
float angle_rad = angle_look_at_camera + 3.1415 * object->angle / 180.0;
|
||||
cosinus = 1024 * cosf(angle_rad);
|
||||
sinus = 1024 * sinf(angle_rad);
|
||||
}*/
|
||||
//if (object->rotation.Null() == false)
|
||||
if (object->axe == N)
|
||||
{
|
||||
float angle_rad = 3.1415 * object->angle / 180.0;
|
||||
cos = 1024 * cosf(angle_rad);
|
||||
sin = 1024 * sinf(angle_rad);
|
||||
}
|
||||
|
||||
// transformation de chaque vertex
|
||||
for (int k = 0; k<vertex_length; k++)
|
||||
{
|
||||
int vertex_x = vertex[k].x;
|
||||
int vertex_y = vertex[k].y;
|
||||
int vertex_z = vertex[k].z;
|
||||
|
||||
//if (cos == 0 and sin == 0)
|
||||
if(object->axe == N)
|
||||
{
|
||||
vertex[k].x = vertex_x + object->position.x;
|
||||
vertex[k].y = vertex_y + object->position.y;
|
||||
vertex[k].z = vertex_z + object->position.z;
|
||||
}
|
||||
/*else
|
||||
{
|
||||
int a1 = object->rotation.x * object->rotation.x * (1024 - cos) + cos;
|
||||
int a2 = object->rotation.x * object->rotation.y * (1024 - cos) - object->rotation.z * sin;
|
||||
int a3 = object->rotation.x * object->rotation.y * (1024 - cos) + object->rotation.y * sin;
|
||||
int a4 = object->rotation.x * object->rotation.y * (1024 - cos) + object->rotation.z * sin;
|
||||
int a5 = object->rotation.y * object->rotation.y * (1024 - cos) + cos;
|
||||
int a6 = object->rotation.y * object->rotation.z * (1024 - cos) - object->rotation.x * sin;
|
||||
int a7 = object->rotation.x * object->rotation.z * (1024 - cos) - object->rotation.y * sin;
|
||||
int a8 = object->rotation.y * object->rotation.z * (1024 - cos) + object->rotation.x * sin;
|
||||
int a9 = object->rotation.z * object->rotation.z * (1024 - cos) + cos;
|
||||
|
||||
vertex[k].x = (a1 * vertex_x + a2 * vertex_y + a3 * vertex_z) / 1024 + object->position.x;
|
||||
vertex[k].y = (a4 * vertex_x + a5 * vertex_y + a6 * vertex_z) / 1024 + object->position.y;
|
||||
vertex[k].z = (a7 * vertex_x + a8 * vertex_y + a9 * vertex_z) / 1024 + object->position.z;
|
||||
|
||||
//vertex[k].x = ((vertex_x * cosinus - vertex_z * sinus) >> 10) + object->position.x;
|
||||
//vertex[k].y = ((vertex_y * cosinus - vertex_z * sinus) >> 10) + object->position.y;
|
||||
//vertex[k].z = ((vertex_y * sinus + vertex_z * cosinus) >> 10) + object->position.z;
|
||||
}*/
|
||||
if (object->axe == RX)
|
||||
{
|
||||
vertex[k].x = vertex_x + object->position.x;
|
||||
vertex[k].y = ((vertex_y * cos - vertex_z * sin) / 1024) + object->position.y;
|
||||
vertex[k].z = ((vertex_y * sin + vertex_z * cos) / 1024) + object->position.z;
|
||||
}
|
||||
if (object->axe == RY)
|
||||
{
|
||||
vertex[k].x = ((vertex_x * cos - vertex_z * sin) / 1024) + object->position.x;
|
||||
vertex[k].y = vertex_y + object->position.y;
|
||||
vertex[k].z = ((vertex_x * sin + vertex_z * cos) / 1024) + object->position.z;
|
||||
}
|
||||
if (object->axe == RZ)// or object->axe == Z_BILLBOARD)
|
||||
{
|
||||
vertex[k].x = ((vertex_x * cos - vertex_y * sin) / 1024) + object->position.x;
|
||||
vertex[k].y = ((vertex_x * sin + vertex_y * cos) / 1024) + object->position.y;
|
||||
vertex[k].z = vertex_z + object->position.z;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Windmill::transform_world_to_camera(Vertex vertex[], int vertex_length)
|
||||
{
|
||||
for (int k = 0; k<vertex_length; k++)
|
||||
{
|
||||
// translation
|
||||
int vertex_x = int(camera.x) - vertex[k].x;
|
||||
int vertex_y = int(camera.y) - vertex[k].y;
|
||||
int vertex_z = int(camera.z) - vertex[k].z;
|
||||
// rotation
|
||||
vertex[k].z = (-(camera.a1 * vertex_x + camera.a2 * vertex_y + camera.a3 * vertex_z) ) / SCALE_AI;
|
||||
vertex[k].x = (camera.a4 * vertex_x + camera.a5 * vertex_y + camera.a6 * vertex_z ) / SCALE_AI;
|
||||
vertex[k].y = (camera.a7 * vertex_x + camera.a8 * vertex_y + camera.a9 * vertex_z ) / SCALE_AI;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Windmill::transform_camera_to_screen(Vertex vertex[], int vertex_length)
|
||||
{
|
||||
for (int k = 0; k<vertex_length; k++)
|
||||
{
|
||||
// perspective
|
||||
vertex[k].x = (vertex[k].x * camera.scale_coef) / vertex[k].z + shift_x;
|
||||
vertex[k].y = (vertex[k].y * camera.scale_coef) / vertex[k].z + shift_y;
|
||||
|
||||
// pre calcul
|
||||
vertex[k].inv_z = (1<<13) / vertex[k].z;
|
||||
vertex[k].z_normalized = (1<<15) * ( float(vertex[k].z - camera.near) / float(camera.far) );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,240 @@
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// WINDMILL
|
||||
//
|
||||
// version : 2.0
|
||||
// Moteur de rendu 3D base sur la methode de rasterisation avec buffer de profondeur
|
||||
//
|
||||
// Cree par Olivier Lanneau, alias NineStars
|
||||
// Planet-casio.fr
|
||||
//
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "windmill.hpp"
|
||||
|
||||
void debug_pop(char const *fmt, ...);
|
||||
|
||||
extern Texture tex_white;
|
||||
extern Texture tex_light;
|
||||
extern Texture tex_dark;
|
||||
extern Texture tex_black;
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// DIVERS
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
/*void WMesh::from_mesh(const Mesh* mesh, int margin)
|
||||
{
|
||||
// Double allocated memory because 3D clipping could generate more vertices and copy mesh into working mesh
|
||||
WMesh wmesh;
|
||||
|
||||
v_length = mesh->v_length;
|
||||
v_length_allocated = mesh->v_length * margin;
|
||||
v = (Vertex*) malloc(v_length_allocated * sizeof(Vertex));
|
||||
for (int i = 0; i < mesh->v_length; i++)
|
||||
{
|
||||
//v[i].FromVertexPoint(mesh->v[i])
|
||||
v[i].x = mesh->v[i].x;
|
||||
v[i].y = mesh->v[i].y;
|
||||
v[i].z = mesh->v[i].z;
|
||||
}
|
||||
|
||||
t_length = mesh->t_length;
|
||||
t_length_allocated = mesh->t_length * margin;
|
||||
t = (TexturePoint*) malloc(t_length_allocated * sizeof(TexturePoint));
|
||||
memcpy(t, mesh->t, mesh->t_length * sizeof(TexturePoint));
|
||||
|
||||
f_length = mesh->f_length;
|
||||
f_length_allocated = mesh->f_length * margin;
|
||||
f = (Face*) malloc(f_length_allocated * sizeof(Face));
|
||||
memcpy(f, mesh->f, mesh->f_length * sizeof(Face));
|
||||
|
||||
return wmesh;
|
||||
}*/
|
||||
|
||||
|
||||
/*WMesh Windmill::create_working_mesh(const WMesh* wmesh)
|
||||
{
|
||||
WMesh output_wmesh;
|
||||
|
||||
output_v_length = 0;
|
||||
output_v_length_allocated = wmesh->v_length_allocated;
|
||||
output_v = (Vertex*) malloc(output_v_length_allocated * sizeof(Vertex));
|
||||
|
||||
output_t_length = 0;
|
||||
output_t_length_allocated = wmesh->t_length_allocated;
|
||||
output_t = (TexturePoint*) malloc(output_t_length_allocated * sizeof(TexturePoint));
|
||||
|
||||
output_f_length = 0;
|
||||
output_f_length_allocated = wmesh->f_length_allocated;
|
||||
output_f = (Face*) malloc(output_f_length_allocated * sizeof(Face));
|
||||
|
||||
return output_wmesh;
|
||||
}*/
|
||||
|
||||
|
||||
void Windmill::copy_camera()
|
||||
{
|
||||
memcpy(&camera, camera2, sizeof(Camera)); // a supprimer cf remarque lephe
|
||||
}
|
||||
|
||||
|
||||
void Windmill::sort_object()
|
||||
{
|
||||
qsort(map->object, map->object_length, sizeof(Object*), compare_object);
|
||||
}
|
||||
|
||||
|
||||
int compare_object(void const *a, void const *b)
|
||||
{
|
||||
Object* object_a = *(Object **) a;
|
||||
Object* object_b = *(Object **) b;
|
||||
return (object_a->position.z - object_b->position.z);
|
||||
}
|
||||
|
||||
|
||||
void Windmill::clear_z_buffer()
|
||||
{
|
||||
memset(z_buffer, MAX_DEPTH_Z_BUFFER, z_buffer_size * sizeof(short));
|
||||
}
|
||||
|
||||
float Windmill::distance(float dx, float dy, float dz)
|
||||
{
|
||||
return sqrtf(dx*dx + dy*dy + dz*dz);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// DEBUG
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void Windmill::show_coordinates()
|
||||
{
|
||||
// coordonnees
|
||||
float tab_coordinates[5] = {camera.x, camera.y, camera.z, to_deg(camera.yaw), to_deg(camera.pitch)};
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
dprint_opt(1, 1+8*i, C_BLACK, C_WHITE, 0, 0, "%i", (int)(tab_coordinates[i]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Windmill::show_repere()
|
||||
{
|
||||
// repere
|
||||
int repere_x = 112;
|
||||
int repere_y = 55;
|
||||
int repere_size = -12;
|
||||
|
||||
// repere
|
||||
Vertex v[3];
|
||||
const char* letter[] = {"x", "y", "z"};
|
||||
v[0].set_xyz(repere_size, 0 , 0 );
|
||||
v[1].set_xyz(0 , repere_size, 0 );
|
||||
v[2].set_xyz(0 , 0 , repere_size);
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
float x3D = (camera.a4 * v[i].x + camera.a5 * v[i].y + camera.a6 * v[i].z) / 128;
|
||||
float y3D = (camera.a7 * v[i].x + camera.a8 * v[i].y + camera.a9 * v[i].z) / 128;
|
||||
//float z3D = (-(camera.a1 * v[i].x + camera.a2 * v[i].y + camera.a3 * v[i].z)) / 128;
|
||||
|
||||
float x2D = x3D;
|
||||
float y2D = y3D;
|
||||
|
||||
//int color = (z3D < 0 ? C_BLACK : C_LIGHT);
|
||||
|
||||
dline(repere_x, repere_y, x2D + repere_x, y2D + repere_y, C_BLACK);
|
||||
dtext(x2D + repere_x, y2D + repere_y-2, C_BLACK, letter[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// VERTEX
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
Vertex::Vertex(){}
|
||||
|
||||
Vertex::Vertex(int _x, int _y, int _z)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
z = _z;
|
||||
}
|
||||
|
||||
Vertex::Vertex(int _x, int _y, int _z, float _u, float _v)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
z = _z;
|
||||
u = _u;
|
||||
v = _v;
|
||||
}
|
||||
|
||||
void Vertex::set_texture(TexturePoint t)
|
||||
{
|
||||
u = t.u;
|
||||
v = t.v;
|
||||
}
|
||||
|
||||
void Vertex::set_xyz(int _x, int _y, int _z)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
z = _z;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// WMESH
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
||||
void WMesh::from_mesh(const Mesh* mesh, int margin)
|
||||
{
|
||||
// Double allocated memory because 3D clipping could generate more vertices and copy mesh into working mesh
|
||||
v_length = mesh->v_length;
|
||||
v_length_allocated = mesh->v_length * margin;
|
||||
v = (Vertex*) malloc(v_length_allocated * sizeof(Vertex));
|
||||
for (int i = 0; i < mesh->v_length; i++)
|
||||
{
|
||||
//v[i].FromVertexPoint(mesh->v[i])
|
||||
v[i].x = mesh->v[i].x;
|
||||
v[i].y = mesh->v[i].y;
|
||||
v[i].z = mesh->v[i].z;
|
||||
}
|
||||
|
||||
t_length = mesh->t_length;
|
||||
t_length_allocated = mesh->t_length * margin;
|
||||
t = (TexturePoint*) malloc(t_length_allocated * sizeof(TexturePoint));
|
||||
memcpy(t, mesh->t, mesh->t_length * sizeof(TexturePoint));
|
||||
|
||||
f_length = mesh->f_length;
|
||||
f_length_allocated = mesh->f_length * margin;
|
||||
f = (Face*) malloc(f_length_allocated * sizeof(Face));
|
||||
memcpy(f, mesh->f, mesh->f_length * sizeof(Face));
|
||||
}
|
||||
|
||||
void WMesh::free_memory()
|
||||
{
|
||||
free(v);
|
||||
free(t);
|
||||
free(f);
|
||||
}
|
||||
|
||||
void WMesh::add_vertex(Vertex vertex)
|
||||
{
|
||||
v[v_length].x = vertex.x;
|
||||
v[v_length].y = vertex.y;
|
||||
v[v_length].z = vertex.z;
|
||||
t[t_length].u = vertex.u;
|
||||
t[t_length].v = vertex.v;
|
||||
|
||||
if (v_length < v_length_allocated) v_length++;
|
||||
if (t_length < t_length_allocated) t_length++;
|
||||
}
|
Loading…
Reference in New Issue