Merge pull request #268 from kichikuou/drawfield

Pastel Chime Continue: Add DrawField HLL
This commit is contained in:
Nunuhara Cabbage
2025-08-30 10:05:32 -07:00
committed by GitHub
13 changed files with 1104 additions and 185 deletions
+18 -4
View File
@@ -20,6 +20,7 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <cglm/cglm.h>
/*
* Dungeon data is a collection of cells indexed by three integers (x, y, z).
@@ -92,6 +93,10 @@ struct dgn_cell {
float south_door_angle;
float east_door_angle;
float west_door_angle;
int north_door_lock;
int south_door_lock;
int east_door_lock;
int west_door_lock;
int32_t floor_event2;
int32_t north_event2;
int32_t south_event2;
@@ -113,19 +118,28 @@ struct packed_pvs {
};
struct dgn {
uint32_t version; // 10: Rance VI, 13: GALZOO Island
uint32_t version;
uint32_t size_x;
uint32_t size_y;
uint32_t size_z;
// uint32_t unknown[10];
struct dgn_cell *cells;
struct packed_pvs *pvs;
vec3 sphere_theta;
float sphere_color_top;
float sphere_color_bottom;
int start_x, start_y; // DrawDungeon2
int exit_x, exit_y; // DrawDungeon2
// DrawDungeon2
int start_x, start_y;
int exit_x, exit_y;
// DrawField
int32_t back_color_r;
int32_t back_color_g;
int32_t back_color_b;
};
struct dgn *dgn_parse(uint8_t *data, size_t size);
struct dgn *dgn_parse(uint8_t *data, size_t size, bool for_draw_field);
void dgn_free(struct dgn *dgn);
int dgn_cell_index(struct dgn *dgn, uint32_t x, uint32_t y, uint32_t z);
+18 -1
View File
@@ -20,20 +20,25 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <cglm/cglm.h>
#include "gfx/gfx.h"
#include "plugin.h"
#define DRAWFIELD_NR_CHARACTERS 256
struct page;
struct dgn;
struct dtx;
struct tes;
struct dungeon_renderer;
struct dungeon_map;
struct drawfield_character;
enum draw_dungeon_version {
DRAW_DUNGEON_1, // Rance VI
DRAW_DUNGEON_2, // Dungeons & Dolls
DRAW_DUNGEON_14 // GALZOO Island
DRAW_DUNGEON_14, // GALZOO Island
DRAW_FIELD // Pastel Chime Continue
};
struct camera {
@@ -62,6 +67,9 @@ struct dungeon_context {
struct dgn *dgn;
struct dtx *dtx;
struct tes *tes;
ivec3 player_pos;
struct drawfield_character *characters;
mat4 proj_transform;
struct dungeon_renderer *renderer;
struct texture texture;
GLuint depth_buffer;
@@ -69,7 +77,11 @@ struct dungeon_context {
struct dungeon_context *dungeon_context_create(enum draw_dungeon_version version, int width, int height);
bool dungeon_load(struct dungeon_context *ctx, int num);
bool dungeon_load_dungeon(struct dungeon_context *ctx, const char *filename, int num);
bool dungeon_load_texture(struct dungeon_context *ctx, const char *filename);
void dungeon_set_camera(int surface, float x, float y, float z, float angle, float angle_p);
void dungeon_set_perspective(int surface, int width, int height, float near, float far, float deg);
void dungeon_set_player_pos(int surface, int x, int y, int z);
void dungeon_set_walked(int surface, int x, int y, int z, int flag);
int dungeon_get_walked(int surface, int x, int y, int z);
void dungeon_set_walked_all(int surface);
@@ -77,6 +89,11 @@ int dungeon_calc_conquer(int surface);
bool dungeon_load_walk_data(int surface, int map, struct page **page);
bool dungeon_save_walk_data(int surface, int map, struct page **page);
void dungeon_paint_step(int surface, int x, int y, int z);
void dungeon_set_chara_sprite(int surface, int num, int sprite);
void dungeon_set_chara_pos(int surface, int num, float x, float y, float z);
void dungeon_set_chara_cg(int surface, int num, int cg);
void dungeon_set_chara_cg_info(int surface, int num, int num_chara_x, int num_chara_y);
void dungeon_set_chara_show(int surface, int num, bool show);
struct dungeon_context *dungeon_get_context(int surface);
+2 -1
View File
@@ -32,6 +32,7 @@ void dungeon_map_set_all_view(int surface, int flag);
void dungeon_map_set_cg(int surface, int index, int sprite);
void dungeon_map_set_small_map_floor(int surface, int floor);
void dungeon_map_set_large_map_floor(int surface, int floor);
void dungeon_map_reveal(struct dungeon_context *ctx, int x, int y, int z, bool transparent);
void dungeon_map_reveal(struct dungeon_context *ctx, int x, int y, int z, bool from_walk_data);
void dungeon_map_hide(struct dungeon_context *ctx, int x, int y, int z);
#endif /* SYSTEM4_DUNGEON_MAP_H */
+13 -1
View File
@@ -26,14 +26,26 @@ struct dtx;
struct polyobj;
struct dungeon_renderer;
struct drawfield_character {
vec3 pos;
int sprite;
int rows;
int cols;
int cg_index;
bool show;
};
struct dungeon_renderer *dungeon_renderer_create(enum draw_dungeon_version version, int num, struct dtx *dtx, GLuint *event_textures, int nr_event_textures, struct polyobj *po);
void dungeon_renderer_free(struct dungeon_renderer *r);
void dungeon_renderer_render(struct dungeon_renderer *r, struct dgn_cell **cells, int nr_cells, mat4 view_transform, mat4 proj_transform);
void dungeon_renderer_render(struct dungeon_renderer *r, struct dgn_cell **cells, int nr_cells, struct drawfield_character *characters, mat4 view_transform, mat4 proj_transform);
void dungeon_renderer_enable_event_markers(struct dungeon_renderer *r, bool enable);
bool dungeon_renderer_event_markers_enabled(struct dungeon_renderer *r);
bool dungeon_renderer_is_floor_opaque(struct dungeon_renderer *r, struct dgn_cell *cell);
void dungeon_renderer_run_post_processing(struct dungeon_renderer *r, struct texture *src, struct texture *dst);
void dungeon_renderer_set_raster_scroll(struct dungeon_renderer *r, int type);
void dungeon_renderer_set_raster_amp(struct dungeon_renderer *r, float amp);
void dungeon_renderer_enable_lightmap(struct dungeon_renderer *r, bool enable);
bool dungeon_renderer_get_draw_obj_flag(struct dungeon_renderer *r, int type);
void dungeon_renderer_set_draw_obj_flag(struct dungeon_renderer *r, int type, bool flag);
#endif /* SYSTEM4_DUNGEON_RENDERER_H */
+11 -3
View File
@@ -18,6 +18,7 @@ uniform sampler2D tex;
uniform sampler2D light_texture;
uniform bool use_lightmap;
uniform float alpha_mod;
uniform bool use_fog;
in float dist;
in vec2 tex_coord;
@@ -32,7 +33,14 @@ void main() {
if (use_lightmap) {
light_factor = texture(light_texture, tex_coord).a;
}
float fog_factor = (FOG_MAX_DIST - dist) / FOG_MAX_DIST;
fog_factor = clamp(fog_factor, 0.3, 1.0);
frag_color = vec4(mix(FOG_COLOR, texel.rgb * light_factor, fog_factor), texel.a * alpha_mod);
if (use_fog) {
float fog_factor = (FOG_MAX_DIST - dist) / FOG_MAX_DIST;
fog_factor = clamp(fog_factor, 0.3, 1.0);
frag_color = vec4(mix(FOG_COLOR, texel.rgb * light_factor, fog_factor), texel.a * alpha_mod);
} else {
if (texel.a < 0.01) {
discard;
}
frag_color = vec4(texel.rgb * light_factor, texel.a * alpha_mod);
}
}
+3 -1
View File
@@ -17,6 +17,8 @@
uniform mat4 local_transform;
uniform mat4 view_transform;
uniform mat4 proj_transform;
uniform vec2 uv_offset;
uniform vec2 uv_scale;
in vec3 vertex_pos;
in vec2 vertex_uv;
@@ -27,5 +29,5 @@ void main() {
vec4 pos = view_transform * local_transform * vec4(vertex_pos, 1.0);
dist = abs(pos.z);
gl_Position = proj_transform * pos;
tex_coord = vertex_uv;
tex_coord = vertex_uv * uv_scale + uv_offset;
}
+91 -58
View File
@@ -24,7 +24,7 @@
#include "dungeon/mtrand43.h"
#include "vm.h"
struct dgn *dgn_parse(uint8_t *data, size_t size)
struct dgn *dgn_parse(uint8_t *data, size_t size, bool for_draw_field)
{
struct buffer r;
buffer_init(&r, data, size);
@@ -34,11 +34,6 @@ struct dgn *dgn_parse(uint8_t *data, size_t size)
struct dgn *dgn = xcalloc(1, sizeof(struct dgn));
dgn->version = buffer_read_int32(&r);
if (dgn->version != DGN_VER_RANCE6 && dgn->version != DGN_VER_GALZOO) {
WARNING("unknown DGN version: %d", dgn->version);
free(dgn);
return NULL;
}
dgn->size_x = buffer_read_int32(&r);
dgn->size_y = buffer_read_int32(&r);
dgn->size_z = buffer_read_int32(&r);
@@ -79,7 +74,7 @@ struct dgn *dgn_parse(uint8_t *data, size_t size)
cell->lightmap_south = buffer_read_int32(&r);
cell->lightmap_east = buffer_read_int32(&r);
cell->lightmap_west = buffer_read_int32(&r);
buffer_skip(&r, 7 * 4);
buffer_skip(&r, 7 * 4); // lightmap parameters for doors / stairs, 2 unknowns
cell->enterable = buffer_read_int32(&r);
cell->enterable_north = buffer_read_int32(&r);
cell->enterable_south = buffer_read_int32(&r);
@@ -95,64 +90,102 @@ struct dgn *dgn_parse(uint8_t *data, size_t size)
buffer_skip(&r, 4);
buffer_skip(&r, strlen(buffer_strdata(&r)) + 1);
}
buffer_skip(&r, 4);
cell->battle_background = buffer_read_int32(&r);
if (dgn->version != DGN_VER_GALZOO) {
cell->polyobj_index = -1;
cell->roof_orientation = -1;
cell->roof_texture = -1;
cell->roof_underside_texture = -1;
continue;
cell->polyobj_index = -1;
cell->roof_orientation = -1;
cell->roof_texture = -1;
cell->roof_underside_texture = -1;
if (for_draw_field) {
if (dgn->version >= 9) {
cell->north_door_lock = buffer_read_int32(&r);
cell->west_door_lock = buffer_read_int32(&r);
cell->south_door_lock = buffer_read_int32(&r);
cell->east_door_lock = buffer_read_int32(&r);
cell->north_door_angle = buffer_read_float(&r);
cell->west_door_angle = buffer_read_float(&r);
cell->south_door_angle = buffer_read_float(&r);
cell->east_door_angle = buffer_read_float(&r);
cell->walked = buffer_read_int32(&r);
}
if (dgn->version >= 11) {
cell->polyobj_index = buffer_read_int32(&r);
cell->polyobj_scale = buffer_read_float(&r);
cell->polyobj_rotation_y = buffer_read_float(&r);
cell->polyobj_rotation_z = buffer_read_float(&r);
cell->polyobj_rotation_x = buffer_read_float(&r);
cell->polyobj_position_x = buffer_read_float(&r);
cell->polyobj_position_y = buffer_read_float(&r);
cell->polyobj_position_z = buffer_read_float(&r);
}
} else {
buffer_skip(&r, 4); // unknown
cell->battle_background = buffer_read_int32(&r);
if (dgn->version != DGN_VER_GALZOO) {
continue;
}
cell->polyobj_index = buffer_read_int32(&r);
cell->polyobj_scale = buffer_read_float(&r);
cell->polyobj_rotation_y = buffer_read_float(&r);
cell->polyobj_rotation_z = buffer_read_float(&r);
cell->polyobj_rotation_x = buffer_read_float(&r);
cell->polyobj_position_x = buffer_read_float(&r);
cell->polyobj_position_y = buffer_read_float(&r);
cell->polyobj_position_z = buffer_read_float(&r);
cell->roof_orientation = buffer_read_int32(&r);
cell->roof_texture = buffer_read_int32(&r);
buffer_skip(&r, 4); // unknown
cell->roof_underside_texture = buffer_read_int32(&r);
buffer_skip(&r, 4); // unknown
}
cell->polyobj_index = buffer_read_int32(&r);
cell->polyobj_scale = buffer_read_float(&r);
cell->polyobj_rotation_y = buffer_read_float(&r);
cell->polyobj_rotation_z = buffer_read_float(&r);
cell->polyobj_rotation_x = buffer_read_float(&r);
cell->polyobj_position_x = buffer_read_float(&r);
cell->polyobj_position_y = buffer_read_float(&r);
cell->polyobj_position_z = buffer_read_float(&r);
cell->roof_orientation = buffer_read_int32(&r);
cell->roof_texture = buffer_read_int32(&r);
buffer_skip(&r, 4);
cell->roof_underside_texture = buffer_read_int32(&r);
buffer_skip(&r, 4);
}
if (buffer_read_u8(&r) != 0 || buffer_read_int32(&r) != 1) {
if (buffer_read_u8(&r) != 0) {
dgn_free(dgn);
return NULL;
}
dgn->pvs = xcalloc(nr_cells, sizeof(struct packed_pvs));
for (int i = 0; i < nr_cells; i++) {
struct packed_pvs *pvs = &dgn->pvs[i];
int32_t len = buffer_read_int32(&r);
if (len % 8 != 4) {
WARNING("dgn_parse: unexpected PVS length");
dgn_free(dgn);
return NULL;
}
if (buffer_read_int32(&r) != nr_cells) {
WARNING("dgn_parse: bad PVS");
dgn_free(dgn);
return NULL;
}
pvs->nr_run_lengths = (len - 4) / 8;
pvs->run_lengths = xmalloc(pvs->nr_run_lengths * sizeof(struct pvs_run_lengths));
int32_t total = 0;
for (int j = 0; j < pvs->nr_run_lengths; j++) {
int32_t invisible = buffer_read_int32(&r);
int32_t visible = buffer_read_int32(&r);
pvs->run_lengths[j].invisible_cells = invisible;
pvs->run_lengths[j].visible_cells = visible;
pvs->nr_visible_cells += visible;
total += invisible + visible;
}
if (total != nr_cells) {
WARNING("dgn_parse: bad PVS");
dgn_free(dgn);
return NULL;
int has_pvs = buffer_read_int32(&r);
if (has_pvs) {
dgn->pvs = xcalloc(nr_cells, sizeof(struct packed_pvs));
for (int i = 0; i < nr_cells; i++) {
struct packed_pvs *pvs = &dgn->pvs[i];
int32_t len = buffer_read_int32(&r);
if (len % 8 != 4) {
WARNING("dgn_parse: unexpected PVS length");
dgn_free(dgn);
return NULL;
}
if (buffer_read_int32(&r) != nr_cells) {
WARNING("dgn_parse: bad PVS");
dgn_free(dgn);
return NULL;
}
pvs->nr_run_lengths = (len - 4) / 8;
pvs->run_lengths = xmalloc(pvs->nr_run_lengths * sizeof(struct pvs_run_lengths));
int32_t total = 0;
for (int j = 0; j < pvs->nr_run_lengths; j++) {
int32_t invisible = buffer_read_int32(&r);
int32_t visible = buffer_read_int32(&r);
pvs->run_lengths[j].invisible_cells = invisible;
pvs->run_lengths[j].visible_cells = visible;
pvs->nr_visible_cells += visible;
total += invisible + visible;
}
if (total != nr_cells) {
WARNING("dgn_parse: bad PVS");
dgn_free(dgn);
return NULL;
}
}
}
dgn->sphere_theta[0] = buffer_read_float(&r);
dgn->sphere_theta[1] = buffer_read_float(&r);
dgn->sphere_theta[2] = buffer_read_float(&r);
dgn->sphere_color_top = buffer_read_float(&r);
dgn->sphere_color_bottom = buffer_read_float(&r);
buffer_skip(&r, 4); // unknown
if (for_draw_field && dgn->version >= 10) {
dgn->back_color_r = buffer_read_int32(&r);
dgn->back_color_g = buffer_read_int32(&r);
dgn->back_color_b = buffer_read_int32(&r);
}
return dgn;
}
+212 -39
View File
@@ -43,10 +43,6 @@
#include "vm/page.h"
#include "xsystem4.h"
#ifndef M_PI
#define M_PI (3.14159265358979323846)
#endif
static const char plugin_name[] = "DrawDungeon";
static void dungeon_render(struct sact_sprite *sp);
@@ -75,8 +71,13 @@ struct dungeon_context *dungeon_context_create(enum draw_dungeon_version version
glBindRenderbuffer(GL_RENDERBUFFER, ctx->depth_buffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glm_perspective(GLM_PIf / 3.f, (float)width / height, 0.5f, 100.f, ctx->proj_transform);
ctx->map = dungeon_map_create(version);
if (version == DRAW_FIELD) {
ctx->characters = xcalloc(DRAWFIELD_NR_CHARACTERS, sizeof(struct drawfield_character));
}
return ctx;
}
@@ -89,6 +90,8 @@ static void dungeon_context_free(struct draw_plugin *plugin)
dtx_free(ctx->dtx);
if (ctx->tes)
tes_free(ctx->tes);
if (ctx->characters)
free(ctx->characters);
if (ctx->renderer)
dungeon_renderer_free(ctx->renderer);
@@ -164,7 +167,7 @@ bool dungeon_load(struct dungeon_context *ctx, int num)
struct archive_data *dgn = archive_get(dlf, num * 3);
if (dgn) {
ctx->dgn = dgn_parse(dgn->data, dgn->size);
ctx->dgn = dgn_parse(dgn->data, dgn->size, false);
archive_free_data(dgn);
}
struct archive_data *dtx = archive_get(dlf, num * 3 + 1);
@@ -191,7 +194,7 @@ bool dungeon_load(struct dungeon_context *ctx, int num)
size_t len;
uint8_t *dgn = file_read(path, &len);
if (dgn) {
ctx->dgn = dgn_parse(dgn, len);
ctx->dgn = dgn_parse(dgn, len, false);
free(dgn);
}
@@ -242,6 +245,79 @@ bool dungeon_load(struct dungeon_context *ctx, int num)
return true;
}
static void dungeon_finalize_loading(struct dungeon_context *ctx)
{
ctx->renderer = dungeon_renderer_create(ctx->version, 0, ctx->dtx, NULL, 0, NULL);
dungeon_map_init(ctx);
ctx->loaded = true;
}
bool dungeon_load_dungeon(struct dungeon_context *ctx, const char *filename, int num)
{
char *path = gamedir_path(filename);
size_t len;
uint8_t *dgn = file_read(path, &len);
if (!dgn) {
WARNING("Cannot load %s", path);
free(path);
return false;
}
free(path);
if (ctx->dgn)
dgn_free(ctx->dgn);
ctx->dgn = dgn_parse(dgn, len, ctx->version == DRAW_FIELD);
free(dgn);
if (!ctx->dgn)
return false;
if (ctx->dgn && ctx->dtx) {
dungeon_finalize_loading(ctx);
}
return true;
}
bool dungeon_load_texture(struct dungeon_context *ctx, const char *filename)
{
// load .dtx
char *path = gamedir_path(filename);
size_t dtx_len;
uint8_t *dtx = file_read(path, &dtx_len);
if (!dtx) {
WARNING("Cannot load %s", path);
free(path);
return false;
}
if (ctx->dtx)
dtx_free(ctx->dtx);
ctx->dtx = dtx_parse(dtx, dtx_len);
free(dtx);
if (!ctx->dtx) {
free(path);
return false;
}
// load .tes
if (ctx->tes)
tes_free(ctx->tes);
ctx->tes = NULL;
size_t path_len = strlen(path);
if (path_len > 4 && path[path_len - 4] == '.') {
strcpy(path + path_len - 4, ".tes"); // .dtx -> .tes
size_t tes_len;
uint8_t *tes = file_read(path, &tes_len);
if (tes) {
ctx->tes = tes_parse(tes, tes_len);
free(tes);
}
}
if (ctx->dgn && ctx->dtx) {
dungeon_finalize_loading(ctx);
}
free(path);
return true;
}
void dungeon_set_camera(int surface, float x, float y, float z, float angle, float angle_p)
{
struct dungeon_context *ctx = dungeon_get_context(surface);
@@ -250,22 +326,59 @@ void dungeon_set_camera(int surface, float x, float y, float z, float angle, flo
ctx->camera.pos[0] = x;
ctx->camera.pos[1] = y;
ctx->camera.pos[2] = -z;
ctx->camera.angle = -angle * M_PI / 180;
ctx->camera.angle_p = angle_p * M_PI / 180;
ctx->camera.angle = -glm_rad(angle);
ctx->camera.angle_p = glm_rad(angle_p);
if (ctx->version != DRAW_FIELD) {
ctx->player_pos[0] = roundf(x / 2.f);
ctx->player_pos[1] = roundf(y / 2.f);
ctx->player_pos[2] = roundf(z / 2.f);
}
}
static void model_view_matrix(struct camera *camera, vec3 eye_out, mat4 mv_out)
void dungeon_set_perspective(int surface, int width, int height, float near, float far, float deg)
{
// The actual camera position is slightly behind camera->pos.
float dist = 0.9;
vec3 d = {
dist * sin(camera->angle) * cos(camera->angle_p),
dist * sin(camera->angle_p),
dist * -cos(camera->angle) * cos(camera->angle_p),
struct dungeon_context *ctx = dungeon_get_context(surface);
if (!ctx)
return;
float aspect = (float)width / height;
// XXX: Pastel Chime Continue sets unnecessarily small near (0.1) and large
// far (10000), which degrades depth buffer precision.
near = max(near, 0.4f);
far = min(far, 500.f);
glm_perspective(glm_rad(deg), aspect, near, far, ctx->proj_transform);
}
void dungeon_set_player_pos(int surface, int x, int y, int z)
{
struct dungeon_context *ctx = dungeon_get_context(surface);
if (!ctx)
return;
ctx->player_pos[0] = x;
ctx->player_pos[1] = y;
ctx->player_pos[2] = z;
}
static void model_view_matrix(struct dungeon_context *ctx, mat4 mv_out)
{
struct camera *camera = &ctx->camera;
float dist = 0.9f;
vec3 front = {
dist * sinf(camera->angle) * cosf(camera->angle_p),
dist * sinf(camera->angle_p),
dist * -cosf(camera->angle) * cosf(camera->angle_p),
};
glm_vec3_sub(camera->pos, d, eye_out);
vec3 up = {0.0, 1.0, 0.0};
glm_lookat(eye_out, camera->pos, up, mv_out);
if (ctx->version != DRAW_FIELD) {
// The actual camera position is slightly behind camera->pos.
vec3 eye;
glm_vec3_sub(camera->pos, front, eye);
glm_lookat(eye, camera->pos, GLM_YUP, mv_out);
} else {
vec3 target;
glm_vec3_add(camera->pos, front, target);
glm_lookat(camera->pos, target, GLM_YUP, mv_out);
}
}
static void dungeon_render(struct sact_sprite *sp)
@@ -279,23 +392,28 @@ static void dungeon_render(struct sact_sprite *sp)
if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
ERROR("Incomplete framebuffer");
glClearColor(0.f, 0.f, 0.f, 1.f);
glClearColor(ctx->dgn->back_color_r / 255.f, ctx->dgn->back_color_g / 255.f, ctx->dgn->back_color_b / 255.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.f, 0.f, 0.f, 1.f);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
vec3 eye;
mat4 local_transform, view_transform, proj_transform;
glm_mat4_identity(local_transform);
model_view_matrix(&ctx->camera, eye, view_transform);
glm_perspective(M_PI / 3.0, (float)ctx->texture.w / ctx->texture.h, 0.5, 100.0, proj_transform);
mat4 view_transform;
model_view_matrix(ctx, view_transform);
int dgn_x = round(eye[0] / 2.0);
int dgn_y = round(eye[1] / 2.0);
int dgn_z = round(eye[2] / -2.0);
int dgn_x, dgn_y, dgn_z;
if (ctx->version == DRAW_FIELD) {
dgn_x = 0;
dgn_y = ctx->dgn->size_y - 1;
dgn_z = 0;
} else {
dgn_x = ctx->player_pos[0];
dgn_y = ctx->player_pos[1];
dgn_z = ctx->player_pos[2];
}
int nr_cells;
struct dgn_cell **cells = dgn_get_visible_cells(ctx->dgn, dgn_x, dgn_y, dgn_z, &nr_cells);
dungeon_renderer_render(ctx->renderer, cells, nr_cells, view_transform, proj_transform);
dungeon_renderer_render(ctx->renderer, cells, nr_cells, ctx->characters, view_transform, ctx->proj_transform);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
@@ -323,6 +441,7 @@ static void neighbor_reveal(struct dungeon_context *ctx, int x, int y, int z)
}
break;
case DRAW_DUNGEON_14:
case DRAW_FIELD:
// do nothing
break;
}
@@ -333,16 +452,23 @@ void dungeon_set_walked(int surface, int x, int y, int z, int flag)
struct dungeon_context *ctx = dungeon_get_context(surface);
if (!ctx)
return;
dgn_cell_at(ctx->dgn, x, y, z)->walked = ctx->version == DRAW_DUNGEON_2 ? 3 : 1;
dungeon_map_reveal(ctx, x, y, z, false);
if (x > 0)
neighbor_reveal(ctx, x - 1, y, z);
if (x + 1u < ctx->dgn->size_x)
neighbor_reveal(ctx, x + 1, y, z);
if (z > 0)
neighbor_reveal(ctx, x, y, z - 1);
if (z + 1u < ctx->dgn->size_z)
neighbor_reveal(ctx, x, y, z + 1);
if (x < 0 || y < 0 || z < 0)
return; // avoid VM_ERROR in Pastel Chime Continue
if (flag) {
dgn_cell_at(ctx->dgn, x, y, z)->walked = ctx->version == DRAW_DUNGEON_2 ? 3 : 1;
dungeon_map_reveal(ctx, x, y, z, false);
if (x > 0)
neighbor_reveal(ctx, x - 1, y, z);
if (x + 1u < ctx->dgn->size_x)
neighbor_reveal(ctx, x + 1, y, z);
if (z > 0)
neighbor_reveal(ctx, x, y, z - 1);
if (z + 1u < ctx->dgn->size_z)
neighbor_reveal(ctx, x, y, z + 1);
} else {
dgn_cell_at(ctx->dgn, x, y, z)->walked = 0;
dungeon_map_hide(ctx, x, y, z);
}
}
void dungeon_set_walked_all(int surface)
@@ -482,7 +608,7 @@ static bool dd2_load_walk_data(struct dungeon_context *ctx, struct page **page)
for (struct dgn_cell *c = ctx->dgn->cells; c < ctx->dgn->cells + nr_cells; c++) {
c->walked = array->values[ptr++].i;
if (c->walked)
dungeon_map_reveal(ctx, c->x, c->y, c->z, false);
dungeon_map_reveal(ctx, c->x, c->y, c->z, true);
}
return true;
}
@@ -498,6 +624,8 @@ bool dungeon_load_walk_data(int surface, int map, struct page **page)
return dd1_load_walk_data(ctx, map, page);
case DRAW_DUNGEON_2:
return dd2_load_walk_data(ctx, page);
case DRAW_FIELD:
break; // DrawField does not export LoadWalkData
}
return false;
}
@@ -563,6 +691,8 @@ bool dungeon_save_walk_data(int surface, int map, struct page **page)
return dd1_save_walk_data(ctx, map, page);
case DRAW_DUNGEON_2:
return dd2_save_walk_data(ctx, page);
case DRAW_FIELD:
break; // DrawField does not export SaveWalkData
}
return false;
}
@@ -575,6 +705,49 @@ void dungeon_paint_step(int surface, int x, int y, int z)
dgn_paint_step(ctx->dgn, x, z);
}
void dungeon_set_chara_sprite(int surface, int num, int sprite)
{
struct dungeon_context *ctx = dungeon_get_context(surface);
if (!ctx || !ctx->characters || num < 0 || num >= DRAWFIELD_NR_CHARACTERS)
return;
ctx->characters[num].sprite = sprite;
}
void dungeon_set_chara_pos(int surface, int num, float x, float y, float z)
{
struct dungeon_context *ctx = dungeon_get_context(surface);
if (!ctx || !ctx->characters || num < 0 || num >= DRAWFIELD_NR_CHARACTERS)
return;
ctx->characters[num].pos[0] = x;
ctx->characters[num].pos[1] = y;
ctx->characters[num].pos[2] = -z;
}
void dungeon_set_chara_cg(int surface, int num, int cg)
{
struct dungeon_context *ctx = dungeon_get_context(surface);
if (!ctx || !ctx->characters || num < 0 || num >= DRAWFIELD_NR_CHARACTERS)
return;
ctx->characters[num].cg_index = cg;
}
void dungeon_set_chara_cg_info(int surface, int num, int num_chara_x, int num_chara_y)
{
struct dungeon_context *ctx = dungeon_get_context(surface);
if (!ctx || !ctx->characters || num < 0 || num >= DRAWFIELD_NR_CHARACTERS)
return;
ctx->characters[num].rows = num_chara_y;
ctx->characters[num].cols = num_chara_x;
}
void dungeon_set_chara_show(int surface, int num, bool show)
{
struct dungeon_context *ctx = dungeon_get_context(surface);
if (!ctx || !ctx->characters || num < 0 || num >= DRAWFIELD_NR_CHARACTERS)
return;
ctx->characters[num].show = show;
}
static cJSON *dungeon_to_json(struct sact_sprite *sp, bool verbose)
{
cJSON *obj, *cam;
+121 -42
View File
@@ -25,10 +25,6 @@
#include "sact.h"
#include "vm.h"
#ifndef M_PI
#define M_PI (3.14159265358979323846)
#endif
static const SDL_Color unenterable_cell_color = {182, 72, 0, 0};
enum dd1_symbol_type {
@@ -86,6 +82,7 @@ struct dungeon_map *dungeon_map_create(enum draw_dungeon_version version)
struct dungeon_map *map = xcalloc(1, sizeof(struct dungeon_map));
switch (version) {
case DRAW_DUNGEON_1:
case DRAW_FIELD:
map->grid_size = 12;
break;
case DRAW_DUNGEON_2:
@@ -120,35 +117,48 @@ void dungeon_map_init(struct dungeon_context *ctx)
int map_width;
int map_height;
if (ctx->version == DRAW_DUNGEON_1) {
// Calculate the bounding box on the XZ plane so that map is drawn in the
// center of the texture.
uint32_t min_x = dgn->size_x;
uint32_t min_y = dgn->size_z;
uint32_t max_x = 0;
uint32_t max_y = 0;
for (uint32_t y = 0; y < dgn->size_y; y++) {
for (uint32_t z = 0; z < dgn->size_z; z++) {
uint32_t map_y = ctx->dgn->size_z - z - 1;
for (uint32_t x = 0; x < dgn->size_x; x++) {
if (dgn_cell_at(ctx->dgn, x, y, z)->floor < 0)
continue;
min_x = min(min_x, x);
min_y = min(min_y, map_y);
max_x = max(max_x, x);
max_y = max(max_y, map_y);
switch (ctx->version) {
case DRAW_DUNGEON_1: {
// Calculate the bounding box on the XZ plane so that map is drawn in the
// center of the texture.
uint32_t min_x = dgn->size_x;
uint32_t min_y = dgn->size_z;
uint32_t max_x = 0;
uint32_t max_y = 0;
for (uint32_t y = 0; y < dgn->size_y; y++) {
for (uint32_t z = 0; z < dgn->size_z; z++) {
uint32_t map_y = ctx->dgn->size_z - z - 1;
for (uint32_t x = 0; x < dgn->size_x; x++) {
if (dgn_cell_at(ctx->dgn, x, y, z)->floor < 0)
continue;
min_x = min(min_x, x);
min_y = min(min_y, map_y);
max_x = max(max_x, x);
max_y = max(max_y, map_y);
}
}
}
map_width = 32;
map_height = 32;
map->offset_x = (map_width - (max_x - min_x + 1)) / 2 - min_x;
map->offset_y = (map_height - (max_y - min_y)) / 2 - min_y;
}
map_width = 32;
map_height = 32;
map->offset_x = (map_width - (max_x - min_x + 1)) / 2 - min_x;
map->offset_y = (map_height - (max_y - min_y)) / 2 - min_y;
} else {
break;
case DRAW_DUNGEON_2:
map_width = 19;
map_height = 19;
map->offset_x = 0;
map->offset_y = 1;
break;
case DRAW_DUNGEON_14:
ERROR("cannot happen");
break;
case DRAW_FIELD:
map_width = dgn->size_x;
map_height = dgn->size_z;
map->offset_x = 0;
map->offset_y = 0;
break;
}
// Initial draw
for (uint32_t y = 0; y < dgn->size_y; y++) {
@@ -164,16 +174,18 @@ void dungeon_map_init(struct dungeon_context *ctx)
}
}
void dungeon_map_reveal(struct dungeon_context *ctx, int x, int y, int z, bool transparent)
void dungeon_map_reveal(struct dungeon_context *ctx, int x, int y, int z, bool from_walk_data)
{
if (!ctx->map)
return;
struct texture *dst = &ctx->map->textures[y];
struct dgn_cell *cell = dgn_cell_at(ctx->dgn, x, y, z);
Point pos = texture_pos(ctx, x, z);
int alpha;
switch (ctx->version) {
case DRAW_DUNGEON_1:
gfx_fill_amap(dst, pos.x, pos.y, ctx->map->grid_size, ctx->map->grid_size, transparent ? 128 : 255);
alpha = from_walk_data ? 128 : 255;
gfx_fill_amap(dst, pos.x, pos.y, ctx->map->grid_size, ctx->map->grid_size, alpha);
break;
case DRAW_DUNGEON_2:
if ((x == ctx->dgn->start_x && z == ctx->dgn->start_y) || cell->floor_event == 17) {
@@ -184,11 +196,23 @@ void dungeon_map_reveal(struct dungeon_context *ctx, int x, int y, int z, bool t
gfx_fill_with_alpha(dst, pos.x, pos.y, ctx->map->grid_size, ctx->map->grid_size, rg, rg, 0, 255);
}
break;
case DRAW_FIELD:
alpha = cell->floor == -1 ? 160 : 255;
gfx_fill_amap(dst, pos.x, pos.y, ctx->map->grid_size, ctx->map->grid_size, alpha);
default:
break;
}
}
void dungeon_map_hide(struct dungeon_context *ctx, int x, int y, int z)
{
if (!ctx->map)
return;
struct texture *dst = &ctx->map->textures[y];
Point pos = texture_pos(ctx, x, z);
gfx_fill_amap(dst, pos.x, pos.y, ctx->map->grid_size, ctx->map->grid_size, 0);
}
static void draw_hline(struct texture *dst, int x, int y, int w, SDL_Color col)
{
gfx_fill(dst, x, y, w, 1, col.r, col.g, col.b);
@@ -298,6 +322,60 @@ static void dd2_update_cell(struct dungeon_context *ctx, int dgn_x, int dgn_y, i
}
}
static void df_update_cell(struct dungeon_context *ctx, int dgn_x, int dgn_y, int dgn_z)
{
if (!ctx->map)
return;
struct dgn_cell *cell = dgn_cell_at(ctx->dgn, dgn_x, dgn_y, dgn_z);
struct texture *dst = &ctx->map->textures[dgn_y];
Point pos = texture_pos(ctx, dgn_x, dgn_z);
int x = pos.x;
int y = pos.y;
const int CS = ctx->map->grid_size;
if (cell->floor >= 0)
gfx_fill(dst, x, y, CS, CS, 128, 64, 32);
else
gfx_fill(dst, x, y, CS, CS, 0, 0, 0);
const SDL_Color wall_color = {255, 255, 255, 255};
if (cell->north_wall >= 0)
draw_hline(dst, x, y, CS, wall_color);
if (cell->south_wall >= 0)
draw_hline(dst, x, y + CS - 1, CS, wall_color);
if (cell->west_wall >= 0)
draw_vline(dst, x, y, CS, wall_color);
if (cell->east_wall >= 0)
draw_vline(dst, x + CS - 1, y, CS, wall_color);
const SDL_Color door_colors[2] = {{0, 255, 0, 255}, {255, 0, 0, 255}};
if (cell->north_door >= 0) {
draw_hline(dst, x, y, CS / 2 - 1, door_colors[cell->north_door_lock]);
draw_hline(dst, x + CS / 2 - 1, y, 2, COLOR(0, 0, 0, 0));
draw_hline(dst, x + CS / 2 + 1, y, CS / 2 - 1, door_colors[cell->north_door_lock]);
}
if (cell->south_door >= 0) {
draw_hline(dst, x, y + CS - 1, CS / 2 - 1, door_colors[cell->south_door_lock]);
draw_hline(dst, x + CS / 2 - 1, y + CS - 1, 2, COLOR(0, 0, 0, 0));
draw_hline(dst, x + CS / 2 + 1, y + CS - 1, CS / 2 - 1, door_colors[cell->south_door_lock]);
}
if (cell->west_door >= 0) {
draw_vline(dst, x, y, CS / 2 - 1, door_colors[cell->west_door_lock]);
draw_vline(dst, x, y + CS / 2 - 1, 2, COLOR(0, 0, 0, 0));
draw_vline(dst, x, y + CS / 2 + 1, CS / 2 - 1, door_colors[cell->west_door_lock]);
}
if (cell->east_door >= 0) {
draw_vline(dst, x + CS - 1, y, CS / 2 - 1, door_colors[cell->east_door_lock]);
draw_vline(dst, x + CS - 1, y + CS / 2 - 1, 2, COLOR(0, 0, 0, 0));
draw_vline(dst, x + CS - 1, y + CS / 2 + 1, CS / 2 - 1, door_colors[cell->east_door_lock]);
}
if (cell->stairs_texture >= 0)
gfx_fill(dst, x + 2, y + 2, CS - 4, CS - 4, 0, 255, 255);
else if (dgn_y && dgn_cell_at(ctx->dgn, dgn_x, dgn_y - 1, dgn_z)->stairs_texture >= 0)
gfx_fill(dst, x + 2, y + 2, CS - 4, CS - 4, 0, 0, 255);
}
void dungeon_map_update_cell(struct dungeon_context *ctx, int dgn_x, int dgn_y, int dgn_z)
{
switch (ctx->version) {
@@ -310,6 +388,8 @@ void dungeon_map_update_cell(struct dungeon_context *ctx, int dgn_x, int dgn_y,
case DRAW_DUNGEON_14:
// unused
break;
case DRAW_FIELD:
df_update_cell(ctx, dgn_x, dgn_y, dgn_z);
}
}
@@ -328,7 +408,7 @@ static int player_symbol(struct dungeon_context *ctx)
DD2_SYMBOL_PLAYER_WEST,
};
const int *symbols = ctx->version == DRAW_DUNGEON_1 ? dd1_symbols : dd2_symbols;
return symbols[(int)(round(ctx->camera.angle * 2 / M_PI)) & 3];
return symbols[(int)(roundf(ctx->camera.angle * 2 / GLM_PIf)) & 3];
}
void dungeon_map_draw(int surface, int sprite)
@@ -349,17 +429,14 @@ void dungeon_map_draw(int surface, int sprite)
sprite_dirty(sp);
struct texture *dst = sprite_get_texture(sp);
int player_x = round(ctx->camera.pos[0] / 2.0);
int player_y = round(ctx->camera.pos[1] / 2.0);
int player_z = round(ctx->camera.pos[2] / -2.0);
int level = ctx->map->small_map_floor;
if (level < 0)
level = player_y;
level = ctx->player_pos[1];
struct texture *src = &ctx->map->textures[level];
const int CS = ctx->map->grid_size;
Point pos = texture_pos(ctx, player_x, player_z);
Point pos = texture_pos(ctx, ctx->player_pos[0], ctx->player_pos[2]);
int x = pos.x - (dst->w - CS) / 2;
int y = pos.y - (dst->h - CS) / 2;
@@ -385,12 +462,9 @@ void dungeon_map_draw_lmap(int surface, int sprite)
sprite_dirty(sp);
struct texture *dst = sprite_get_texture(sp);
int player_x = round(ctx->camera.pos[0] / 2.0);
int player_y = round(ctx->camera.pos[1] / 2.0);
int player_z = round(ctx->camera.pos[2] / -2.0);
int level = ctx->map->large_map_floor;
if (level < 0)
level = player_y;
level = ctx->player_pos[1];
struct texture *src = &ctx->map->textures[level];
gfx_copy_with_alpha_map(dst, 0, 0, src, 0, 0, src->w, src->h);
@@ -399,10 +473,15 @@ void dungeon_map_draw_lmap(int surface, int sprite)
gfx_fill_amap(dst, 0, 0, dst->w, dst->h, 255);
// Draw the player symbol.
Point pos = texture_pos(ctx, player_x, player_z);
draw_symbol(ctx->map, dst, pos.x + 1, pos.y + 1, player_symbol(ctx));
int size = ctx->map->grid_size - 2;
gfx_fill_amap(dst, pos.x + 1, pos.y + 1, size, size, level == player_y ? 255 : 128);
Point pos = texture_pos(ctx, ctx->player_pos[0], ctx->player_pos[2]);
if (ctx->version == DRAW_FIELD) {
int ofs = (ctx->map->grid_size - 4) / 2;
gfx_fill(dst, pos.x + ofs, pos.y + ofs, 4, 4, 255, 192, 255);
} else {
draw_symbol(ctx->map, dst, pos.x + 1, pos.y + 1, player_symbol(ctx));
int size = ctx->map->grid_size - 2;
gfx_fill_amap(dst, pos.x + 1, pos.y + 1, size, size, level == ctx->player_pos[1] ? 255 : 128);
}
}
static void redraw_event_symbols(struct dungeon_context *ctx)
+169 -29
View File
@@ -30,6 +30,7 @@
#include "dungeon/renderer.h"
#include "dungeon/skybox.h"
#include "gfx/gfx.h"
#include "sact.h"
enum {
COLOR_TEXTURE_UNIT,
@@ -55,6 +56,10 @@ enum floor_marker {
GZ_MAGIC_CIRCLE = 0,
};
static const struct marker_info empty_marker_info[] = {
{0},
};
static const struct marker_info rance6_marker_info[] = {
{ 11, 41, 3, R6_MAGIC_CIRCLE}, // treasure chest
{ 12, 51, 7, R6_RED_OCTAGRAM}, // enemy
@@ -92,7 +97,8 @@ static const struct marker_info galzoo_marker_info[] = {
static const struct marker_info *marker_tables[] = {
[DRAW_DUNGEON_1] = rance6_marker_info,
[DRAW_DUNGEON_2] = dolls_marker_info,
[DRAW_DUNGEON_14] = galzoo_marker_info
[DRAW_DUNGEON_14] = galzoo_marker_info,
[DRAW_FIELD] = empty_marker_info
};
struct geometry;
@@ -106,6 +112,7 @@ struct raster_shader {
};
struct dungeon_renderer {
enum draw_dungeon_version version;
struct shader shader;
// Uniform variable locations
GLint local_transform;
@@ -113,6 +120,9 @@ struct dungeon_renderer {
GLint alpha_mod;
GLint use_lightmap;
GLint light_texture;
GLint use_fog;
GLint uv_offset;
GLint uv_scale;
struct geometry *wall_geometry;
struct geometry *door_left_geometry;
@@ -140,6 +150,19 @@ struct dungeon_renderer {
struct raster_shader raster_shader;
bool raster_scroll;
float raster_amp;
bool enable_lightmap;
uint32_t draw_obj_flags;
};
enum draw_obj_flag_index {
DRAW_POLYOBJ = 0,
DRAW_FLOOR = 1,
DRAW_WALL = 2,
DRAW_DOOR = 3,
DRAW_CEILING = 4,
DRAW_STAIRS = 5,
NR_DRAW_OBJ_FLAGS
};
static const struct marker_info *get_marker_info(struct dungeon_renderer *r, int event_type)
@@ -389,13 +412,21 @@ static bool is_dolls_boss_floor(int num)
struct dungeon_renderer *dungeon_renderer_create(enum draw_dungeon_version version, int num, struct dtx *dtx, GLuint *event_textures, int nr_event_textures, struct polyobj *po)
{
struct dungeon_renderer *r = xcalloc(1, sizeof(struct dungeon_renderer));
r->version = version;
gfx_load_shader(&r->shader, "shaders/dungeon.v.glsl", "shaders/dungeon.f.glsl");
r->local_transform = glGetUniformLocation(r->shader.program, "local_transform");
r->proj_transform = glGetUniformLocation(r->shader.program, "proj_transform");
r->alpha_mod = glGetUniformLocation(r->shader.program, "alpha_mod");
r->use_lightmap = glGetUniformLocation(r->shader.program, "use_lightmap");
r->light_texture = glGetUniformLocation(r->shader.program, "light_texture");
r->use_fog = glGetUniformLocation(r->shader.program, "use_fog");
r->uv_offset = glGetUniformLocation(r->shader.program, "uv_offset");
r->uv_scale = glGetUniformLocation(r->shader.program, "uv_scale");
glUseProgram(r->shader.program);
glUniform1i(r->use_fog, version != DRAW_FIELD);
glUniform2f(r->uv_offset, 0.0f, 0.0f);
glUniform2f(r->uv_scale, 1.0f, 1.0f);
glUseProgram(0);
r->wall_geometry = geometry_create(r, wall_vertices, sizeof(wall_vertices), GL_TRIANGLE_STRIP);
r->door_left_geometry = geometry_create(r, door_left_vertices, sizeof(door_left_vertices), GL_TRIANGLE_STRIP);
@@ -433,6 +464,8 @@ struct dungeon_renderer *dungeon_renderer_create(enum draw_dungeon_version versi
r->skybox = skybox_create(version, dtx);
r->enable_lightmap = true;
r->draw_obj_flags = (1 << NR_DRAW_OBJ_FLAGS) - 1;
return r;
}
@@ -470,7 +503,8 @@ void dungeon_renderer_free(struct dungeon_renderer *r)
static void set_lightmap_texture(struct dungeon_renderer *r, int texture_index)
{
struct material *material = texture_index >= 0 ? get_material(r, DTX_LIGHTMAP, texture_index) : NULL;
struct material *material = (r->enable_lightmap && texture_index >= 0)
? get_material(r, DTX_LIGHTMAP, texture_index) : NULL;
glUniform1i(r->use_lightmap, !!material);
if (material) {
glActiveTexture(GL_TEXTURE0 + LIGHT_TEXTURE_UNIT);
@@ -504,13 +538,13 @@ static void draw_door(struct dungeon_renderer *r, GLuint texture, float angle, m
glm_mat4_copy(transform, m);
m[3][0] += dx;
m[3][2] += dz;
glm_rotate_y(m, angle * (M_PI/180), m);
glm_rotate_y(m, glm_rad(angle), m);
draw(r, r->door_left_geometry, texture, m);
glm_mat4_copy(transform, m);
m[3][0] -= dx;
m[3][2] -= dz;
glm_rotate_y(m, angle * -(M_PI/180), m);
glm_rotate_y(m, -glm_rad(angle), m);
draw(r, r->door_right_geometry, texture, m);
}
@@ -551,7 +585,7 @@ static void draw_floating_marker(struct dungeon_renderer *r, const struct marker
glm_mat4_pick3t(view_mat, r);
glm_mat4_ins3(r, m);
} else {
float angle = t / -(M_PI * 100.0);
float angle = t / -(GLM_PIf * 100.f);
glm_rotate_y(m, angle, m);
}
@@ -594,7 +628,7 @@ static void draw_cell(struct dungeon_renderer *r, struct dgn_cell *cell, bool re
float y = 2.0 * cell->y;
float z = -2.0 * cell->z;
if (cell->floor >= 0) {
if (cell->floor >= 0 && r->draw_obj_flags & (1 << DRAW_FLOOR)) {
struct material *material = get_material(r, DTX_FLOOR, cell->floor);
if (material && material->opaque == render_opaque) {
mat4 m = MAT4(
@@ -607,20 +641,32 @@ static void draw_cell(struct dungeon_renderer *r, struct dgn_cell *cell, bool re
set_lightmap_texture(r, -1);
}
}
if (cell->ceiling >= 0) {
if (cell->ceiling >= 0 && r->draw_obj_flags & (1 << DRAW_CEILING)) {
struct material *material = get_material(r, DTX_CEILING, cell->ceiling);
if (material && material->opaque == render_opaque) {
mat4 m = MAT4(
-1, 0, 0, x,
0, 0, -1, y+1,
0, -1, 0, z,
0, 0, 0, 1);
set_lightmap_texture(r, cell->lightmap_ceiling);
draw(r, r->wall_geometry, material->texture, m);
set_lightmap_texture(r, -1);
if (r->version == DRAW_FIELD) {
// Draw as a billboard.
mat4 m;
vec3 pos = {x, y, z};
glm_translate_make(m, pos);
mat3 r_bill;
glm_mat4_pick3t(view_transform, r_bill);
glm_mat4_ins3(r_bill, m);
glm_scale_uni(m, 1.7f);
draw(r, r->wall_geometry, material->texture, m);
} else {
mat4 m = MAT4(
-1, 0, 0, x,
0, 0, -1, y+1,
0, -1, 0, z,
0, 0, 0, 1);
set_lightmap_texture(r, cell->lightmap_ceiling);
draw(r, r->wall_geometry, material->texture, m);
set_lightmap_texture(r, -1);
}
}
}
if (cell->north_wall >= 0) {
if (cell->north_wall >= 0 && r->draw_obj_flags & (1 << DRAW_WALL)) {
struct material *material = get_material(r, DTX_WALL, cell->north_wall);
if (material && material->opaque == render_opaque) {
mat4 m = MAT4(
@@ -633,7 +679,7 @@ static void draw_cell(struct dungeon_renderer *r, struct dgn_cell *cell, bool re
set_lightmap_texture(r, -1);
}
}
if (cell->south_wall >= 0) {
if (cell->south_wall >= 0 && r->draw_obj_flags & (1 << DRAW_WALL)) {
struct material *material = get_material(r, DTX_WALL, cell->south_wall);
if (material && material->opaque == render_opaque) {
mat4 m = MAT4(
@@ -646,7 +692,7 @@ static void draw_cell(struct dungeon_renderer *r, struct dgn_cell *cell, bool re
set_lightmap_texture(r, -1);
}
}
if (cell->east_wall >= 0) {
if (cell->east_wall >= 0 && r->draw_obj_flags & (1 << DRAW_WALL)) {
struct material *material = get_material(r, DTX_WALL, cell->east_wall);
if (material && material->opaque == render_opaque) {
mat4 m = MAT4(
@@ -659,7 +705,7 @@ static void draw_cell(struct dungeon_renderer *r, struct dgn_cell *cell, bool re
set_lightmap_texture(r, -1);
}
}
if (cell->west_wall >= 0) {
if (cell->west_wall >= 0 && r->draw_obj_flags & (1 << DRAW_WALL)) {
struct material *material = get_material(r, DTX_WALL, cell->west_wall);
if (material && material->opaque == render_opaque) {
mat4 m = MAT4(
@@ -672,7 +718,7 @@ static void draw_cell(struct dungeon_renderer *r, struct dgn_cell *cell, bool re
set_lightmap_texture(r, -1);
}
}
if (cell->north_door >= 0) {
if (cell->north_door >= 0 && r->draw_obj_flags & (1 << DRAW_DOOR)) {
struct material *material = get_material(r, DTX_DOOR, cell->north_door);
if (material && material->opaque == render_opaque) {
mat4 m = MAT4(
@@ -683,7 +729,7 @@ static void draw_cell(struct dungeon_renderer *r, struct dgn_cell *cell, bool re
draw_door(r, material->texture, cell->north_door_angle, m, -1, 0);
}
}
if (cell->south_door >= 0) {
if (cell->south_door >= 0 && r->draw_obj_flags & (1 << DRAW_DOOR)) {
struct material *material = get_material(r, DTX_DOOR, cell->south_door);
if (material && material->opaque == render_opaque) {
mat4 m = MAT4(
@@ -694,7 +740,7 @@ static void draw_cell(struct dungeon_renderer *r, struct dgn_cell *cell, bool re
draw_door(r, material->texture, cell->south_door_angle, m, 1, 0);
}
}
if (cell->east_door >= 0) {
if (cell->east_door >= 0 && r->draw_obj_flags & (1 << DRAW_DOOR)) {
struct material *material = get_material(r, DTX_DOOR, cell->east_door);
if (material && material->opaque == render_opaque) {
mat4 m = MAT4(
@@ -705,7 +751,7 @@ static void draw_cell(struct dungeon_renderer *r, struct dgn_cell *cell, bool re
draw_door(r, material->texture, cell->east_door_angle, m, 0, -1);
}
}
if (cell->west_door >= 0) {
if (cell->west_door >= 0 && r->draw_obj_flags & (1 << DRAW_DOOR)) {
struct material *material = get_material(r, DTX_DOOR, cell->west_door);
if (material && material->opaque == render_opaque) {
mat4 m = MAT4(
@@ -716,7 +762,7 @@ static void draw_cell(struct dungeon_renderer *r, struct dgn_cell *cell, bool re
draw_door(r, material->texture, cell->west_door_angle, m, 0, 1);
}
}
if (cell->stairs_texture >= 0) {
if (cell->stairs_texture >= 0 && r->draw_obj_flags & (1 << DRAW_STAIRS)) {
struct material *material = get_material(r, DTX_STAIRS, cell->stairs_texture);
if (material && material->opaque == render_opaque) {
mat4 m;
@@ -744,7 +790,7 @@ static void draw_cell(struct dungeon_renderer *r, struct dgn_cell *cell, bool re
glCullFace(GL_BACK);
}
}
if (cell->polyobj_index >= 0) {
if (cell->polyobj_index >= 0 && r->draw_obj_flags & (1 << DRAW_POLYOBJ)) {
vec3 pos = {
x + cell->polyobj_position_x,
y + cell->polyobj_position_y - 1,
@@ -762,7 +808,75 @@ static void draw_cell(struct dungeon_renderer *r, struct dgn_cell *cell, bool re
}
}
void dungeon_renderer_render(struct dungeon_renderer *r, struct dgn_cell **cells, int nr_cells, mat4 view_transform, mat4 proj_transform)
static void draw_character(struct dungeon_renderer *r, struct drawfield_character *chara, mat4 view_mat)
{
if (!chara->show || chara->sprite <= 0)
return;
struct sact_sprite *sp = sact_try_get_sprite(chara->sprite);
if (!sp || !sp->texture.handle)
return;
if (chara->cols == 0) chara->cols = 1;
if (chara->rows == 0) chara->rows = 1;
glUseProgram(r->shader.program);
glUniform2f(r->uv_offset, (float)(chara->cg_index % chara->cols) / chara->cols, (float)(chara->cg_index / chara->cols) / chara->rows);
glUniform2f(r->uv_scale, 1.0f / chara->cols, 1.0f / chara->rows);
mat4 m;
glm_translate_make(m, chara->pos);
// Make it a billboard of 2.0 x 2.0
mat3 r_bill;
glm_mat4_pick3t(view_mat, r_bill);
glm_mat4_ins3(r_bill, m);
draw(r, r->wall_geometry, sp->texture.handle, m);
}
struct character_z {
struct drawfield_character *chara;
float z;
};
static int compare_character_z(const void *a, const void *b)
{
const struct character_z *cha = a;
const struct character_z *chb = b;
if (cha->z < chb->z)
return -1;
if (cha->z > chb->z)
return 1;
return 0;
}
static void draw_characters(struct dungeon_renderer *r, struct drawfield_character *characters, mat4 view_transform)
{
if (!characters)
return;
struct character_z sorted_characters[DRAWFIELD_NR_CHARACTERS];
int n = 0;
for (int i = 0; i < DRAWFIELD_NR_CHARACTERS; i++) {
struct drawfield_character *chara = characters + i;
if (!chara->show || chara->sprite <= 0)
continue;
sorted_characters[n].chara = chara;
vec4 pos;
glm_mat4_mulv(view_transform, (vec4){chara->pos[0], chara->pos[1], chara->pos[2], 1}, pos);
sorted_characters[n].z = pos[2];
n++;
}
qsort(sorted_characters, n, sizeof(struct character_z), compare_character_z);
for (int i = 0; i < n; i++)
draw_character(r, sorted_characters[i].chara, view_transform);
glUniform2f(r->uv_offset, 0.0f, 0.0f);
glUniform2f(r->uv_scale, 1.0f, 1.0f);
}
void dungeon_renderer_render(struct dungeon_renderer *r, struct dgn_cell **cells, int nr_cells, struct drawfield_character *characters, mat4 view_transform, mat4 proj_transform)
{
glUseProgram(r->shader.program);
glUniformMatrix4fv(r->shader.view_transform, 1, GL_FALSE, view_transform[0]);
@@ -777,11 +891,15 @@ void dungeon_renderer_render(struct dungeon_renderer *r, struct dgn_cell **cells
// Render the skybox.
skybox_render(r->skybox, view_transform, proj_transform);
glUseProgram(r->shader.program);
// Render transparent objects, from far to near.
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// DrawField: draw characters.
draw_characters(r, characters, view_transform);
// Render transparent objects, from far to near.
for (int i = nr_cells - 1; i >= 0; i--)
draw_cell(r, cells[i], false, view_transform);
@@ -865,3 +983,25 @@ void dungeon_renderer_set_raster_amp(struct dungeon_renderer *r, float amp)
{
r->raster_amp = amp;
}
void dungeon_renderer_enable_lightmap(struct dungeon_renderer *r, bool enable)
{
r->enable_lightmap = enable;
}
bool dungeon_renderer_get_draw_obj_flag(struct dungeon_renderer *r, int type)
{
if (type < 0 || type >= NR_DRAW_OBJ_FLAGS)
return false;
return r->draw_obj_flags & (1 << type);
}
void dungeon_renderer_set_draw_obj_flag(struct dungeon_renderer *r, int type, bool flag)
{
if (type < 0 || type >= NR_DRAW_OBJ_FLAGS)
return;
if (flag)
r->draw_obj_flags |= (1 << type);
else
r->draw_obj_flags &= ~(1 << type);
}
+2 -2
View File
@@ -36,8 +36,8 @@ struct skybox {
struct skybox *skybox_create(enum draw_dungeon_version version, struct dtx *dtx)
{
if (version == DRAW_DUNGEON_2) {
// Skybox is not used in Dungeons & Dolls.
if (version == DRAW_DUNGEON_2 || version == DRAW_FIELD) {
// Skybox is not used in these games.
return NULL;
};
+2
View File
@@ -436,6 +436,7 @@ extern struct static_library lib_DrawDungeon;
extern struct static_library lib_DrawDungeon2;
extern struct static_library lib_DrawDungeon14;
extern struct static_library lib_DrawEffect;
extern struct static_library lib_DrawField;
extern struct static_library lib_DrawGraph;
extern struct static_library lib_DrawMovie;
extern struct static_library lib_DrawMovie2;
@@ -549,6 +550,7 @@ static struct static_library *static_libraries[] = {
&lib_DrawDungeon2,
&lib_DrawDungeon14,
&lib_DrawEffect,
&lib_DrawField,
&lib_DrawGraph,
&lib_DrawMovie,
&lib_DrawMovie2,
+442 -4
View File
@@ -17,8 +17,10 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <math.h>
#include "system4.h"
#include "system4/string.h"
#include "dungeon/dgn.h"
#include "dungeon/dungeon.h"
@@ -62,6 +64,11 @@ static int DrawDungeon14_Init(int surface)
return dungeon_init(DRAW_DUNGEON_14, surface);
}
static int DrawField_Init(int surface)
{
return dungeon_init(DRAW_FIELD, surface);
}
static void DrawDungeon_Release(int surface)
{
if (!dungeon_get_context(surface))
@@ -77,6 +84,14 @@ static void DrawDungeon_SetDrawFlag(int surface, int flag)
ctx->draw_enabled = flag;
}
static bool DrawDungeon_GetDrawFlag(int surface)
{
struct dungeon_context *ctx = dungeon_get_context(surface);
if (!ctx)
return false;
return ctx->draw_enabled;
}
static bool DrawDungeon_BeginLoad(int surface, int num)
{
struct dungeon_context *ctx = dungeon_get_context(surface);
@@ -99,8 +114,23 @@ static bool DrawDungeon_IsSucceededLoading(int surface)
}
//float DrawDungeon_GetLoadingPercent(int surface);
//int DrawDungeon_LoadFromFile(int surface, struct string *file_name, int num);
//int DrawDungeon_LoadTexture(int surface, struct string *file_name);
static int DrawDungeon_LoadFromFile(int surface, struct string *file_name, int num)
{
struct dungeon_context *ctx = dungeon_get_context(surface);
if (!ctx)
return false;
return dungeon_load_dungeon(ctx, file_name->text, num);
}
static int DrawDungeon_LoadTexture(int surface, struct string *file_name)
{
struct dungeon_context *ctx = dungeon_get_context(surface);
if (!ctx)
return false;
return dungeon_load_texture(ctx, file_name->text);
}
//int DrawDungeon_LoadEventTexture(int surface, struct string *file_name);
static int DrawDungeon_GetMapX(int surface)
@@ -248,6 +278,7 @@ HLL_QUIET_UNIMPLEMENTED(0, int, DrawDungeon, GetDrawHalfFlag, int surface);
//int DrawDungeon_CalcNumofWalk2(int surface);
HLL_QUIET_UNIMPLEMENTED( , void, DrawDungeon, SetInterlaceMode, int surface, int flag);
HLL_QUIET_UNIMPLEMENTED(1, bool, DrawDungeon, SetDirect3DMode, int surface, int flag);
HLL_QUIET_UNIMPLEMENTED(1, bool, DrawDungeon, GetDirect3DMode, int surface);
HLL_QUIET_UNIMPLEMENTED( , void, DrawDungeon, SaveDrawSettingFlag, int direct3D, int interlace, int half);
HLL_QUIET_UNIMPLEMENTED( , void, DrawDungeon, GetDrawSettingFlag, int *direct3D, int *half);
HLL_QUIET_UNIMPLEMENTED(1, bool, DrawDungeon, IsDrawSettingFile, void);
@@ -278,8 +309,8 @@ HLL_QUIET_UNIMPLEMENTED( , void, DrawDungeon, RestartTimer, void);
HLL_EXPORT(IsLoading, DrawDungeon_IsLoading), \
HLL_EXPORT(IsSucceededLoading, DrawDungeon_IsSucceededLoading), \
HLL_TODO_EXPORT(GetLoadingPercent, DrawDungeon_GetLoadingPercent), \
HLL_TODO_EXPORT(LoadFromFile, DrawDungeon_LoadFromFile), \
HLL_TODO_EXPORT(LoadTexture, DrawDungeon_LoadTexture), \
HLL_EXPORT(LoadFromFile, DrawDungeon_LoadFromFile), \
HLL_EXPORT(LoadTexture, DrawDungeon_LoadTexture), \
HLL_TODO_EXPORT(LoadEventTexture, DrawDungeon_LoadEventTexture), \
HLL_EXPORT(GetMapX, DrawDungeon_GetMapX), \
HLL_EXPORT(GetMapY, DrawDungeon_GetMapY), \
@@ -469,3 +500,410 @@ HLL_LIBRARY(DrawDungeon14,
HLL_EXPORT(GetDrawMapObjectFlag, DrawDungeon14_GetDrawMapObjectFlag),
HLL_EXPORT(SetDrawMapObjectFlag, DrawDungeon14_SetDrawMapObjectFlag)
);
//bool DrawField_BeginLoad(int nSurface, struct string *szFileName, int nNum);
//bool DrawField_IsLoadEnd(int nSurface);
//bool DrawField_StopLoad(int nSurface);
//float DrawField_GetLoadPercent(int nSurface);
//bool DrawField_IsLoadSucceeded(int nSurface);
//bool DrawField_BeginLoadTexture(int nSurface, struct string *szFileName);
//bool DrawField_IsLoadTextureEnd(int nSurface);
//bool DrawField_StopLoadTexture(int nSurface);
//float DrawField_GetLoadTexturePercent(int nSurface);
//bool DrawField_IsLoadTextureSucceeded(int nSurface);
//void DrawField_UpdateTexture(int nSurface);
//bool DrawField_GetDoorNAngle(int nSurface, int nX, int nY, int nZ, float *pfAngle);
//bool DrawField_GetDoorWAngle(int nSurface, int nX, int nY, int nZ, float *pfAngle);
//bool DrawField_GetDoorSAngle(int nSurface, int nX, int nY, int nZ, float *pfAngle);
//bool DrawField_GetDoorEAngle(int nSurface, int nX, int nY, int nZ, float *pfAngle);
//bool DrawField_SetDoorNAngle(int nSurface, int nX, int nY, int nZ, float fAngle);
//bool DrawField_SetDoorWAngle(int nSurface, int nX, int nY, int nZ, float fAngle);
//bool DrawField_SetDoorSAngle(int nSurface, int nX, int nY, int nZ, float fAngle);
//bool DrawField_SetDoorEAngle(int nSurface, int nX, int nY, int nZ, float fAngle);
CELL_SETTER(DrawField_SetDoorNLock, int, cell->north_door_lock, true);
CELL_SETTER(DrawField_SetDoorWLock, int, cell->west_door_lock, true);
CELL_SETTER(DrawField_SetDoorSLock, int, cell->south_door_lock, true);
CELL_SETTER(DrawField_SetDoorELock, int, cell->east_door_lock, true);
static bool DrawField_GetDoorNLock(int surface, int x, int y, int z, int *lock)
{
struct dgn_cell *cell = dungeon_get_cell(surface, x, y, z);
if (!cell || cell->north_door == -1)
return false;
*lock = cell->north_door_lock;
return true;
}
static bool DrawField_GetDoorWLock(int surface, int x, int y, int z, int *lock)
{
struct dgn_cell *cell = dungeon_get_cell(surface, x, y, z);
if (!cell || cell->west_door == -1)
return false;
*lock = cell->west_door_lock;
return true;
}
static bool DrawField_GetDoorSLock(int surface, int x, int y, int z, int *lock)
{
struct dgn_cell *cell = dungeon_get_cell(surface, x, y, z);
if (!cell || cell->south_door == -1)
return false;
*lock = cell->south_door_lock;
return true;
}
static bool DrawField_GetDoorELock(int surface, int x, int y, int z, int *lock)
{
struct dgn_cell *cell = dungeon_get_cell(surface, x, y, z);
if (!cell || cell->east_door == -1)
return false;
*lock = cell->east_door_lock;
return true;
}
//void DrawField_SetTexStair(int nSurface, int nX, int nY, int nZ, int nTexture, int nType);
//void DrawField_SetShadowTexFloor(int nSurface, int nX, int nY, int nZ, int nTexture);
//void DrawField_SetShadowTexCeiling(int nSurface, int nX, int nY, int nZ, int nTexture);
//void DrawField_SetShadowTexWallN(int nSurface, int nX, int nY, int nZ, int nTexture);
//void DrawField_SetShadowTexWallW(int nSurface, int nX, int nY, int nZ, int nTexture);
//void DrawField_SetShadowTexWallS(int nSurface, int nX, int nY, int nZ, int nTexture);
//void DrawField_SetShadowTexWallE(int nSurface, int nX, int nY, int nZ, int nTexture);
//void DrawField_SetShadowTexDoorN(int nSurface, int nX, int nY, int nZ, int nTexture);
//void DrawField_SetShadowTexDoorW(int nSurface, int nX, int nY, int nZ, int nTexture);
//void DrawField_SetShadowTexDoorS(int nSurface, int nX, int nY, int nZ, int nTexture);
//void DrawField_SetShadowTexDoorE(int nSurface, int nX, int nY, int nZ, int nTexture);
static void DrawField_CalcShadowMap(int surface)
{
struct dungeon_context *ctx = dungeon_get_context(surface);
if (!ctx || !ctx->dgn)
return;
return dgn_calc_lightmap(ctx->dgn);
}
HLL_QUIET_UNIMPLEMENTED(, void, DrawField, SetLooked, int surface, int x, int y, int z, bool flag);
HLL_WARN_UNIMPLEMENTED(false, bool, DrawField, SetHideDrawMapFloor, int surface, int floor, bool hide);
//bool DrawField_SetHideDrawMapWall(int nSurface, int nWall, bool bHide);
static void DrawField_SetDrawShadowMap(int surface, bool draw)
{
struct dungeon_context *ctx = dungeon_get_context(surface);
if (!ctx || !ctx->renderer)
return;
dungeon_renderer_enable_lightmap(ctx->renderer, draw);
}
static float DrawField_CosDeg(float deg)
{
return cosf(glm_rad(deg));
}
static float DrawField_SinDeg(float deg)
{
return sinf(glm_rad(deg));
}
static float DrawField_TanDeg(float deg)
{
return tanf(glm_rad(deg));
}
static float DrawField_Atan2(float y, float x)
{
return glm_deg(atan2f(y, x));
}
//bool DrawField_TransPos2DToPos3DOnPlane(int surface, int nScreenX, int nScreenY, float fPlaneY, float *pfX, float *pfY, float *pfZ);
//bool DrawField_TransPos3DToPos2D(int nSurace, float fX, float fY, float fZ, int *pnScreenX, int *pnScreenY);
static int DrawField_GetCharaNumMax(int surface)
{
return DRAWFIELD_NR_CHARACTERS;
}
//void DrawField_SetCharaZBias(int surface, float fZBias0, float fZBias1, float fZBias2, float fZBias3);
HLL_QUIET_UNIMPLEMENTED(, void, DrawField, SetCenterOffsetY, int surface, float y);
//void DrawField_SetBuilBoard(int surface, int num, int sprite);
static void DrawField_SetSphereTheta(int surface, float x, float y, float z)
{
struct dungeon_context *ctx = dungeon_get_context(surface);
if (!ctx || !ctx->dgn)
return;
ctx->dgn->sphere_theta[0] = x;
ctx->dgn->sphere_theta[1] = y;
ctx->dgn->sphere_theta[2] = z;
}
static void DrawField_SetSphereColor(int surface, float top, float bottom)
{
struct dungeon_context *ctx = dungeon_get_context(surface);
if (!ctx || !ctx->dgn)
return;
ctx->dgn->sphere_color_top = top;
ctx->dgn->sphere_color_bottom = bottom;
}
static bool DrawField_GetSphereTheta(int surface, float *x, float *y, float *z)
{
struct dungeon_context *ctx = dungeon_get_context(surface);
if (!ctx || !ctx->dgn)
return false;
*x = ctx->dgn->sphere_theta[0];
*y = ctx->dgn->sphere_theta[1];
*z = ctx->dgn->sphere_theta[2];
return true;
}
static bool DrawField_GetSphereColor(int surface, float *top, float *bottom)
{
struct dungeon_context *ctx = dungeon_get_context(surface);
if (!ctx || !ctx->dgn)
return false;
*top = ctx->dgn->sphere_color_top;
*bottom = ctx->dgn->sphere_color_bottom;
return true;
}
static bool DrawField_GetBackColor(int surface, int *r, int *g, int *b)
{
struct dungeon_context *ctx = dungeon_get_context(surface);
if (!ctx || !ctx->dgn)
return false;
*r = ctx->dgn->back_color_r;
*g = ctx->dgn->back_color_g;
*b = ctx->dgn->back_color_b;
return true;
}
static void DrawField_SetBackColor(int surface, int r, int g, int b)
{
struct dungeon_context *ctx = dungeon_get_context(surface);
if (!ctx || !ctx->dgn)
return;
ctx->dgn->back_color_r = r;
ctx->dgn->back_color_g = g;
ctx->dgn->back_color_b = b;
}
//int DrawField_GetPolyObj(int surface, int nX, int nY, int nZ);
//float DrawField_GetPolyObjMag(int surface, int nX, int nY, int nZ);
//float DrawField_GetPolyObjRotateH(int surface, int nX, int nY, int nZ);
//float DrawField_GetPolyObjRotateP(int surface, int nX, int nY, int nZ);
//float DrawField_GetPolyObjRotateB(int surface, int nX, int nY, int nZ);
//float DrawField_GetPolyObjOffsetX(int surface, int nX, int nY, int nZ);
//float DrawField_GetPolyObjOffsetY(int surface, int nX, int nY, int nZ);
//float DrawField_GetPolyObjOffsetZ(int surface, int nX, int nY, int nZ);
//void DrawField_SetPolyObj(int surface, int nX, int nY, int nZ, int nPolyObj);
//void DrawField_SetPolyObjMag(int surface, int nX, int nY, int nZ, float fMag);
//void DrawField_SetPolyObjRotateH(int surface, int nX, int nY, int nZ, float fRotateH);
//void DrawField_SetPolyObjRotateP(int surface, int nX, int nY, int nZ, float fRotateP);
//void DrawField_SetPolyObjRotateB(int surface, int nX, int nY, int nZ, float fRotateB);
//void DrawField_SetPolyObjOffsetX(int surface, int nX, int nY, int nZ, float fOffsetX);
//void DrawField_SetPolyObjOffsetY(int surface, int nX, int nY, int nZ, float fOffsetY);
//void DrawField_SetPolyObjOffsetZ(int surface, int nX, int nY, int nZ, float fOffsetZ);
static void DrawField_SetDrawObjFlag(int surface, int type, bool flag)
{
struct dungeon_context *ctx = dungeon_get_context(surface);
if (!ctx || !ctx->renderer)
return;
dungeon_renderer_set_draw_obj_flag(ctx->renderer, type, flag);
}
static bool DrawField_GetDrawObjFlag(int surface, int type)
{
struct dungeon_context *ctx = dungeon_get_context(surface);
if (!ctx || !ctx->renderer)
return false;
return dungeon_renderer_get_draw_obj_flag(ctx->renderer, type);
}
//int DrawField_GetNumofTexSound(int nSurface, int nType);
HLL_LIBRARY(DrawField,
HLL_EXPORT(Init, DrawField_Init),
HLL_EXPORT(Release, DrawDungeon_Release),
HLL_EXPORT(SetDrawFlag, DrawDungeon_SetDrawFlag),
HLL_EXPORT(GetDrawFlag, DrawDungeon_GetDrawFlag),
HLL_EXPORT(LoadFromFile, DrawDungeon_LoadFromFile),
HLL_EXPORT(LoadTexture, DrawDungeon_LoadTexture),
HLL_TODO_EXPORT(LoadEventTexture, DrawDungeon_LoadEventTexture),
HLL_TODO_EXPORT(BeginLoad, DrawField_BeginLoad),
HLL_TODO_EXPORT(IsLoadEnd, DrawField_IsLoadEnd),
HLL_TODO_EXPORT(StopLoad, DrawField_StopLoad),
HLL_TODO_EXPORT(GetLoadPercent, DrawField_GetLoadPercent),
HLL_TODO_EXPORT(IsLoadSucceeded, DrawField_IsLoadSucceeded),
HLL_TODO_EXPORT(BeginLoadTexture, DrawField_BeginLoadTexture),
HLL_TODO_EXPORT(IsLoadTextureEnd, DrawField_IsLoadTextureEnd),
HLL_TODO_EXPORT(StopLoadTexture, DrawField_StopLoadTexture),
HLL_TODO_EXPORT(GetLoadTexturePercent, DrawField_GetLoadTexturePercent),
HLL_TODO_EXPORT(IsLoadTextureSucceeded, DrawField_IsLoadTextureSucceeded),
HLL_TODO_EXPORT(UpdateTexture, DrawField_UpdateTexture),
HLL_EXPORT(SetCamera, dungeon_set_camera),
HLL_EXPORT(GetMapX, DrawDungeon_GetMapX),
HLL_EXPORT(GetMapY, DrawDungeon_GetMapY),
HLL_EXPORT(GetMapZ, DrawDungeon_GetMapZ),
HLL_EXPORT(IsInMap, DrawDungeon_IsInMap),
HLL_EXPORT(IsFloor, DrawDungeon_IsFloor),
HLL_EXPORT(IsStair, DrawDungeon_IsStair),
HLL_EXPORT(IsStairN, DrawDungeon_IsStairN),
HLL_EXPORT(IsStairW, DrawDungeon_IsStairW),
HLL_EXPORT(IsStairS, DrawDungeon_IsStairS),
HLL_EXPORT(IsStairE, DrawDungeon_IsStairE),
HLL_EXPORT(IsWallN, DrawDungeon_IsWallN),
HLL_EXPORT(IsWallW, DrawDungeon_IsWallW),
HLL_EXPORT(IsWallS, DrawDungeon_IsWallS),
HLL_EXPORT(IsWallE, DrawDungeon_IsWallE),
HLL_EXPORT(IsDoorN, DrawDungeon_IsDoorN),
HLL_EXPORT(IsDoorW, DrawDungeon_IsDoorW),
HLL_EXPORT(IsDoorS, DrawDungeon_IsDoorS),
HLL_EXPORT(IsDoorE, DrawDungeon_IsDoorE),
HLL_EXPORT(IsEnter, DrawDungeon_IsEnter),
HLL_EXPORT(IsEnterN, DrawDungeon_IsEnterN),
HLL_EXPORT(IsEnterW, DrawDungeon_IsEnterW),
HLL_EXPORT(IsEnterS, DrawDungeon_IsEnterS),
HLL_EXPORT(IsEnterE, DrawDungeon_IsEnterE),
HLL_EXPORT(GetEvFloor, DrawDungeon_GetEvFloor),
HLL_EXPORT(GetEvWallN, DrawDungeon_GetEvWallN),
HLL_EXPORT(GetEvWallW, DrawDungeon_GetEvWallW),
HLL_EXPORT(GetEvWallS, DrawDungeon_GetEvWallS),
HLL_EXPORT(GetEvWallE, DrawDungeon_GetEvWallE),
HLL_EXPORT(GetEvFloor2, DrawDungeon_GetEvFloor2),
HLL_EXPORT(GetEvWallN2, DrawDungeon_GetEvWallN2),
HLL_EXPORT(GetEvWallW2, DrawDungeon_GetEvWallW2),
HLL_EXPORT(GetEvWallS2, DrawDungeon_GetEvWallS2),
HLL_EXPORT(GetEvWallE2, DrawDungeon_GetEvWallE2),
HLL_EXPORT(GetTexFloor, DrawDungeon_GetTexFloor),
HLL_EXPORT(GetTexCeiling, DrawDungeon_GetTexCeiling),
HLL_EXPORT(GetTexWallN, DrawDungeon_GetTexWallN),
HLL_EXPORT(GetTexWallW, DrawDungeon_GetTexWallW),
HLL_EXPORT(GetTexWallS, DrawDungeon_GetTexWallS),
HLL_EXPORT(GetTexWallE, DrawDungeon_GetTexWallE),
HLL_EXPORT(GetTexDoorN, DrawDungeon_GetTexDoorN),
HLL_EXPORT(GetTexDoorW, DrawDungeon_GetTexDoorW),
HLL_EXPORT(GetTexDoorS, DrawDungeon_GetTexDoorS),
HLL_EXPORT(GetTexDoorE, DrawDungeon_GetTexDoorE),
HLL_TODO_EXPORT(GetDoorNAngle, DrawField_GetDoorNAngle),
HLL_TODO_EXPORT(GetDoorWAngle, DrawField_GetDoorWAngle),
HLL_TODO_EXPORT(GetDoorSAngle, DrawField_GetDoorSAngle),
HLL_TODO_EXPORT(GetDoorEAngle, DrawField_GetDoorEAngle),
HLL_TODO_EXPORT(SetDoorNAngle, DrawField_SetDoorNAngle),
HLL_TODO_EXPORT(SetDoorWAngle, DrawField_SetDoorWAngle),
HLL_TODO_EXPORT(SetDoorSAngle, DrawField_SetDoorSAngle),
HLL_TODO_EXPORT(SetDoorEAngle, DrawField_SetDoorEAngle),
HLL_EXPORT(SetEvFloor, DrawDungeon_SetEvFloor),
HLL_EXPORT(SetEvWallN, DrawDungeon_SetEvWallN),
HLL_EXPORT(SetEvWallW, DrawDungeon_SetEvWallW),
HLL_EXPORT(SetEvWallS, DrawDungeon_SetEvWallS),
HLL_EXPORT(SetEvWallE, DrawDungeon_SetEvWallE),
HLL_EXPORT(SetEvFloor2, DrawDungeon_SetEvFloor2),
HLL_EXPORT(SetEvWallN2, DrawDungeon_SetEvWallN2),
HLL_EXPORT(SetEvWallW2, DrawDungeon_SetEvWallW2),
HLL_EXPORT(SetEvWallS2, DrawDungeon_SetEvWallS2),
HLL_EXPORT(SetEvWallE2, DrawDungeon_SetEvWallE2),
HLL_TODO_EXPORT(SetEvMag, DrawDungeon_SetEvMag),
HLL_EXPORT(SetEvRate, DrawDungeon_SetEvRate),
HLL_EXPORT(SetEnter, DrawDungeon_SetEnter),
HLL_EXPORT(SetEnterN, DrawDungeon_SetEnterN),
HLL_EXPORT(SetEnterW, DrawDungeon_SetEnterW),
HLL_EXPORT(SetEnterS, DrawDungeon_SetEnterS),
HLL_EXPORT(SetEnterE, DrawDungeon_SetEnterE),
HLL_EXPORT(SetDoorNLock, DrawField_SetDoorNLock),
HLL_EXPORT(SetDoorWLock, DrawField_SetDoorWLock),
HLL_EXPORT(SetDoorSLock, DrawField_SetDoorSLock),
HLL_EXPORT(SetDoorELock, DrawField_SetDoorELock),
HLL_EXPORT(GetDoorNLock, DrawField_GetDoorNLock),
HLL_EXPORT(GetDoorWLock, DrawField_GetDoorWLock),
HLL_EXPORT(GetDoorSLock, DrawField_GetDoorSLock),
HLL_EXPORT(GetDoorELock, DrawField_GetDoorELock),
HLL_EXPORT(SetTexFloor, DrawDungeon_SetTexFloor),
HLL_EXPORT(SetTexCeiling, DrawDungeon_SetTexCeiling),
HLL_EXPORT(SetTexWallN, DrawDungeon_SetTexWallN),
HLL_EXPORT(SetTexWallW, DrawDungeon_SetTexWallW),
HLL_EXPORT(SetTexWallS, DrawDungeon_SetTexWallS),
HLL_EXPORT(SetTexWallE, DrawDungeon_SetTexWallE),
HLL_EXPORT(SetTexDoorN, DrawDungeon_SetTexDoorN),
HLL_EXPORT(SetTexDoorW, DrawDungeon_SetTexDoorW),
HLL_EXPORT(SetTexDoorS, DrawDungeon_SetTexDoorS),
HLL_EXPORT(SetTexDoorE, DrawDungeon_SetTexDoorE),
HLL_TODO_EXPORT(SetTexStair, DrawField_SetTexStair),
HLL_TODO_EXPORT(SetShadowTexFloor, DrawField_SetShadowTexFloor),
HLL_TODO_EXPORT(SetShadowTexCeiling, DrawField_SetShadowTexCeiling),
HLL_TODO_EXPORT(SetShadowTexWallN, DrawField_SetShadowTexWallN),
HLL_TODO_EXPORT(SetShadowTexWallW, DrawField_SetShadowTexWallW),
HLL_TODO_EXPORT(SetShadowTexWallS, DrawField_SetShadowTexWallS),
HLL_TODO_EXPORT(SetShadowTexWallE, DrawField_SetShadowTexWallE),
HLL_TODO_EXPORT(SetShadowTexDoorN, DrawField_SetShadowTexDoorN),
HLL_TODO_EXPORT(SetShadowTexDoorW, DrawField_SetShadowTexDoorW),
HLL_TODO_EXPORT(SetShadowTexDoorS, DrawField_SetShadowTexDoorS),
HLL_TODO_EXPORT(SetShadowTexDoorE, DrawField_SetShadowTexDoorE),
HLL_EXPORT(CalcShadowMap, DrawField_CalcShadowMap),
HLL_EXPORT(DrawMap, dungeon_map_draw),
HLL_EXPORT(SetMapAllViewFlag, dungeon_map_set_all_view),
HLL_EXPORT(SetDrawMapFloor, dungeon_map_set_small_map_floor),
HLL_EXPORT(DrawLMap, dungeon_map_draw_lmap),
HLL_EXPORT(SetMapCG, dungeon_map_set_cg),
HLL_EXPORT(SetDrawLMapFloor, dungeon_map_set_large_map_floor),
HLL_EXPORT(SetPlayerPos, dungeon_set_player_pos),
HLL_EXPORT(SetWalked, dungeon_set_walked),
HLL_EXPORT(SetLooked, DrawField_SetLooked),
HLL_EXPORT(SetHideDrawMapFloor, DrawField_SetHideDrawMapFloor),
HLL_TODO_EXPORT(SetHideDrawMapWall, DrawField_SetHideDrawMapWall),
HLL_EXPORT(SetDrawHalfFlag, DrawDungeon_SetDrawHalfFlag),
HLL_EXPORT(GetDrawHalfFlag, DrawDungeon_GetDrawHalfFlag),
HLL_EXPORT(SetInterlaceMode, DrawDungeon_SetInterlaceMode),
HLL_EXPORT(SetDirect3DMode, DrawDungeon_SetDirect3DMode),
HLL_EXPORT(GetDirect3DMode, DrawDungeon_GetDirect3DMode),
HLL_EXPORT(SaveDrawSettingFlag, DrawDungeon_SaveDrawSettingFlag),
HLL_EXPORT(SetPerspective, dungeon_set_perspective),
HLL_EXPORT(SetDrawShadowMap, DrawField_SetDrawShadowMap),
HLL_TODO_EXPORT(CalcNumofFloor, DrawField_CalcNumofFloor),
HLL_TODO_EXPORT(CalcNumofWalk, DrawField_CalcNumofWalk),
HLL_TODO_EXPORT(CalcNumofWalk2, DrawField_CalcNumofWalk2),
HLL_EXPORT(IsPVSData, DrawDungeon_IsPVSData),
HLL_EXPORT(CosDeg, DrawField_CosDeg),
HLL_EXPORT(SinDeg, DrawField_SinDeg),
HLL_EXPORT(TanDeg, DrawField_TanDeg),
HLL_EXPORT(Sqrt, sqrtf),
HLL_EXPORT(Atan2, DrawField_Atan2),
HLL_TODO_EXPORT(TransPos2DToPos3DOnPlane, DrawField_TransPos2DToPos3DOnPlane),
HLL_TODO_EXPORT(TransPos3DToPos2D, DrawField_TransPos3DToPos2D),
HLL_EXPORT(GetCharaNumMax, DrawField_GetCharaNumMax),
HLL_EXPORT(SetCharaSprite, dungeon_set_chara_sprite),
HLL_EXPORT(SetCharaPos, dungeon_set_chara_pos),
HLL_EXPORT(SetCharaCG, dungeon_set_chara_cg),
HLL_EXPORT(SetCharaCGInfo, dungeon_set_chara_cg_info),
HLL_TODO_EXPORT(SetCharaZBias, DrawField_SetCharaZBias),
HLL_EXPORT(SetCharaShow, dungeon_set_chara_show),
HLL_EXPORT(SetCenterOffsetY, DrawField_SetCenterOffsetY),
HLL_TODO_EXPORT(SetBuilBoard, DrawField_SetBuilBoard),
HLL_EXPORT(SetSphereTheta, DrawField_SetSphereTheta),
HLL_EXPORT(SetSphereColor, DrawField_SetSphereColor),
HLL_EXPORT(GetSphereTheta, DrawField_GetSphereTheta),
HLL_EXPORT(GetSphereColor, DrawField_GetSphereColor),
HLL_EXPORT(GetBackColor, DrawField_GetBackColor),
HLL_EXPORT(SetBackColor, DrawField_SetBackColor),
HLL_TODO_EXPORT(GetPolyObj, DrawField_GetPolyObj),
HLL_TODO_EXPORT(GetPolyObjMag, DrawField_GetPolyObjMag),
HLL_TODO_EXPORT(GetPolyObjRotateH, DrawField_GetPolyObjRotateH),
HLL_TODO_EXPORT(GetPolyObjRotateP, DrawField_GetPolyObjRotateP),
HLL_TODO_EXPORT(GetPolyObjRotateB, DrawField_GetPolyObjRotateB),
HLL_TODO_EXPORT(GetPolyObjOffsetX, DrawField_GetPolyObjOffsetX),
HLL_TODO_EXPORT(GetPolyObjOffsetY, DrawField_GetPolyObjOffsetY),
HLL_TODO_EXPORT(GetPolyObjOffsetZ, DrawField_GetPolyObjOffsetZ),
HLL_TODO_EXPORT(SetPolyObj, DrawField_SetPolyObj),
HLL_TODO_EXPORT(SetPolyObjMag, DrawField_SetPolyObjMag),
HLL_TODO_EXPORT(SetPolyObjRotateH, DrawField_SetPolyObjRotateH),
HLL_TODO_EXPORT(SetPolyObjRotateP, DrawField_SetPolyObjRotateP),
HLL_TODO_EXPORT(SetPolyObjRotateB, DrawField_SetPolyObjRotateB),
HLL_TODO_EXPORT(SetPolyObjOffsetX, DrawField_SetPolyObjOffsetX),
HLL_TODO_EXPORT(SetPolyObjOffsetY, DrawField_SetPolyObjOffsetY),
HLL_TODO_EXPORT(SetPolyObjOffsetZ, DrawField_SetPolyObjOffsetZ),
HLL_EXPORT(SetDrawObjFlag, DrawField_SetDrawObjFlag),
HLL_EXPORT(GetDrawObjFlag, DrawField_GetDrawObjFlag),
HLL_EXPORT(GetTexSound, DrawDungeon_GetTexSound),
HLL_TODO_EXPORT(GetNumofTexSound, DrawField_GetNumofTexSound)
);