mirror of
https://github.com/Karaka-Management/cOMS.git
synced 2026-01-11 11:18:40 +00:00
Started to render with normals. working
This commit is contained in:
parent
149543016b
commit
2149c82b63
|
|
@ -19,6 +19,7 @@
|
|||
#endif
|
||||
|
||||
#include "Audio.h"
|
||||
#include "AudioSetting.h"
|
||||
#include "Wav.h"
|
||||
|
||||
void audio_from_file(RingMemory* ring, const char* path, Audio* audio)
|
||||
|
|
@ -31,4 +32,88 @@ void audio_from_file(RingMemory* ring, const char* path, Audio* audio)
|
|||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void audio_fill_buffer(AudioSetting* setting, uint32 to_fill, Audio* sound, int16* buffer1, int32 buffer1_size, int16* buffer2 = NULL, int32 buffer2_size = 0)
|
||||
{
|
||||
uint32 limit = to_fill / setting->sample_size;
|
||||
buffer1_size /= setting->sample_size;
|
||||
buffer2_size /= setting->sample_size;
|
||||
uint32 sample_count = sound->size / sound->sample_size;
|
||||
f32 volume_scale = (f32) setting->volume / 100.0f;
|
||||
const int16* data = (int16*) sound->data;
|
||||
uint32 sample_index = setting->sample_index;
|
||||
|
||||
uint32 i;
|
||||
for (i = 0; i < limit && i < buffer1_size; ++i) {
|
||||
if (sample_index >= sample_count) {
|
||||
sample_index = 0;
|
||||
|
||||
// @question why are we doing this?
|
||||
setting->sample_index = 0;
|
||||
}
|
||||
|
||||
buffer1[i * 2] = (int16) (data[sample_index * 2] * volume_scale);
|
||||
buffer1[i * 2 + 1] = (int16) (data[sample_index * 2 + 1] * volume_scale);
|
||||
|
||||
++sample_index;
|
||||
}
|
||||
|
||||
for (; i < limit && buffer2_size; ++i) {
|
||||
if (sample_index >= sample_count) {
|
||||
sample_index = 0;
|
||||
|
||||
// @question why are we doing this?
|
||||
setting->sample_index = 0;
|
||||
}
|
||||
|
||||
buffer2[i * 2] = (int16) (data[sample_index * 2] * volume_scale);
|
||||
buffer2[i * 2 + 1] = (int16) (data[sample_index * 2 + 1] * volume_scale);
|
||||
|
||||
++sample_index;
|
||||
}
|
||||
|
||||
++setting->sample_output;
|
||||
setting->sample_buffer_size = to_fill;
|
||||
}
|
||||
|
||||
// @bug This is slower
|
||||
/*
|
||||
inline
|
||||
void fill_audio_buffer(AudioSetting* audio_handle, uint32 to_fill, Audio* sound, int32 steps = 8)
|
||||
{
|
||||
uint32 limit = to_fill / audio_handle->sample_size;
|
||||
uint32 sample_count = sound->size / sound->sample_size;
|
||||
uint32 sample_index = audio_handle->sample_index;
|
||||
|
||||
// Copy all data until end
|
||||
int32 offset;
|
||||
memcpy(
|
||||
audio_handle->buffer,
|
||||
sound->data + audio_handle->sample_index * audio_handle->sample_size,
|
||||
(offset = OMS_MIN(sample_count - sample_index, limit)) * audio_handle->sample_size
|
||||
);
|
||||
|
||||
// If we are wrapping (play sound on loop)
|
||||
// @todo we still need a setting if we actually want to do this
|
||||
if (offset != limit) {
|
||||
audio_handle->sample_index = 0;
|
||||
memcpy(
|
||||
audio_handle->buffer + offset * audio_handle->sample_size,
|
||||
sound->data,
|
||||
(limit - offset) * audio_handle->sample_size
|
||||
);
|
||||
}
|
||||
|
||||
simd_mult(
|
||||
(int16 *) audio_handle->buffer,
|
||||
(f32) audio_handle->volume / 100.0f,
|
||||
(int16 *) audio_handle->buffer, limit * 2,
|
||||
steps
|
||||
);
|
||||
|
||||
++audio_handle->sample_output;
|
||||
audio_handle->sample_buffer_size = to_fill;
|
||||
}
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
|
|
|||
31
environment/Globe.h
Normal file
31
environment/Globe.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#ifndef TOS_ENVIRONMENT_GLOBE_H
|
||||
#define TOS_ENVIRONMENT_GLOBE_H
|
||||
|
||||
#include "../stdlib/Types.h"
|
||||
#include <math.h>
|
||||
|
||||
// day_length in seconds
|
||||
f32 time_of_day(f64 time, f32 day_length) {
|
||||
f64 t = time;
|
||||
t = t / day_length;
|
||||
t = t - (int32) t;
|
||||
|
||||
return (f32) t;
|
||||
}
|
||||
|
||||
// time can either be actual time in seconds OR relative time to progra start
|
||||
f32 daylight_get(f64 time, f32 day_length) {
|
||||
f32 timer = time_of_day(time, day_length);
|
||||
|
||||
if (timer < 0.5) {
|
||||
f32 t = (timer - 0.25) * 100;
|
||||
|
||||
return 1 / (1 + powf(2, -t));
|
||||
}
|
||||
|
||||
f32 t = (timer - 0.85) * 100;
|
||||
|
||||
return 1 - 1 / (1 + powf(2, -t));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -39,6 +39,8 @@ struct Font {
|
|||
char texture_name[32];
|
||||
f32 size; // Default font size at which the font renders best
|
||||
f32 line_height; // How tall is a single line (mostly important for multiple lines)
|
||||
|
||||
// WARNING: Glyphs MUST be sorted ascending based on codepoint
|
||||
Glyph* glyphs;
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -333,15 +333,83 @@ void vertex_input(Vertex3DTextureColorIndex* __restrict vertices, uint32* __rest
|
|||
);
|
||||
}
|
||||
|
||||
f32 text_calculate_dimensions_height(
|
||||
f32 height,
|
||||
const Font* __restrict font, const char* __restrict text, f32 scale, int32 length
|
||||
) {
|
||||
f32 y = font->line_height * scale;
|
||||
|
||||
// @todo remember to restrict to width/height if value > 0 -> force width to remain below certain value
|
||||
|
||||
for (int i = 0; i < length; ++i) {
|
||||
if (text[i] == '\n') {
|
||||
y += font->line_height * scale;
|
||||
}
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
f32 text_calculate_dimensions_width(
|
||||
f32 width,
|
||||
const Font* __restrict font, const char* __restrict text, f32 scale, int32 length
|
||||
) {
|
||||
f32 x = 0;
|
||||
f32 offset_x = 0;
|
||||
|
||||
uint32 first_glyph = font->glyphs[0].codepoint;
|
||||
|
||||
// @todo remember to restrict to width/height if value > 0 -> force width to remain below certain value
|
||||
|
||||
for (int i = 0; i < length; ++i) {
|
||||
int32 character = utf8_get_char_at(text, i);
|
||||
|
||||
if (character == '\n') {
|
||||
x = OMS_MAX(x, offset_x);
|
||||
offset_x = 0;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
Glyph* glyph = NULL;
|
||||
// We try to jump t othe correct glyph based on the glyph codepoint
|
||||
// If that doesn't work we iterate the glyph list BUT only until the last possible match (glyphs must be sorted ascending)
|
||||
if (font->glyph_count > character - first_glyph
|
||||
&& font->glyphs[character - first_glyph].codepoint == character
|
||||
) {
|
||||
glyph = &font->glyphs[character - first_glyph];
|
||||
} else {
|
||||
// @performance consider to do binary search
|
||||
for (int j = 0; j <= character - first_glyph && j < font->glyph_count; ++j) {
|
||||
if (font->glyphs[j].codepoint == character) {
|
||||
glyph = &font->glyphs[j];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!glyph) {
|
||||
continue;
|
||||
}
|
||||
|
||||
offset_x += (glyph->metrics.width + glyph->metrics.offset_x + glyph->metrics.advance_x) * scale;
|
||||
}
|
||||
|
||||
return OMS_MAX(x, offset_x);
|
||||
}
|
||||
|
||||
void text_calculate_dimensions(
|
||||
f32* __restrict width, f32* __restrict height,
|
||||
const Font* __restrict font, const char* text, f32 scale, int32 length
|
||||
const Font* __restrict font, const char* __restrict text, f32 scale, int32 length
|
||||
) {
|
||||
f32 x = 0;
|
||||
f32 y = font->line_height * scale;
|
||||
|
||||
f32 offset_x = 0;
|
||||
|
||||
uint32 first_glyph = font->glyphs[0].codepoint;
|
||||
|
||||
// @todo remember to restrict to width/height if value > 0 -> force width to remain below certain value
|
||||
|
||||
for (int i = 0; i < length; ++i) {
|
||||
|
|
@ -357,11 +425,20 @@ void text_calculate_dimensions(
|
|||
}
|
||||
|
||||
Glyph* glyph = NULL;
|
||||
for (int j = 0; j < font->glyph_count; ++j) {
|
||||
if (font->glyphs[j].codepoint == character) {
|
||||
glyph = &font->glyphs[j];
|
||||
// We try to jump t othe correct glyph based on the glyph codepoint
|
||||
// If that doesn't work we iterate the glyph list BUT only until the last possible match (glyphs must be sorted ascending)
|
||||
if (font->glyph_count > character - first_glyph
|
||||
&& font->glyphs[character - first_glyph].codepoint == character
|
||||
) {
|
||||
glyph = &font->glyphs[character - first_glyph];
|
||||
} else {
|
||||
// @performance consider to do binary search
|
||||
for (int j = 0; j <= character - first_glyph && j < font->glyph_count; ++j) {
|
||||
if (font->glyphs[j].codepoint == character) {
|
||||
glyph = &font->glyphs[j];
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -369,7 +446,7 @@ void text_calculate_dimensions(
|
|||
continue;
|
||||
}
|
||||
|
||||
offset_x += (glyph->metrics.width + glyph->metrics.offset_x) * scale;
|
||||
offset_x += (glyph->metrics.width + glyph->metrics.offset_x + glyph->metrics.advance_x) * scale;
|
||||
}
|
||||
|
||||
*width = OMS_MAX(x, offset_x);
|
||||
|
|
@ -386,7 +463,13 @@ f32 vertex_text_create(
|
|||
|
||||
// If we do a different alignment we need to pre-calculate the width and height
|
||||
if (align_h != 0 || align_v != 0) {
|
||||
text_calculate_dimensions(&width, &height, font, text, scale, length);
|
||||
if (align_h != 0 && align_v != 0) {
|
||||
text_calculate_dimensions(&width, &height, font, text, scale, length);
|
||||
} else if (align_h != 0) {
|
||||
width = text_calculate_dimensions_width(width, font, text, scale, length);
|
||||
} else {
|
||||
height = text_calculate_dimensions_height(height, font, text, scale, length);
|
||||
}
|
||||
|
||||
if (align_h == UI_ALIGN_H_RIGHT) {
|
||||
x -= width;
|
||||
|
|
@ -401,6 +484,8 @@ f32 vertex_text_create(
|
|||
}
|
||||
}
|
||||
|
||||
uint32 first_glyph = font->glyphs[0].codepoint;
|
||||
|
||||
f32 offset_x = x;
|
||||
for (int i = 0; i < length; ++i) {
|
||||
int32 character = utf8_get_char_at(text, i);
|
||||
|
|
@ -412,11 +497,20 @@ f32 vertex_text_create(
|
|||
}
|
||||
|
||||
Glyph* glyph = NULL;
|
||||
for (int j = 0; j < font->glyph_count; ++j) {
|
||||
if (font->glyphs[j].codepoint == character) {
|
||||
glyph = &font->glyphs[j];
|
||||
// We try to jump t othe correct glyph based on the glyph codepoint
|
||||
// If that doesn't work we iterate the glyph list BUT only until the last possible match (glyphs must be sorted ascending)
|
||||
if (font->glyph_count > character - first_glyph
|
||||
&& font->glyphs[character - first_glyph].codepoint == character
|
||||
) {
|
||||
glyph = &font->glyphs[character - first_glyph];
|
||||
} else {
|
||||
// @performance consider to do binary search
|
||||
for (int j = 0; j <= character - first_glyph && j < font->glyph_count; ++j) {
|
||||
if (font->glyphs[j].codepoint == character) {
|
||||
glyph = &font->glyphs[j];
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -506,7 +600,13 @@ f32 ui_text_create(
|
|||
f32 tmp_width = width->value_int;
|
||||
f32 tmp_height = height->value_int;
|
||||
|
||||
text_calculate_dimensions(&tmp_width, &tmp_height, &theme->font, text->value_str, scale, length);
|
||||
if (align_h != NULL && align_v != NULL) {
|
||||
text_calculate_dimensions(&tmp_width, &tmp_height, &theme->font, text->value_str, scale, length);
|
||||
} else if (align_h != NULL) {
|
||||
tmp_width = text_calculate_dimensions_width(tmp_width, &theme->font, text->value_str, scale, length);
|
||||
} else {
|
||||
tmp_height = text_calculate_dimensions_height(tmp_height, &theme->font, text->value_str, scale, length);
|
||||
}
|
||||
|
||||
if (align_h->value_int == UI_ALIGN_H_RIGHT) {
|
||||
x -= width->value_int;
|
||||
|
|
@ -521,6 +621,8 @@ f32 ui_text_create(
|
|||
}
|
||||
}
|
||||
|
||||
uint32 first_glyph = theme->font.glyphs[0].codepoint;
|
||||
|
||||
int32 start = *index;
|
||||
f32 offset_x = x->value_int;
|
||||
f32 offset_y = y->value_int;
|
||||
|
|
@ -535,11 +637,20 @@ f32 ui_text_create(
|
|||
}
|
||||
|
||||
Glyph* glyph = NULL;
|
||||
for (int j = 0; j < theme->font.glyph_count; ++j) {
|
||||
if (theme->font.glyphs[j].codepoint == character) {
|
||||
glyph = &theme->font.glyphs[j];
|
||||
// We try to jump t othe correct glyph based on the glyph codepoint
|
||||
// If that doesn't work we iterate the glyph list BUT only until the last possible match (glyphs must be sorted ascending)
|
||||
if (theme->font.glyph_count > character - first_glyph
|
||||
&& theme->font.glyphs[character - first_glyph].codepoint == character
|
||||
) {
|
||||
glyph = &theme->font.glyphs[character - first_glyph];
|
||||
} else {
|
||||
// @performance consider to do binary search
|
||||
for (int j = 0; j <= character - first_glyph && j < theme->font.glyph_count; ++j) {
|
||||
if (theme->font.glyphs[j].codepoint == character) {
|
||||
glyph = &theme->font.glyphs[j];
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
24
input/ControllerType.h
Normal file
24
input/ControllerType.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* Jingga
|
||||
*
|
||||
* @copyright Jingga
|
||||
* @license OMS License 2.0
|
||||
* @version 1.0.0
|
||||
* @link https://jingga.app
|
||||
*/
|
||||
#ifndef TOS_PLATFORM_WIN32_INPUT_CONTROLLER_TYPE_H
|
||||
#define TOS_PLATFORM_WIN32_INPUT_CONTROLLER_TYPE_H
|
||||
|
||||
#include "../stdlib/Types.h"
|
||||
|
||||
enum ControllerType {
|
||||
CONTROLLER_TYPE_NONE,
|
||||
CONTROLLER_TYPE_DUALSHOCK4,
|
||||
CONTROLLER_TYPE_DUALSENSE,
|
||||
CONTROLLER_TYPE_XBOX_360,
|
||||
CONTROLLER_TYPE_XBOX_ONE,
|
||||
CONTROLLER_TYPE_XBOX_S,
|
||||
CONTROLLER_TYPE_OTHER,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -133,6 +133,7 @@ struct Input {
|
|||
LPDIRECTINPUTDEVICE8* direct_controller; // used by direct input controller
|
||||
#endif
|
||||
|
||||
byte controller_type;
|
||||
bool state_change_button;
|
||||
bool state_change_mouse;
|
||||
|
||||
|
|
@ -434,7 +435,7 @@ void input_set_state(InputState* state, InputKey* __restrict new_key)
|
|||
free_state = &state->state_keys[i];
|
||||
} else if (state->state_keys[i].key_id == new_key->key_id) {
|
||||
state->state_keys[i].key_state = new_key->key_state;
|
||||
state->state_keys[i].value = new_key->value;
|
||||
state->state_keys[i].value += new_key->value;
|
||||
state->state_keys[i].time = new_key->time;
|
||||
action_required = false;
|
||||
}
|
||||
|
|
@ -592,23 +593,24 @@ input_hotkey_state(Input* input)
|
|||
continue;
|
||||
}
|
||||
|
||||
bool is_pressed = hotkey_keys_are_active(&input->state, mapping, hotkeys_for_key[possible_hotkey_idx]);
|
||||
|
||||
// store active hotkey, if it is not already active
|
||||
if (is_pressed) {
|
||||
input->state.state_hotkeys[active_hotkeys] = hotkeys_for_key[possible_hotkey_idx];
|
||||
++active_hotkeys;
|
||||
bool is_pressed = hotkey_keys_are_active(&input->state, mapping, hotkeys_for_key[possible_hotkey_idx]);
|
||||
if (!is_pressed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Run callback if defined
|
||||
if (input->input_mapping1.callbacks[hotkeys_for_key[possible_hotkey_idx]] != 0
|
||||
&& old_hotkeys[0] != hotkeys_for_key[possible_hotkey_idx]
|
||||
&& old_hotkeys[1] != hotkeys_for_key[possible_hotkey_idx]
|
||||
&& old_hotkeys[2] != hotkeys_for_key[possible_hotkey_idx]
|
||||
&& old_hotkeys[3] != hotkeys_for_key[possible_hotkey_idx]
|
||||
&& old_hotkeys[4] != hotkeys_for_key[possible_hotkey_idx]
|
||||
) {
|
||||
input->input_mapping1.callbacks[hotkeys_for_key[possible_hotkey_idx]](input->callback_data);
|
||||
}
|
||||
input->state.state_hotkeys[active_hotkeys] = hotkeys_for_key[possible_hotkey_idx];
|
||||
++active_hotkeys;
|
||||
|
||||
// Run callback if defined
|
||||
if (input->input_mapping1.callbacks[hotkeys_for_key[possible_hotkey_idx]] != 0
|
||||
&& old_hotkeys[0] != hotkeys_for_key[possible_hotkey_idx]
|
||||
&& old_hotkeys[1] != hotkeys_for_key[possible_hotkey_idx]
|
||||
&& old_hotkeys[2] != hotkeys_for_key[possible_hotkey_idx]
|
||||
&& old_hotkeys[3] != hotkeys_for_key[possible_hotkey_idx]
|
||||
&& old_hotkeys[4] != hotkeys_for_key[possible_hotkey_idx]
|
||||
) {
|
||||
input->input_mapping1.callbacks[hotkeys_for_key[possible_hotkey_idx]](input->callback_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,25 @@ void update_timing_stat(uint32 stat, const char* function)
|
|||
debug_container->perf_stats[stat].old_tick_count = new_tick_count;
|
||||
}
|
||||
|
||||
inline
|
||||
void update_timing_stat_start(uint32 stat, const char* function)
|
||||
{
|
||||
uint64 new_tick_count = __rdtsc();
|
||||
|
||||
debug_container->perf_stats[stat].old_tick_count = new_tick_count;
|
||||
}
|
||||
|
||||
inline
|
||||
void update_timing_stat_end(uint32 stat, const char* function)
|
||||
{
|
||||
uint64 new_tick_count = __rdtsc();
|
||||
|
||||
debug_container->perf_stats[stat].function = function;
|
||||
debug_container->perf_stats[stat].delta_tick = new_tick_count - debug_container->perf_stats[stat].old_tick_count;
|
||||
debug_container->perf_stats[stat].delta_time = (double) debug_container->perf_stats[stat].delta_tick / (double) debug_container->performance_count_frequency;
|
||||
debug_container->perf_stats[stat].old_tick_count = new_tick_count;
|
||||
}
|
||||
|
||||
inline
|
||||
void reset_counter(int32 id)
|
||||
{
|
||||
|
|
@ -253,6 +272,8 @@ byte* log_get_memory(uint64 size, byte aligned = 1, bool zeroed = false)
|
|||
if (save || debug_container->log_memory.size - debug_container->log_memory.pos < MAX_LOG_LENGTH) {
|
||||
log_to_file();
|
||||
}
|
||||
|
||||
ASSERT_SIMPLE(false);
|
||||
}
|
||||
|
||||
void log(const char* format, LogDataType data_type, void* data, bool should_log, bool save, const char* file, const char* function, int32 line)
|
||||
|
|
@ -297,6 +318,8 @@ byte* log_get_memory(uint64 size, byte aligned = 1, bool zeroed = false)
|
|||
if (save || debug_container->log_memory.size - debug_container->log_memory.pos < MAX_LOG_LENGTH) {
|
||||
log_to_file();
|
||||
}
|
||||
|
||||
ASSERT_SIMPLE(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -32,8 +32,16 @@ struct TimingStat {
|
|||
#if DEBUG || INTERNAL
|
||||
void update_timing_stat(uint32, const char*);
|
||||
#define UPDATE_TIMING_STAT(stat) update_timing_stat(stat, __func__)
|
||||
|
||||
// These are only needed if we need to delay the overwrite by 1 frame (e.g. ui update)
|
||||
void update_timing_stat_start(uint32, const char*);
|
||||
void update_timing_stat_end(uint32, const char*);
|
||||
#define UPDATE_TIMING_STAT_START(stat) update_timing_stat_start(stat, __func__)
|
||||
#define UPDATE_TIMING_STAT_END(stat) update_timing_stat_end(stat, __func__)
|
||||
#else
|
||||
#define UPDATE_TIMING_STAT(stat) ((void) 0)
|
||||
#define UPDATE_TIMING_STAT_START(stat) ((void) 0)
|
||||
#define UPDATE_TIMING_STAT_END(stat) ((void) 0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -102,6 +102,7 @@ struct CSettings {
|
|||
char path[MAX_PATH];
|
||||
bool is_changed = false;
|
||||
byte simd_version;
|
||||
int32 simd_step_size;
|
||||
bool supports_abm;
|
||||
|
||||
// Network data
|
||||
|
|
@ -178,6 +179,7 @@ struct CSettings {
|
|||
byte gpu_anti_aliasing_detail = 0;
|
||||
byte gpu_sharpening = SETTING_TYPE_DISABLED;
|
||||
byte gpu_ambient_occlusion = SETTING_TYPE_DISABLED;
|
||||
byte gpu_color_deficiency;
|
||||
|
||||
bool gpu_gamma_correction = true;
|
||||
bool gpu_normal_mapping = true;
|
||||
|
|
@ -241,38 +243,21 @@ struct CSettings {
|
|||
|
||||
char game_theme[32];
|
||||
|
||||
v4_f32* game_ui_dim[50];
|
||||
v4_f32 game_ui_dim[50];
|
||||
|
||||
// @todo replace settings below with bit flag
|
||||
// UI
|
||||
uint64 ui_visibility_flags = 0;
|
||||
uint64 game_visibility_flags = 0;
|
||||
|
||||
// HUD
|
||||
bool game_hud_animated;
|
||||
bool game_ui_show_hotkeys;
|
||||
|
||||
bool game_show_health_bar_self = false;
|
||||
bool game_show_health_bar_player = false;
|
||||
bool game_show_health_bar_monster = false;
|
||||
bool game_show_health_numbers = false;
|
||||
bool game_show_resource_numbers = false;
|
||||
bool game_show_buffs = false;
|
||||
bool game_show_xp_bar_numbers = true;
|
||||
|
||||
bool game_show_name_self = false;
|
||||
bool game_show_name_player = false;
|
||||
bool game_show_name_monster = false;
|
||||
bool game_show_name_npc = false;
|
||||
bool game_show_title_self = false;
|
||||
bool game_show_title_other = false;
|
||||
byte game_minion_visibility_self = 128;
|
||||
byte game_minion_visibility_player = 128;
|
||||
|
||||
bool game_show_dmg_numbers = false;
|
||||
bool game_show_cooldown_times = false;
|
||||
bool game_show_dodge = true;
|
||||
bool game_show_effect_gains = true; // e.g. XP
|
||||
|
||||
bool game_minimap_show_merchants = false;
|
||||
bool game_minimap_show_quest = false;
|
||||
bool game_minimap_show_dungeons = false;
|
||||
|
|
@ -284,8 +269,6 @@ struct CSettings {
|
|||
bool game_map_show_dungeons = false;
|
||||
bool game_map_show_names = false;
|
||||
|
||||
bool game_show_subtitles = true;
|
||||
|
||||
// Mounts
|
||||
uint32 game_default_mount = 0;
|
||||
|
||||
|
|
@ -413,7 +396,7 @@ void load_settings(CSettings* __restrict client_settings, char* data)
|
|||
|
||||
// Get name
|
||||
name = pos;
|
||||
while (!is_eol(pos) && *pos != '\0' && !is_whitespace(*pos)) {
|
||||
while (!is_eol(pos) && *pos != '\0' && !is_whitespace(*pos) && *pos != '[') {
|
||||
++pos;
|
||||
}
|
||||
|
||||
|
|
@ -441,6 +424,8 @@ void load_settings(CSettings* __restrict client_settings, char* data)
|
|||
client_settings->gpu_aspect_ratio = (f32) atof(pos);
|
||||
} else if (strncmp(name, "_attack_effect_quality", sizeof("_attack_effect_quality") - 1) == 0) {
|
||||
} else if (strncmp(name, "_blur", sizeof("_blur") - 1) == 0) {
|
||||
} else if (strncmp(name, "_color_deficiency", sizeof("_color_deficiency") - 1) == 0) {
|
||||
client_settings->gpu_color_deficiency = (byte) atoi(pos);
|
||||
} else if (strncmp(name, "_brightness", sizeof("_brightness") - 1) == 0) {
|
||||
} else if (strncmp(name, "_camera_shake", sizeof("_camera_shake") - 1) == 0) {
|
||||
} else if (strncmp(name, "_caustics_quality", sizeof("_caustics_quality") - 1) == 0) {
|
||||
|
|
@ -546,8 +531,20 @@ void load_settings(CSettings* __restrict client_settings, char* data)
|
|||
} else if (strncmp(name, "_show_title_other", sizeof("_show_title_other") - 1) == 0) {
|
||||
} else if (strncmp(name, "_show_title_self", sizeof("_show_title_self") - 1) == 0) {
|
||||
} else if (strncmp(name, "_show_xp_bar_numbers", sizeof("_show_xp_bar_numbers") - 1) == 0) {
|
||||
} else if (strncmp(name, "_ui_visibility_flags", sizeof("_ui_visibility_flags") - 1) == 0) {
|
||||
client_settings->ui_visibility_flags = strtoull(pos, &pos, 10);
|
||||
} else if (strncmp(name, "_visibility_flags", sizeof("_visibility_flags") - 1) == 0) {
|
||||
client_settings->game_visibility_flags = strtoull(pos, &pos, 10);
|
||||
} else if (strncmp(name, "_theme", sizeof("_theme") - 1) == 0) {
|
||||
pos += strcpy_to_eol(pos, client_settings->game_theme);
|
||||
} else if (strncmp(name, "_ui_dim", sizeof("_ui_dim") - 1) == 0) {
|
||||
int32 index = strtoul(++pos, &pos, 10);
|
||||
pos += 2;
|
||||
|
||||
client_settings->game_ui_dim[index].x = strtof(pos, &pos); ++pos;
|
||||
client_settings->game_ui_dim[index].y = strtof(pos, &pos); ++pos;
|
||||
client_settings->game_ui_dim[index].width = strtof(pos, &pos); ++pos;
|
||||
client_settings->game_ui_dim[index].height = strtof(pos, &pos);
|
||||
} else if (strncmp(name, "_ui_show_hotkeys", sizeof("_ui_show_hotkeys") - 1) == 0) {
|
||||
} else if (strncmp(name, "_view", sizeof("_view") - 1) == 0) {
|
||||
} else if (strncmp(name, "_window1_dim", sizeof("_window1_dim") - 1) == 0) {
|
||||
|
|
|
|||
|
|
@ -78,6 +78,34 @@
|
|||
#define SETTING_UI_VISIBILITY_APM 2
|
||||
#define SETTING_UI_VISIBILITY_DEBUG 4
|
||||
#define SETTING_UI_VISIBILITY_WIREFRAME 8
|
||||
#define SETTING_UI_VISIBILITY_HOTKEYS 16
|
||||
#define SETTING_UI_VISIBILITY_XP_BAR 32
|
||||
#define SETTING_UI_VISIBILITY_COOLDOWN_TIMER 64
|
||||
#define SETTING_UI_VISIBILITY_MINIMAP 128
|
||||
#define SETTING_UI_VISIBILITY_CHAT 256
|
||||
#define SETTING_UI_VISIBILITY_CLOCK 512
|
||||
#define SETTING_UI_VISIBILITY_SUBTITLES 1024
|
||||
#define SETTING_UI_VISIBILITY_BAR 1024
|
||||
#define SETTING_UI_VISIBILITY_HEALTH 2048
|
||||
#define SETTING_UI_VISIBILITY_RESOURCE 4096
|
||||
#define SETTING_UI_VISIBILITY_INFO 8192 // = e.g. quest info
|
||||
|
||||
#define SETTING_GAME_VISIBILITY_BAR_SELF 1
|
||||
#define SETTING_GAME_VISIBILITY_BAR_PLAYER 2
|
||||
#define SETTING_GAME_VISIBILITY_BAR_OTHER 4
|
||||
#define SETTING_GAME_VISIBILITY_BAR_NUMBERS 8
|
||||
#define SETTING_GAME_VISIBILITY_BUFFS_SELF 16
|
||||
#define SETTING_GAME_VISIBILITY_BUFFS_PLAYER 32
|
||||
#define SETTING_GAME_VISIBILITY_BUFFS_OTHER 64
|
||||
#define SETTING_GAME_VISIBILITY_NAME_SELF 128
|
||||
#define SETTING_GAME_VISIBILITY_NAME_PLAYER 256
|
||||
#define SETTING_GAME_VISIBILITY_NAME_OTHER 512
|
||||
#define SETTING_GAME_VISIBILITY_TITLE_SELF 1024
|
||||
#define SETTING_GAME_VISIBILITY_TITLE_PLAYER 2048
|
||||
#define SETTING_GAME_VISIBILITY_TITLE_OTHER 4096
|
||||
#define SETTING_GAME_VISIBILITY_DMG_NUMBERS 8192
|
||||
#define SETTING_GAME_VISIBILITY_XP_NUMBERS 16384
|
||||
#define SETTING_GAME_VISIBILITY_EFFECTS 32768
|
||||
|
||||
#define SETTING_INPUT_DEVICE_TYPE_MOUSE_KEYBOARD 1
|
||||
#define SETTING_INPUT_DEVICE_TYPE_CONTROLLER 2
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
/**
|
||||
* Jingga
|
||||
*
|
||||
* @copyright Jingga
|
||||
* @license OMS License 2.0
|
||||
* @version 1.0.0
|
||||
* @link https://jingga.app
|
||||
*/
|
||||
#ifndef TOS_OBJECT_FACE_TYPE_H
|
||||
#define TOS_OBJECT_FACE_TYPE_H
|
||||
|
||||
enum FaceType {
|
||||
FACE_TYPE_VERTICES = 1,
|
||||
FACE_TYPE_TEXTURES = 2,
|
||||
FACE_TYPE_NORMALS = 4,
|
||||
FACE_TYPE_COLORS = 8,
|
||||
FACE_TYPE_ALL = 15
|
||||
};
|
||||
|
||||
#endif
|
||||
752
object/Mesh.h
752
object/Mesh.h
|
|
@ -10,7 +10,6 @@
|
|||
#define TOS_OBJECT_MESH_H
|
||||
|
||||
#include "Vertex.h"
|
||||
#include "FaceType.h"
|
||||
#include "../stdlib/Types.h"
|
||||
|
||||
#if _WIN32
|
||||
|
|
@ -43,29 +42,7 @@ struct Mesh {
|
|||
// Separate: [position] [normal] [tex_coord] [color] (separate array for elements)
|
||||
uint32 vertex_type;
|
||||
uint32 vertex_count; // can mean only position or combination of position, normal, tex, ...
|
||||
uint32 normal_count;
|
||||
uint32 tex_coord_count;
|
||||
uint32 color_count;
|
||||
float* vertices;
|
||||
|
||||
// The following references only exist in some situations
|
||||
// depends on the settings above
|
||||
float* normals;
|
||||
float* tex_coords;
|
||||
float* colors;
|
||||
|
||||
uint32 face_type;
|
||||
uint32 face_count;
|
||||
uint32 face_normal_count;
|
||||
uint32 face_tex_coord_count;
|
||||
uint32 face_color_count;
|
||||
uint32* faces;
|
||||
|
||||
// The following references only exist in some situations
|
||||
// depends on the settings above
|
||||
uint32* face_textures;
|
||||
uint32* face_normals;
|
||||
uint32* face_colors;
|
||||
f32* vertices;
|
||||
|
||||
// @todo this only works if you have sub meshes e.g. one for body, one for hat, one for weapon etc.
|
||||
uint32 vertex_ref;
|
||||
|
|
@ -95,7 +72,8 @@ struct Mesh {
|
|||
// WARNING: mesh needs to have memory already reserved and asigned to data
|
||||
void mesh_from_file_txt(
|
||||
Mesh* mesh,
|
||||
byte* data
|
||||
byte* data,
|
||||
RingMemory* ring
|
||||
) {
|
||||
char* pos = (char *) data;
|
||||
|
||||
|
|
@ -109,15 +87,24 @@ void mesh_from_file_txt(
|
|||
|
||||
mesh->vertices = (f32 *) mesh->data;
|
||||
|
||||
mesh->vertex_count = 0;
|
||||
mesh->normal_count = 0;
|
||||
mesh->tex_coord_count = 0;
|
||||
mesh->color_count = 0;
|
||||
|
||||
mesh->face_count = 0;
|
||||
mesh->face_normal_count = 0;
|
||||
mesh->face_tex_coord_count = 0;
|
||||
mesh->face_color_count = 0;
|
||||
// @todo The temp memory reservation is bad, once the file format is really finalized we need to change this.
|
||||
// We can't just assume these sizes
|
||||
int32 vertex_count = 0;
|
||||
f32* vertices = (f32 *) ring_get_memory(ring, 500000 * sizeof(f32));
|
||||
|
||||
int32 normal_count = 0;
|
||||
f32* normals = (f32 *) ring_get_memory(ring, 500000 * sizeof(f32));
|
||||
|
||||
int32 tex_coord_count = 0;
|
||||
f32* tex_coords = (f32 *) ring_get_memory(ring, 500000 * sizeof(f32));
|
||||
|
||||
int32 color_count = 0;
|
||||
f32* colors = (f32 *) ring_get_memory(ring, 500000 * sizeof(f32));
|
||||
|
||||
int32 face_type = VERTEX_TYPE_POSITION;
|
||||
int32 face_count = 0;
|
||||
int32* faces = (int32 *) ring_get_memory(ring, 500000 * sizeof(int32));
|
||||
|
||||
uint32 temp_color_count = 0;
|
||||
|
||||
|
|
@ -133,6 +120,7 @@ void mesh_from_file_txt(
|
|||
// Parse type
|
||||
// WARNING: The code below could fail if [1] is outside of range
|
||||
// However that should never happen for well formed files
|
||||
// @todo create an enum to make it easier to read
|
||||
int32 state = 0;
|
||||
if (*pos == 'v' && pos[1] == ' ') {
|
||||
state = 1;
|
||||
|
|
@ -162,6 +150,8 @@ void mesh_from_file_txt(
|
|||
state = 13;
|
||||
} else if (*pos == 'u' && pos[3] == 'h') {
|
||||
state = 14;
|
||||
} else if (*pos == 'c' && pos[3] == 'o') {
|
||||
state = 15;
|
||||
} else {
|
||||
// not supported or comment
|
||||
while (*pos != '\n' && *pos != '\0') {
|
||||
|
|
@ -194,60 +184,51 @@ void mesh_from_file_txt(
|
|||
case 0: break;
|
||||
case 1: {
|
||||
// 'v'
|
||||
if (mesh->vertex_count == 0) {
|
||||
if (vertex_count == 0) {
|
||||
mesh->vertex_type |= VERTEX_TYPE_POSITION;
|
||||
}
|
||||
|
||||
mesh->vertices[mesh->vertex_count * 3] = strtof(pos, &pos); ++pos;
|
||||
mesh->vertices[mesh->vertex_count * 3 + 1] = strtof(pos, &pos); ++pos;
|
||||
mesh->vertices[mesh->vertex_count * 3 + 2] = strtof(pos, &pos); ++pos;
|
||||
vertices[vertex_count * 3] = strtof(pos, &pos); ++pos;
|
||||
vertices[vertex_count * 3 + 1] = strtof(pos, &pos); ++pos;
|
||||
vertices[vertex_count * 3 + 2] = strtof(pos, &pos); ++pos;
|
||||
|
||||
// has color information
|
||||
// @todo Move to own case statement // 'co'
|
||||
if (*pos != '\n' && pos[1] != ' ' && pos[1] != '\n') {
|
||||
if (mesh->vertex_count == 0) {
|
||||
if (vertex_count == 0) {
|
||||
mesh->vertex_type |= VERTEX_TYPE_COLOR;
|
||||
}
|
||||
|
||||
mesh->vertices[mesh->vertex_count * 12 + 8] = strtof(pos, &pos); ++pos;
|
||||
mesh->vertices[mesh->vertex_count * 12 + 9] = strtof(pos, &pos); ++pos;
|
||||
mesh->vertices[mesh->vertex_count * 12 + 10] = strtof(pos, &pos); ++pos;
|
||||
vertices[vertex_count * 12 + 8] = strtof(pos, &pos); ++pos;
|
||||
vertices[vertex_count * 12 + 9] = strtof(pos, &pos); ++pos;
|
||||
vertices[vertex_count * 12 + 10] = strtof(pos, &pos); ++pos;
|
||||
|
||||
// handle optional alpha [a]
|
||||
if (*pos != '\n' && pos[1] != ' ' && pos[1] != '\n') {
|
||||
mesh->vertices[mesh->vertex_count * 12 + 11] = strtof(pos, &pos); ++pos;
|
||||
vertices[vertex_count * 12 + 11] = strtof(pos, &pos); ++pos;
|
||||
} else {
|
||||
mesh->vertices[mesh->vertex_count * 12 + 11] = 1.0f;
|
||||
vertices[vertex_count * 12 + 11] = 1.0f;
|
||||
}
|
||||
|
||||
++temp_color_count;
|
||||
}
|
||||
|
||||
++mesh->vertex_count;
|
||||
++vertex_count;
|
||||
} break;
|
||||
case 2: {
|
||||
// 'vn'
|
||||
// @bug This requires normals to be defined before textures
|
||||
if (mesh->normal_count == 0) {
|
||||
mesh->normals = mesh->vertices + mesh->vertex_count * 3;
|
||||
}
|
||||
normals[normal_count * 3] = strtof(pos, &pos); ++pos;
|
||||
normals[normal_count * 3 + 1] = strtof(pos, &pos); ++pos;
|
||||
normals[normal_count * 3 + 2] = strtof(pos, &pos); ++pos;
|
||||
|
||||
mesh->normals[mesh->normal_count * 3] = strtof(pos, &pos); ++pos;
|
||||
mesh->normals[mesh->normal_count * 3 + 1] = strtof(pos, &pos); ++pos;
|
||||
mesh->normals[mesh->normal_count * 3 + 2] = strtof(pos, &pos); ++pos;
|
||||
|
||||
++mesh->normal_count;
|
||||
++normal_count;
|
||||
} break;
|
||||
case 3: {
|
||||
// 'vt'
|
||||
if (mesh->tex_coord_count == 0) {
|
||||
mesh->tex_coords = mesh->vertices + mesh->vertex_count * 3 + mesh->normal_count * 3;
|
||||
}
|
||||
tex_coords[tex_coord_count * 2] = strtof(pos, &pos); ++pos;
|
||||
tex_coords[tex_coord_count * 2 + 1] = strtof(pos, &pos); ++pos;
|
||||
|
||||
mesh->tex_coords[mesh->tex_coord_count * 2] = strtof(pos, &pos); ++pos;
|
||||
mesh->tex_coords[mesh->tex_coord_count * 2 + 1] = strtof(pos, &pos); ++pos;
|
||||
|
||||
++mesh->tex_coord_count;
|
||||
++tex_coord_count;
|
||||
} break;
|
||||
case 4: {
|
||||
// 'vp'
|
||||
|
|
@ -280,10 +261,6 @@ void mesh_from_file_txt(
|
|||
} break;
|
||||
case 7: {
|
||||
// 'f'
|
||||
if (mesh->face_count == 0) {
|
||||
mesh->faces = (uint32 *) (mesh->vertices + mesh->vertex_count * 3 + mesh->normal_count * 3 + mesh->tex_coord_count * 2 + mesh->color_count * 4);
|
||||
}
|
||||
|
||||
int32 ftype = 0;
|
||||
char* tmp = pos;
|
||||
while (*tmp != ' ') {
|
||||
|
|
@ -303,43 +280,43 @@ void mesh_from_file_txt(
|
|||
while (*pos != '\0' && *pos != '\n') {
|
||||
if (ftype == 0) {
|
||||
// v1 v2 v3 ...
|
||||
if (mesh->face_count == 0) {
|
||||
mesh->face_type = FACE_TYPE_VERTICES;
|
||||
if (face_count == 0) {
|
||||
face_type = VERTEX_TYPE_POSITION;
|
||||
}
|
||||
|
||||
mesh->faces[(mesh->face_count * max_blocks * 1) + block] = strtol(pos, &pos, 10) - 1; ++pos;
|
||||
faces[(face_count * max_blocks * 1) + block] = strtol(pos, &pos, 10) - 1; ++pos;
|
||||
} else if (ftype == 1) {
|
||||
// v1/vt1 v2/vt2 v3/vt3 ...
|
||||
if (mesh->face_count == 0) {
|
||||
mesh->face_type = FACE_TYPE_VERTICES | FACE_TYPE_TEXTURES;
|
||||
if (face_count == 0) {
|
||||
face_type = VERTEX_TYPE_POSITION | VERTEX_TYPE_TEXTURE_COORD;
|
||||
}
|
||||
|
||||
mesh->faces[(mesh->face_count * max_blocks * 2) + block * 2] = strtol(pos, &pos, 10) - 1; ++pos;
|
||||
mesh->faces[(mesh->face_count * max_blocks * 2) + block * 2 + 1] = strtol(pos, &pos, 10) - 1; ++pos;
|
||||
faces[(face_count * max_blocks * 2) + block * 2] = strtol(pos, &pos, 10) - 1; ++pos;
|
||||
faces[(face_count * max_blocks * 2) + block * 2 + 1] = strtol(pos, &pos, 10) - 1; ++pos;
|
||||
} else if (ftype == 2) {
|
||||
// v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3 ...
|
||||
if (mesh->face_count == 0) {
|
||||
mesh->face_type = FACE_TYPE_VERTICES | FACE_TYPE_TEXTURES | FACE_TYPE_NORMALS;
|
||||
if (face_count == 0) {
|
||||
face_type = VERTEX_TYPE_POSITION | VERTEX_TYPE_TEXTURE_COORD | VERTEX_TYPE_NORMAL;
|
||||
}
|
||||
|
||||
mesh->faces[(mesh->face_count * max_blocks * 3) + block * 3] = strtol(pos, &pos, 10) - 1; ++pos;
|
||||
mesh->faces[(mesh->face_count * max_blocks * 3) + block * 3 + 1] = strtol(pos, &pos, 10) - 1; ++pos;
|
||||
mesh->faces[(mesh->face_count * max_blocks * 3) + block * 3 + 2] = strtol(pos, &pos, 10) - 1; ++pos;
|
||||
faces[(face_count * max_blocks * 3) + block * 3] = strtol(pos, &pos, 10) - 1; ++pos;
|
||||
faces[(face_count * max_blocks * 3) + block * 3 + 1] = strtol(pos, &pos, 10) - 1; ++pos;
|
||||
faces[(face_count * max_blocks * 3) + block * 3 + 2] = strtol(pos, &pos, 10) - 1; ++pos;
|
||||
} else if (ftype == 3) {
|
||||
// v1//vn1 v2//vn2 v3//vn3 ...
|
||||
if (mesh->face_count == 0) {
|
||||
mesh->face_type = FACE_TYPE_VERTICES | FACE_TYPE_NORMALS;
|
||||
if (face_count == 0) {
|
||||
face_type = VERTEX_TYPE_POSITION | VERTEX_TYPE_NORMAL;
|
||||
}
|
||||
|
||||
mesh->faces[(mesh->face_count * max_blocks * 2) + block * 2] = strtol(pos, &pos, 10) - 1; ++pos;
|
||||
faces[(face_count * max_blocks * 2) + block * 2] = strtol(pos, &pos, 10) - 1; ++pos;
|
||||
++pos;
|
||||
mesh->faces[(mesh->face_count * max_blocks * 2) + block * 2 + 1] = strtol(pos, &pos, 10) - 1; ++pos;
|
||||
faces[(face_count * max_blocks * 2) + block * 2 + 1] = strtol(pos, &pos, 10) - 1; ++pos;
|
||||
}
|
||||
|
||||
++block;
|
||||
}
|
||||
|
||||
++mesh->face_count;
|
||||
++face_count;
|
||||
} break;
|
||||
case 8: {
|
||||
// 'g'
|
||||
|
|
@ -405,15 +382,83 @@ void mesh_from_file_txt(
|
|||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
mesh->vertex_type = face_type;
|
||||
|
||||
// Populate the vertex data based on the face data
|
||||
if (face_count > 0) {
|
||||
int32 vertex_size = 3;
|
||||
int32 face_size = 1;
|
||||
|
||||
// We need this since in the text file textures are defined before the normals (v/vt/vn)
|
||||
int32 normal_offset = ((mesh->vertex_type & VERTEX_TYPE_TEXTURE_COORD) ? 1 : 0);
|
||||
|
||||
int32 texture_offset = ((mesh->vertex_type & VERTEX_TYPE_NORMAL) ? 1 : 0);
|
||||
|
||||
if (mesh->vertex_type & VERTEX_TYPE_NORMAL) {
|
||||
vertex_size += 3;
|
||||
++face_size;
|
||||
}
|
||||
|
||||
if (mesh->vertex_type & VERTEX_TYPE_TEXTURE_COORD) {
|
||||
vertex_size += 2;
|
||||
++face_size;
|
||||
}
|
||||
|
||||
if (mesh->vertex_type & VERTEX_TYPE_COLOR) {
|
||||
vertex_size += 4;
|
||||
++face_size;
|
||||
}
|
||||
|
||||
mesh->vertex_count = face_count * 3;
|
||||
|
||||
// Every face consists of 3 vertecies -> *3
|
||||
for (int32 i = 0; i < face_count * 3; ++i) {
|
||||
const f32* vertex_pos = &vertices[faces[i * face_size] * 3];
|
||||
memcpy(
|
||||
mesh->data + i * vertex_size * sizeof(f32),
|
||||
vertex_pos,
|
||||
3 * sizeof(f32)
|
||||
);
|
||||
|
||||
// Normals come before texture coordinates since we most likely need them more than texture (e.g. pre-copmuting of shadows on cpu etc.)
|
||||
if (mesh->vertex_type & VERTEX_TYPE_NORMAL) {
|
||||
const f32* normal_pos = &normals[faces[i * face_size + 1 + normal_offset] * 3];
|
||||
|
||||
memcpy(
|
||||
mesh->data + i * vertex_size * sizeof(f32)
|
||||
+ 3 * sizeof(f32), // Offset by position
|
||||
normal_pos,
|
||||
3 * sizeof(f32)
|
||||
);
|
||||
}
|
||||
|
||||
if (mesh->vertex_type & VERTEX_TYPE_TEXTURE_COORD) {
|
||||
const f32* texture_pos = &tex_coords[faces[i * face_size + 1] * 2];
|
||||
|
||||
memcpy(
|
||||
mesh->data + i * vertex_size * sizeof(f32)
|
||||
+ 3 * sizeof(f32) // Offset by position
|
||||
+ texture_offset * 3 * sizeof(f32), // Offset by normal
|
||||
texture_pos,
|
||||
2 * sizeof(f32)
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No face data -> just output the vertices
|
||||
mesh->vertex_count = vertex_count;
|
||||
memcpy(mesh->vertices, vertices, 3 * sizeof(f32) * mesh->vertex_count);
|
||||
}
|
||||
}
|
||||
|
||||
enum ObjectLoadingRestriction {
|
||||
OBJECT_LOADING_RESTRICTION_POSITION = 1,
|
||||
OBJECT_LOADING_RESTRICTION_NORMAL = 2,
|
||||
OBJECT_LOADING_RESTRICTION_TEXTURE = 4,
|
||||
OBJECT_LOADING_RESTRICTION_COLOR = 8,
|
||||
OBJECT_LOADING_RESTRICTION_FACES = 16,
|
||||
OBJECT_LOADING_RESTRICTION_EVERYTHING = 31
|
||||
enum MeshLoadingRestriction {
|
||||
MESH_LOADING_RESTRICTION_POSITION = 1,
|
||||
MESH_LOADING_RESTRICTION_NORMAL = 2,
|
||||
MESH_LOADING_RESTRICTION_TEXTURE = 4,
|
||||
MESH_LOADING_RESTRICTION_COLOR = 8,
|
||||
MESH_LOADING_RESTRICTION_FACES = 16,
|
||||
MESH_LOADING_RESTRICTION_EVERYTHING = 31
|
||||
};
|
||||
|
||||
// @todo sometimes we don't care about some data, we should have an option which defines which data should be loaded
|
||||
|
|
@ -424,8 +469,8 @@ int32 mesh_from_file(
|
|||
const char* path,
|
||||
Mesh* mesh,
|
||||
const char* group = NULL,
|
||||
int32 load_format = OBJECT_LOADING_RESTRICTION_EVERYTHING,
|
||||
int32 size = 8
|
||||
int32 load_format = MESH_LOADING_RESTRICTION_EVERYTHING,
|
||||
int32 steps = 8
|
||||
)
|
||||
{
|
||||
FileBody file;
|
||||
|
|
@ -444,22 +489,10 @@ int32 mesh_from_file(
|
|||
mesh->vertex_count = *((int32 *) pos);
|
||||
pos += sizeof(mesh->vertex_count);
|
||||
|
||||
mesh->normal_count = *((int32 *) pos);
|
||||
pos += sizeof(mesh->normal_count);
|
||||
|
||||
mesh->tex_coord_count = *((int32 *) pos);
|
||||
pos += sizeof(mesh->tex_coord_count);
|
||||
|
||||
mesh->color_count = *((int32 *) pos);
|
||||
pos += sizeof(mesh->color_count);
|
||||
|
||||
#if !_WIN32 && !__LITTLE_ENDIAN
|
||||
mesh->version = endian_swap(mesh->version);
|
||||
mesh->vertex_type = endian_swap(mesh->vertex_type);
|
||||
mesh->verted_count = endian_swap(mesh->verted_count);
|
||||
mesh->normal_count = endian_swap(mesh->normal_count);
|
||||
mesh->tex_coord_count = endian_swap(mesh->tex_coord_count);
|
||||
mesh->color_count = endian_swap(mesh->color_count);
|
||||
#endif
|
||||
|
||||
int32 vertex_size = 0;
|
||||
|
|
@ -488,108 +521,17 @@ int32 mesh_from_file(
|
|||
offset += sizeof(f32) * vertex_size * mesh->vertex_count;
|
||||
}
|
||||
|
||||
if (mesh->normal_count > 0) {
|
||||
memcpy(mesh->data + offset, pos, sizeof(f32) * 3 * mesh->normal_count);
|
||||
mesh->normals = (f32 *) (mesh->data + offset);
|
||||
|
||||
pos += sizeof(f32) * 3 * mesh->normal_count;
|
||||
offset += sizeof(f32) * 3 * mesh->normal_count;
|
||||
}
|
||||
|
||||
if (mesh->tex_coord_count > 0) {
|
||||
memcpy(mesh->data + offset, pos, sizeof(f32) * 3 * mesh->tex_coord_count);
|
||||
mesh->tex_coords = (f32 *) (mesh->data + offset);
|
||||
|
||||
pos += sizeof(f32) * 2 * mesh->tex_coord_count;
|
||||
offset += sizeof(f32) * 2 * mesh->tex_coord_count;
|
||||
}
|
||||
|
||||
if (mesh->color_count > 0) {
|
||||
memcpy(mesh->data + offset, pos, sizeof(f32) * 4 * mesh->color_count);
|
||||
mesh->colors = (f32 *) (mesh->data + offset);
|
||||
|
||||
pos += sizeof(f32) * 4 * mesh->color_count;
|
||||
offset += sizeof(f32) * 4 * mesh->color_count;
|
||||
}
|
||||
|
||||
// Read face data
|
||||
mesh->face_type = *((int32 *) pos);
|
||||
pos += sizeof(mesh->face_type);
|
||||
|
||||
mesh->face_count = *((int32 *) pos);
|
||||
pos += sizeof(mesh->face_count);
|
||||
|
||||
mesh->face_normal_count = *((int32 *) pos);
|
||||
pos += sizeof(mesh->face_normal_count);
|
||||
|
||||
mesh->face_tex_coord_count = *((int32 *) pos);
|
||||
pos += sizeof(mesh->face_tex_coord_count);
|
||||
|
||||
mesh->face_color_count = *((int32 *) pos);
|
||||
pos += sizeof(mesh->face_color_count);
|
||||
|
||||
#if !_WIN32 && !__LITTLE_ENDIAN
|
||||
mesh->face_type = endian_swap(mesh->face_type);
|
||||
mesh->face_count = endian_swap(mesh->face_count);
|
||||
mesh->face_normal_count = endian_swap(mesh->face_normal_count);
|
||||
mesh->face_tex_coord_count = endian_swap(mesh->face_tex_coord_count);
|
||||
mesh->face_color_count = endian_swap(mesh->face_color_count);
|
||||
/*
|
||||
#if OPENGL
|
||||
if (mesh->vertex_type & VERTEX_TYPE_NORMAL) {
|
||||
for (int i = 0; i < mesh->vertex_count; ++i) {
|
||||
mesh->vertices[i * vertex_size + 3] *= -1;
|
||||
mesh->vertices[i * vertex_size + 3 + 1] *= -1;
|
||||
mesh->vertices[i * vertex_size + 3 + 2] *= -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int32 face_size = 0;
|
||||
if (mesh->face_type & FACE_TYPE_VERTICES) {
|
||||
face_size += 3;
|
||||
}
|
||||
|
||||
if ((mesh->face_type & FACE_TYPE_NORMALS)) {
|
||||
face_size += 3;
|
||||
}
|
||||
|
||||
if ((mesh->face_type & FACE_TYPE_TEXTURES)) {
|
||||
face_size += 3;
|
||||
}
|
||||
|
||||
if ((mesh->face_type & FACE_TYPE_COLORS)) {
|
||||
face_size += 3;
|
||||
}
|
||||
|
||||
// faces can be either in the form
|
||||
// f: v/vt/vn ...
|
||||
// or:
|
||||
// f: v ...
|
||||
// f: vn ...
|
||||
// f: vt ...
|
||||
if (mesh->face_count > 0) {
|
||||
memcpy(mesh->data + offset, pos, sizeof(uint32) * face_size * mesh->face_count);
|
||||
mesh->faces = (uint32 *) (mesh->data + offset);
|
||||
|
||||
pos += sizeof(uint32) * face_size * mesh->face_count;
|
||||
offset += sizeof(uint32) * face_size * mesh->face_count;
|
||||
}
|
||||
|
||||
if (mesh->face_normal_count > 0) {
|
||||
memcpy(mesh->data + offset, pos, sizeof(uint32) * 3 * mesh->face_normal_count);
|
||||
mesh->face_normals = (uint32 *) (mesh->data + offset);
|
||||
|
||||
pos += sizeof(uint32) * 3 * mesh->face_normal_count;
|
||||
offset += sizeof(uint32) * 3 * mesh->face_normal_count;
|
||||
}
|
||||
|
||||
if (mesh->face_tex_coord_count > 0) {
|
||||
memcpy(mesh->data + offset, pos, sizeof(uint32) * 3 * mesh->face_tex_coord_count);
|
||||
mesh->face_textures = (uint32 *) (mesh->data + offset);
|
||||
|
||||
pos += sizeof(uint32) * 3 * mesh->face_tex_coord_count;
|
||||
offset += sizeof(uint32) * 3 * mesh->face_tex_coord_count;
|
||||
}
|
||||
|
||||
if (mesh->face_color_count > 0) {
|
||||
memcpy(mesh->data + offset, pos, sizeof(uint32) * 3 * mesh->face_color_count);
|
||||
mesh->face_colors = (uint32 *) (mesh->data + offset);
|
||||
|
||||
pos += sizeof(uint32) * 3 * mesh->face_color_count;
|
||||
offset += sizeof(uint32) * 3 * mesh->face_color_count;
|
||||
}
|
||||
*/
|
||||
|
||||
SWAP_ENDIAN_LITTLE_SIMD(
|
||||
(int32 *) mesh->data,
|
||||
|
|
@ -605,9 +547,8 @@ void mesh_to_file(
|
|||
RingMemory* ring,
|
||||
const char* path,
|
||||
const Mesh* mesh,
|
||||
int32 vertex_save_format = VERTEX_TYPE_POSITION,
|
||||
int32 face_save_format = FACE_TYPE_VERTICES,
|
||||
int32 size = 8
|
||||
int32 vertex_save_format = VERTEX_TYPE_ALL,
|
||||
int32 steps = 8
|
||||
)
|
||||
{
|
||||
FileBody file;
|
||||
|
|
@ -616,7 +557,6 @@ void mesh_to_file(
|
|||
// @todo check the actual size, we are currently more or less guessing
|
||||
file.size = sizeof(mesh)
|
||||
+ sizeof(Vertex3D) * mesh->vertex_count
|
||||
+ sizeof(f32) * 12 * mesh->vertex_count
|
||||
+ 4096;
|
||||
|
||||
file.content = ring_get_memory(ring, file.size, 64);
|
||||
|
|
@ -627,377 +567,57 @@ void mesh_to_file(
|
|||
pos += sizeof(mesh->version);
|
||||
|
||||
// vertices
|
||||
if (vertex_save_format == VERTEX_TYPE_ALL) {
|
||||
vertex_save_format = mesh->vertex_type;
|
||||
}
|
||||
|
||||
memcpy(pos, &vertex_save_format, sizeof(vertex_save_format));
|
||||
pos += sizeof(vertex_save_format);
|
||||
|
||||
memcpy(pos, &mesh->vertex_count, sizeof(mesh->vertex_count));
|
||||
pos += sizeof(mesh->vertex_count);
|
||||
|
||||
// We are can save the mesh in a different format from the current format -> need to adjust some values
|
||||
uint32 normal_count = mesh->normal_count == 0 && (mesh->vertex_type & VERTEX_TYPE_NORMAL)
|
||||
? mesh->vertex_count
|
||||
: mesh->normal_count;
|
||||
|
||||
memcpy(pos, &normal_count, sizeof(mesh->normal_count));
|
||||
pos += sizeof(mesh->normal_count);
|
||||
|
||||
uint32 tex_coord_count = mesh->tex_coord_count == 0 && (mesh->vertex_type & VERTEX_TYPE_TEXTURE_COORD)
|
||||
? mesh->vertex_count
|
||||
: mesh->tex_coord_count;
|
||||
|
||||
memcpy(pos, &tex_coord_count, sizeof(mesh->tex_coord_count));
|
||||
pos += sizeof(mesh->tex_coord_count);
|
||||
|
||||
uint32 color_count = mesh->color_count == 0 && (mesh->vertex_type & VERTEX_TYPE_COLOR)
|
||||
? mesh->vertex_count
|
||||
: mesh->color_count;
|
||||
|
||||
memcpy(pos, &color_count, sizeof(mesh->color_count));
|
||||
pos += sizeof(mesh->color_count);
|
||||
|
||||
// verticies
|
||||
if (mesh->vertex_count > 0) {
|
||||
int32 vertex_size = 0;
|
||||
if (mesh->vertex_type & VERTEX_TYPE_POSITION) {
|
||||
vertex_size += 3;
|
||||
}
|
||||
|
||||
if (mesh->vertex_type & VERTEX_TYPE_NORMAL) {
|
||||
vertex_size += 3;
|
||||
}
|
||||
|
||||
if (mesh->vertex_type & VERTEX_TYPE_TEXTURE_COORD) {
|
||||
vertex_size += 2;
|
||||
}
|
||||
|
||||
if (mesh->vertex_type & VERTEX_TYPE_COLOR) {
|
||||
vertex_size += 4;
|
||||
}
|
||||
|
||||
int32 out_vertex_size = 0;
|
||||
if (vertex_save_format & VERTEX_TYPE_POSITION) {
|
||||
out_vertex_size += 3;
|
||||
}
|
||||
|
||||
if (vertex_save_format & VERTEX_TYPE_NORMAL) {
|
||||
out_vertex_size += 3;
|
||||
}
|
||||
|
||||
if (vertex_save_format & VERTEX_TYPE_TEXTURE_COORD) {
|
||||
out_vertex_size += 2;
|
||||
}
|
||||
|
||||
if (vertex_save_format & VERTEX_TYPE_COLOR) {
|
||||
out_vertex_size += 4;
|
||||
}
|
||||
|
||||
if ((mesh->vertex_type == VERTEX_TYPE_ALL && vertex_save_format == VERTEX_TYPE_ALL)
|
||||
|| (mesh->vertex_type == VERTEX_TYPE_POSITION && vertex_save_format == VERTEX_TYPE_POSITION)
|
||||
) {
|
||||
// data is the same as in the array
|
||||
memcpy(pos, mesh->vertices, vertex_size * sizeof(f32) * mesh->vertex_count);
|
||||
pos += vertex_size * sizeof(f32) * mesh->vertex_count;
|
||||
} else {
|
||||
f32* temp = mesh->vertices;
|
||||
f32* end = mesh->vertices + mesh->vertex_count * vertex_size;
|
||||
|
||||
int32 offset;
|
||||
|
||||
byte* vertice_start = pos;
|
||||
|
||||
// @bug index gets increased every iteration BUT different groups and objects in the source may have different data
|
||||
// This comes again down to how to handle hierarchal data with multiple groups and objects
|
||||
int32 index = 0;
|
||||
|
||||
// iterate over all vertices to create new output format
|
||||
while (temp < end) {
|
||||
// @question why do I even need offset? couldn't I just directly manipulate temp?
|
||||
offset = 0;
|
||||
|
||||
// First we save everything in one large array if that is the setting
|
||||
if (vertex_save_format & VERTEX_TYPE_POSITION) {
|
||||
if (mesh->vertex_type & VERTEX_TYPE_POSITION) {
|
||||
memcpy(pos, temp, sizeof(f32) * 3);
|
||||
pos += sizeof(f32) * 3;
|
||||
|
||||
offset += 3;
|
||||
} else {
|
||||
memset(pos, 0, sizeof(f32) * 3);
|
||||
pos += sizeof(f32) * 3;
|
||||
}
|
||||
}
|
||||
|
||||
// We want separate arrays for some data
|
||||
if ((mesh->vertex_type & VERTEX_TYPE_NORMAL) && !(vertex_save_format & VERTEX_TYPE_NORMAL)) {
|
||||
// go to end of vertices * shift by previous array sizes + shift by current vertex -> creates one continous array with this data
|
||||
memcpy(vertice_start
|
||||
+ sizeof(f32) * out_vertex_size * mesh->vertex_count
|
||||
+ index * sizeof(f32) * 3, temp + offset, sizeof(f32) * 3);
|
||||
|
||||
offset += 3;
|
||||
} else if (vertex_save_format & VERTEX_TYPE_NORMAL) {
|
||||
if (mesh->vertex_type & VERTEX_TYPE_NORMAL) {
|
||||
memcpy(pos, temp + offset, sizeof(f32) * 3);
|
||||
pos += sizeof(f32) * 3;
|
||||
|
||||
offset += 3;
|
||||
} else {
|
||||
memset(pos, 0, sizeof(f32) * 3);
|
||||
pos += sizeof(f32) * 3;
|
||||
}
|
||||
}
|
||||
|
||||
// We want separate arrays for some data
|
||||
if ((mesh->vertex_type & VERTEX_TYPE_TEXTURE_COORD) && !(vertex_save_format & VERTEX_TYPE_TEXTURE_COORD)) {
|
||||
// go to end of vertices * shift by previous array sizes + shift by current vertex -> creates one continous array with this data
|
||||
memcpy(vertice_start
|
||||
+ sizeof(f32) * out_vertex_size * mesh->vertex_count
|
||||
+ sizeof(f32) * normal_count * 3
|
||||
+ index * sizeof(f32) * 3, temp + offset, sizeof(f32) * 3);
|
||||
|
||||
offset += 2;
|
||||
} else if (vertex_save_format & VERTEX_TYPE_TEXTURE_COORD) {
|
||||
if (mesh->vertex_type & VERTEX_TYPE_TEXTURE_COORD) {
|
||||
memcpy(pos, temp + offset, sizeof(f32) * 2);
|
||||
pos += sizeof(f32) * 2;
|
||||
|
||||
offset += 2;
|
||||
} else {
|
||||
memset(pos, 0, sizeof(f32) * 2);
|
||||
pos += sizeof(f32) * 2;
|
||||
}
|
||||
}
|
||||
|
||||
// We want separate arrays for some data
|
||||
if ((mesh->vertex_type & VERTEX_TYPE_COLOR) && !(vertex_save_format & VERTEX_TYPE_COLOR)) {
|
||||
// go to end of vertices * shift by previous array sizes + shift by current vertex -> creates one continous array with this data
|
||||
memcpy(vertice_start
|
||||
+ sizeof(f32) * out_vertex_size * mesh->vertex_count
|
||||
+ sizeof(f32) * normal_count * 3
|
||||
+ sizeof(f32) * tex_coord_count * 2
|
||||
+ index * sizeof(f32) * 4, temp + offset, sizeof(f32) * 4);
|
||||
|
||||
offset += 4;
|
||||
} else if (vertex_save_format & VERTEX_TYPE_COLOR) {
|
||||
if (mesh->vertex_type & VERTEX_TYPE_COLOR) {
|
||||
memcpy(pos, temp + offset, sizeof(f32) * 4);
|
||||
pos += sizeof(f32) * 4;
|
||||
|
||||
offset += 4;
|
||||
} else {
|
||||
memset(pos, 0, sizeof(f32) * 4);
|
||||
pos += sizeof(f32) * 4;
|
||||
}
|
||||
}
|
||||
|
||||
temp += offset;
|
||||
++index;
|
||||
}
|
||||
}
|
||||
|
||||
// check if we have clean array data already -> output this array data directly
|
||||
if (mesh->normals && mesh->normal_count > 0) {
|
||||
memcpy(pos, mesh->normals, mesh->normal_count * sizeof(f32) * 3);
|
||||
pos += mesh->normal_count * sizeof(f32) * 3;
|
||||
}
|
||||
|
||||
if (mesh->tex_coords && mesh->tex_coord_count > 0) {
|
||||
memcpy(pos, mesh->tex_coords, mesh->tex_coord_count * sizeof(f32) * 2);
|
||||
pos += mesh->tex_coord_count * sizeof(f32) * 2;
|
||||
}
|
||||
|
||||
if (mesh->colors && mesh->color_count > 0) {
|
||||
memcpy(pos, mesh->colors, mesh->color_count * sizeof(f32) * 4);
|
||||
pos += mesh->color_count * sizeof(f32) * 4;
|
||||
}
|
||||
int32 vertex_size = 0;
|
||||
if (mesh->vertex_type & VERTEX_TYPE_POSITION) {
|
||||
vertex_size += 3;
|
||||
}
|
||||
|
||||
// faces/indices
|
||||
memcpy(pos, &face_save_format, sizeof(face_save_format));
|
||||
pos += sizeof(face_save_format);
|
||||
if (mesh->vertex_type & VERTEX_TYPE_NORMAL) {
|
||||
vertex_size += 3;
|
||||
}
|
||||
|
||||
memcpy(pos, &mesh->face_count, sizeof(mesh->face_count));
|
||||
pos += sizeof(mesh->face_count);
|
||||
if (mesh->vertex_type & VERTEX_TYPE_TEXTURE_COORD) {
|
||||
vertex_size += 2;
|
||||
}
|
||||
|
||||
// We are can save the mesh in a different format from the current format -> need to adjust some values
|
||||
uint32 face_normal_count = mesh->face_normal_count == 0 && (mesh->face_type & FACE_TYPE_NORMALS)
|
||||
? mesh->face_count
|
||||
: mesh->face_normal_count;
|
||||
if (mesh->vertex_type & VERTEX_TYPE_COLOR) {
|
||||
vertex_size += 4;
|
||||
}
|
||||
|
||||
memcpy(pos, &face_normal_count, sizeof(mesh->face_normal_count));
|
||||
pos += sizeof(mesh->face_normal_count);
|
||||
int32 out_vertex_size = 0;
|
||||
if (vertex_save_format & VERTEX_TYPE_POSITION) {
|
||||
out_vertex_size += 3;
|
||||
}
|
||||
|
||||
uint32 face_tex_coord_count = mesh->face_tex_coord_count == 0 && (mesh->face_type & FACE_TYPE_TEXTURES)
|
||||
? mesh->face_count
|
||||
: mesh->face_tex_coord_count;
|
||||
if (vertex_save_format & VERTEX_TYPE_NORMAL) {
|
||||
out_vertex_size += 3;
|
||||
}
|
||||
|
||||
memcpy(pos, &face_tex_coord_count, sizeof(mesh->face_tex_coord_count));
|
||||
pos += sizeof(mesh->face_tex_coord_count);
|
||||
if (vertex_save_format & VERTEX_TYPE_TEXTURE_COORD) {
|
||||
out_vertex_size += 2;
|
||||
}
|
||||
|
||||
uint32 face_color_count = mesh->face_color_count == 0 && (mesh->face_type & FACE_TYPE_COLORS)
|
||||
? mesh->face_count
|
||||
: mesh->face_color_count;
|
||||
if (vertex_save_format & VERTEX_TYPE_COLOR) {
|
||||
out_vertex_size += 4;
|
||||
}
|
||||
|
||||
memcpy(pos, &face_color_count, sizeof(mesh->face_color_count));
|
||||
pos += sizeof(mesh->face_color_count);
|
||||
|
||||
if (mesh->face_count > 0) {
|
||||
// WARNING: Carefull, we again assume only 3 elements per face
|
||||
|
||||
int32 face_size = 0;
|
||||
if (mesh->face_type & FACE_TYPE_VERTICES) {
|
||||
face_size += 3;
|
||||
}
|
||||
|
||||
if (mesh->face_type & FACE_TYPE_NORMALS) {
|
||||
face_size += 3;
|
||||
}
|
||||
|
||||
if (mesh->face_type & FACE_TYPE_TEXTURES) {
|
||||
face_size += 3;
|
||||
}
|
||||
|
||||
if (mesh->face_type & FACE_TYPE_COLORS) {
|
||||
face_size += 3;
|
||||
}
|
||||
|
||||
int32 out_face_size = 0;
|
||||
if (face_save_format & FACE_TYPE_VERTICES) {
|
||||
out_face_size += 3;
|
||||
}
|
||||
|
||||
if (face_save_format & FACE_TYPE_NORMALS) {
|
||||
out_face_size += 3;
|
||||
}
|
||||
|
||||
if (face_save_format & FACE_TYPE_TEXTURES) {
|
||||
out_face_size += 3;
|
||||
}
|
||||
|
||||
if (face_save_format & FACE_TYPE_COLORS) {
|
||||
out_face_size += 3;
|
||||
}
|
||||
|
||||
if ((mesh->face_type == FACE_TYPE_ALL && face_save_format == FACE_TYPE_ALL)
|
||||
|| (mesh->face_type == FACE_TYPE_VERTICES && face_save_format == FACE_TYPE_VERTICES)
|
||||
) {
|
||||
// data is the same as in the array
|
||||
memcpy(pos, mesh->faces, face_size * sizeof(uint32) * mesh->face_count);
|
||||
pos += face_size * sizeof(uint32) * mesh->face_count;
|
||||
} else {
|
||||
uint32* temp = mesh->faces;
|
||||
uint32* end = mesh->faces + mesh->face_count * face_size;
|
||||
|
||||
int32 offset;
|
||||
|
||||
byte* face_start = pos;
|
||||
|
||||
// @bug index gets increased every iteration BUT different groups and objects in the source may have different data
|
||||
// This comes again down to how to handle hierarchal data with multiple groups and objects
|
||||
int32 index = 0;
|
||||
|
||||
// iterate over all faces to create new output format
|
||||
// one iteration represents 1 block (a block could be v/vt/vn or, v, or v//vn, ...)
|
||||
while (temp < end) {
|
||||
// @question why do I even need offset? couldn't I just directly manipulate temp?
|
||||
offset = 0;
|
||||
|
||||
// First we save everything in one large array if that is the setting
|
||||
if (face_save_format & FACE_TYPE_VERTICES) {
|
||||
if (mesh->face_type & FACE_TYPE_VERTICES) {
|
||||
memcpy(pos, temp, sizeof(uint32));
|
||||
pos += sizeof(uint32);
|
||||
|
||||
offset += 1;
|
||||
} else {
|
||||
memset(pos, 0, sizeof(f32));
|
||||
pos += sizeof(f32);
|
||||
}
|
||||
}
|
||||
|
||||
// We want separate arrays for some data
|
||||
if (mesh->face_type & FACE_TYPE_NORMALS && !(face_save_format & FACE_TYPE_NORMALS)) {
|
||||
// go to end of faces * shift by previous array sizes + shift by current face -> creates one continous array with this data
|
||||
memcpy(face_start
|
||||
+ sizeof(uint32) * out_face_size * mesh->face_count
|
||||
+ index * sizeof(uint32), temp + offset, sizeof(uint32));
|
||||
|
||||
offset += 1;
|
||||
} else if (face_save_format & FACE_TYPE_NORMALS) {
|
||||
if (mesh->face_type & FACE_TYPE_NORMALS) {
|
||||
memcpy(pos, temp + offset, sizeof(uint32));
|
||||
pos += sizeof(uint32);
|
||||
|
||||
offset += 1;
|
||||
} else {
|
||||
memset(pos, 0, sizeof(uint32));
|
||||
pos += sizeof(uint32);
|
||||
}
|
||||
}
|
||||
|
||||
// We want separate arrays for some data
|
||||
if (mesh->face_type & FACE_TYPE_TEXTURES && !(face_save_format & FACE_TYPE_TEXTURES)) {
|
||||
// go to end of faces * shift by previous array sizes + shift by current face -> creates one continous array with this data
|
||||
memcpy(face_start
|
||||
+ sizeof(uint32) * out_face_size * mesh->face_count
|
||||
+ sizeof(uint32) * 3 * face_normal_count
|
||||
+ index * sizeof(uint32), temp + offset, sizeof(uint32));
|
||||
|
||||
offset += 1;
|
||||
} else if (face_save_format & FACE_TYPE_TEXTURES) {
|
||||
if (mesh->face_type & FACE_TYPE_TEXTURES) {
|
||||
memcpy(pos, temp + offset, sizeof(uint32));
|
||||
pos += sizeof(uint32);
|
||||
|
||||
offset += 1;
|
||||
} else {
|
||||
memset(pos, 0, sizeof(uint32));
|
||||
pos += sizeof(uint32);
|
||||
}
|
||||
}
|
||||
|
||||
// We want separate arrays for some data
|
||||
if (mesh->face_type & VERTEX_TYPE_COLOR && !(face_save_format & VERTEX_TYPE_COLOR)) {
|
||||
// go to end of faces * shift by previous array sizes + shift by current face -> creates one continous array with this data
|
||||
memcpy(face_start
|
||||
+ sizeof(uint32) * out_face_size * mesh->face_count
|
||||
+ sizeof(uint32) * 3 * face_normal_count
|
||||
+ sizeof(uint32) * 3 * face_tex_coord_count
|
||||
+ index * sizeof(uint32), temp + offset, sizeof(uint32));
|
||||
|
||||
offset += 1;
|
||||
} else if (face_save_format & VERTEX_TYPE_COLOR) {
|
||||
if (mesh->face_type & VERTEX_TYPE_COLOR) {
|
||||
memcpy(pos, temp + offset, sizeof(uint32));
|
||||
pos += sizeof(uint32);
|
||||
|
||||
offset += 1;
|
||||
} else {
|
||||
memset(pos, 0, sizeof(uint32));
|
||||
pos += sizeof(uint32);
|
||||
}
|
||||
}
|
||||
|
||||
temp += offset;
|
||||
++index;
|
||||
}
|
||||
}
|
||||
|
||||
// check if we have clean array data already -> output this array data directly
|
||||
if (mesh->face_normals && mesh->face_normal_count > 0) {
|
||||
memcpy(pos, mesh->face_normals, mesh->face_normal_count * sizeof(uint32) * 3);
|
||||
pos += mesh->face_normal_count * sizeof(uint32) * 3;
|
||||
}
|
||||
|
||||
if (mesh->face_textures && mesh->face_tex_coord_count > 0) {
|
||||
memcpy(pos, mesh->face_textures, mesh->face_tex_coord_count * sizeof(uint32) * 3);
|
||||
pos += mesh->face_tex_coord_count * sizeof(uint32) * 3;
|
||||
}
|
||||
|
||||
if (mesh->face_colors && mesh->face_color_count > 0) {
|
||||
memcpy(pos, mesh->face_colors, mesh->face_color_count * sizeof(uint32) * 3);
|
||||
pos += mesh->face_color_count * sizeof(uint32) * 3;
|
||||
}
|
||||
if ((mesh->vertex_type == VERTEX_TYPE_ALL && vertex_save_format == VERTEX_TYPE_ALL)
|
||||
|| (mesh->vertex_type == vertex_save_format)
|
||||
) {
|
||||
// data is the same as in the array
|
||||
memcpy(pos, mesh->vertices, vertex_size * sizeof(f32) * mesh->vertex_count);
|
||||
pos += vertex_size * sizeof(f32) * mesh->vertex_count;
|
||||
}
|
||||
|
||||
file.size = pos - file.content;
|
||||
|
|
@ -1009,14 +629,6 @@ void mesh_to_file(
|
|||
steps
|
||||
);
|
||||
|
||||
/*
|
||||
FileBody file2;
|
||||
file2.content = ring_get_memory(ring, file.size, 64);
|
||||
file2.size = encode_lzp(file.content, file.size, file2.content);
|
||||
|
||||
file_write(path, &file2);
|
||||
*/
|
||||
|
||||
file_write(path, &file);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,11 +43,8 @@ struct Texture {
|
|||
// If yes remember to update prepare_texture()
|
||||
|
||||
byte texture_data_type;
|
||||
byte texture_wrap_type_s;
|
||||
byte texture_wrap_type_t;
|
||||
byte texture_wrap_type_r;
|
||||
|
||||
byte texture_minification;
|
||||
byte data[16];
|
||||
|
||||
Image image;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ enum VertexType {
|
|||
VERTEX_TYPE_NORMAL = 2,
|
||||
VERTEX_TYPE_TEXTURE_COORD = 4,
|
||||
VERTEX_TYPE_COLOR = 8,
|
||||
VERTEX_TYPE_ALL = 15
|
||||
VERTEX_TYPE_ALL = 15,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -24,6 +24,23 @@
|
|||
|
||||
#define strtok_r strtok_s
|
||||
|
||||
inline
|
||||
time_t system_time()
|
||||
{
|
||||
SYSTEMTIME systemTime;
|
||||
FILETIME fileTime;
|
||||
ULARGE_INTEGER largeInt;
|
||||
|
||||
GetLocalTime(&systemTime);
|
||||
SystemTimeToFileTime(&systemTime, &fileTime);
|
||||
|
||||
// Convert FILETIME to a 64-bit integer
|
||||
largeInt.LowPart = fileTime.dwLowDateTime;
|
||||
largeInt.HighPart = fileTime.dwHighDateTime;
|
||||
|
||||
return ((time_t) (largeInt.QuadPart / 10000000ULL)) - ((time_t) 11644473600ULL);
|
||||
}
|
||||
|
||||
// @todo Consider to implement directly mapped files (CreateFileMapping) for certain files (e.g. map data or texture data, ...)
|
||||
|
||||
inline void relative_to_absolute(const char* rel, char* path)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include "../../../audio/AudioSetting.h"
|
||||
#include "../../../utils/MathUtils.h"
|
||||
#include "../../../log/Log.h"
|
||||
#include "../../../audio/Audio.cpp"
|
||||
|
||||
struct DirectSoundSetting {
|
||||
LPDIRECTSOUND8 audio_handle;
|
||||
|
|
@ -191,6 +192,9 @@ void audio_play_buffer(AudioSetting* setting, DirectSoundSetting* api_setting)
|
|||
0
|
||||
);
|
||||
|
||||
// @performance why are we copying again, we already created our buffer, now we have to copy it again?!
|
||||
// Ideally we should have already copied it into the correct final one, no?
|
||||
// We should probably provide a audio_buffer_fill function, that does this -> we could remove one whole memcopy
|
||||
memcpy(
|
||||
(void *) region1,
|
||||
(void *) setting->buffer,
|
||||
|
|
@ -211,4 +215,43 @@ void audio_play_buffer(AudioSetting* setting, DirectSoundSetting* api_setting)
|
|||
setting->sample_buffer_size = 0;
|
||||
}
|
||||
|
||||
// Basically the same as audio_play_buffer but by using this we can avoid one copy
|
||||
// The only reason we have audio_play_buffer is that there might be situations where this is not possible
|
||||
inline
|
||||
void audio_fill_play_buffer(AudioSetting* setting, uint32 to_fill, Audio* sound, DirectSoundSetting* api_setting)
|
||||
{
|
||||
setting->sample_buffer_size = to_fill;
|
||||
|
||||
if (setting->sample_buffer_size == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!setting->is_playing) {
|
||||
audio_play(setting, api_setting);
|
||||
}
|
||||
|
||||
void *region1;
|
||||
DWORD region1_size;
|
||||
|
||||
void *region2;
|
||||
DWORD region2_size;
|
||||
|
||||
DWORD bytes_to_lock = (setting->sample_index * setting->sample_size) % setting->buffer_size;
|
||||
|
||||
api_setting->secondary_buffer->Lock(
|
||||
bytes_to_lock, setting->sample_buffer_size,
|
||||
®ion1, ®ion1_size,
|
||||
®ion2, ®ion2_size,
|
||||
0
|
||||
);
|
||||
|
||||
audio_fill_buffer(setting, to_fill, sound, (int16 *) region1, (int32) region1_size, (int16 *) region2, (int32) region2_size);
|
||||
|
||||
api_setting->secondary_buffer->Unlock(region1, region1_size, region2, region2_size);
|
||||
|
||||
setting->sample_index += setting->sample_buffer_size / setting->sample_size;
|
||||
setting->sample_buffer_size = 0;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
#include "../../../audio/AudioSetting.h"
|
||||
#include "../../../utils/MathUtils.h"
|
||||
#include "../../../log/Log.h"
|
||||
#include "../../../audio/Audio.cpp"
|
||||
|
||||
struct XAudio2Setting {
|
||||
IXAudio2* audio_handle;
|
||||
|
|
@ -196,6 +197,9 @@ void audio_play_buffer(AudioSetting* setting, XAudio2Setting* api_setting) {
|
|||
|
||||
uint32 idx = setting->sample_output % 2;
|
||||
|
||||
// @performance why are we copying again, we already created our buffer, now we have to copy it again?!
|
||||
// Ideally we should have already copied it into the correct final one, no?
|
||||
// We should probably provide a audio_buffer_fill function, that does this -> we could remove one whole memcopy
|
||||
memcpy(
|
||||
(void *) api_setting->internal_buffer[idx].pAudioData,
|
||||
setting->buffer,
|
||||
|
|
@ -212,4 +216,33 @@ void audio_play_buffer(AudioSetting* setting, XAudio2Setting* api_setting) {
|
|||
setting->sample_buffer_size = 0;
|
||||
}
|
||||
|
||||
// Basically the same as audio_play_buffer but by using this we can avoid one copy
|
||||
// The only reason we have audio_play_buffer is that there might be situations where this is not possible
|
||||
inline
|
||||
void audio_fill_play_buffer(AudioSetting* setting, uint32 to_fill, Audio* sound, XAudio2Setting* api_setting)
|
||||
{
|
||||
setting->sample_buffer_size = to_fill;
|
||||
|
||||
if (!api_setting->source_voice || setting->sample_buffer_size == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!setting->is_playing) {
|
||||
audio_play(setting, api_setting);
|
||||
}
|
||||
|
||||
uint32 idx = setting->sample_output % 2;
|
||||
|
||||
audio_fill_buffer(setting, to_fill, sound, (int16 *) api_setting->internal_buffer[idx].pAudioData, to_fill);
|
||||
|
||||
if (!SUCCEEDED(api_setting->source_voice->SubmitSourceBuffer(&api_setting->internal_buffer[idx]))) {
|
||||
LOG("Xaudio2: SubmitSourceBuffer failed\n", true, true);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
setting->sample_index += setting->sample_buffer_size / setting->sample_size;
|
||||
setting->sample_buffer_size = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
164
platform/win32/input/HidInput.h
Normal file
164
platform/win32/input/HidInput.h
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
/**
|
||||
* Jingga
|
||||
*
|
||||
* @copyright Jingga
|
||||
* @license OMS License 2.0
|
||||
* @version 1.0.0
|
||||
* @link https://jingga.app
|
||||
*/
|
||||
#ifndef TOS_PLATFORM_WIN32_INPUT_HID_H
|
||||
#define TOS_PLATFORM_WIN32_INPUT_HID_H
|
||||
|
||||
#include <windows.h>
|
||||
#include <setupapi.h>
|
||||
#include <hidsdi.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../../../input/Input.h"
|
||||
#include "../../../input/ControllerType.h"
|
||||
#include "../../../memory/RingMemory.h"
|
||||
#include "controller/DualShock4.h"
|
||||
|
||||
#pragma comment(lib, "hid.lib")
|
||||
#pragma comment(lib, "setupapi.lib")
|
||||
|
||||
void hid_init_contorllers(Input* __restrict states, int32 state_count, RingMemory* ring) {
|
||||
|
||||
HANDLE* controller_handles = NULL;
|
||||
|
||||
// Get the GUID for HID devices
|
||||
GUID hid_guid;
|
||||
HidD_GetHidGuid(&hid_guid);
|
||||
|
||||
// Get a handle to the device information set
|
||||
HDEVINFO device_info_set = SetupDiGetClassDevs(&hid_guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
||||
if (device_info_set == INVALID_HANDLE_VALUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
SP_DEVICE_INTERFACE_DATA device_interface_data;
|
||||
device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
||||
|
||||
DWORD device_index = 0;
|
||||
int32 controller_found = 0;
|
||||
|
||||
while (SetupDiEnumDeviceInterfaces(device_info_set, NULL, &hid_guid, device_index, &device_interface_data)) {
|
||||
++device_index;
|
||||
DWORD required_size = 0;
|
||||
|
||||
// First call to get required buffer size for device detail data
|
||||
SetupDiGetDeviceInterfaceDetail(device_info_set, &device_interface_data, NULL, 0, &required_size, NULL);
|
||||
PSP_DEVICE_INTERFACE_DETAIL_DATA device_detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA) ring_get_memory(ring, required_size, 8);
|
||||
device_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
|
||||
|
||||
// Get device interface detail
|
||||
if (!SetupDiGetDeviceInterfaceDetail(device_info_set, &device_interface_data, device_detail_data, required_size, NULL, NULL)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Open the device
|
||||
HANDLE device_handle = CreateFile(
|
||||
device_detail_data->DevicePath,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_OVERLAPPED,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (device_handle == INVALID_HANDLE_VALUE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the device is a gamepad or joystick by reading its attributes
|
||||
HIDD_ATTRIBUTES attributes;
|
||||
attributes.Size = sizeof(HIDD_ATTRIBUTES);
|
||||
if (!HidD_GetAttributes(device_handle, &attributes)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the preparsed data to check usage page and usage ID
|
||||
PHIDP_PREPARSED_DATA preparsed_data;
|
||||
if (!HidD_GetPreparsedData(device_handle, &preparsed_data)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
HIDP_CAPS caps;
|
||||
if (HidP_GetCaps(preparsed_data, &caps) == HIDP_STATUS_SUCCESS) {
|
||||
HidD_FreePreparsedData(preparsed_data);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for game controllers (Generic Desktop Page, Gamepad or Joystick Usage)
|
||||
if (caps.UsagePage == 0x01 && caps.Usage == 0x05) {
|
||||
if (states[controller_found].handle_controller != NULL) {
|
||||
++controller_found;
|
||||
}
|
||||
|
||||
states[controller_found].handle_controller = device_handle;
|
||||
// @bug This is not always true, how to check?
|
||||
states[controller_found].connection_type = INPUT_CONNECTION_TYPE_USB;
|
||||
|
||||
if (attributes.VendorID == 0x054C
|
||||
&& (attributes.ProductID == 0x05C4 || attributes.ProductID == 0x09CC)
|
||||
) {
|
||||
states[controller_found].controller_type = CONTROLLER_TYPE_DUALSHOCK4;
|
||||
} else if (attributes.VendorID == 0x054C
|
||||
&& (attributes.ProductID == 0x0CE6 || attributes.ProductID == 0x0DF2)
|
||||
) {
|
||||
states[controller_found].controller_type = CONTROLLER_TYPE_DUALSENSE;
|
||||
} else if (attributes.VendorID == 0x045E && attributes.ProductID == 0x02E0) {
|
||||
states[controller_found].controller_type = CONTROLLER_TYPE_XBOX_360;
|
||||
} else if (attributes.VendorID == 0x045E && attributes.ProductID == 0x02FF) {
|
||||
states[controller_found].controller_type = CONTROLLER_TYPE_XBOX_ONE;
|
||||
} else if (attributes.VendorID == 0x045E && attributes.ProductID == 0x028E) {
|
||||
states[controller_found].controller_type = CONTROLLER_TYPE_XBOX_S;
|
||||
} else {
|
||||
states[controller_found].controller_type = CONTROLLER_TYPE_OTHER;
|
||||
}
|
||||
} else if (caps.UsagePage == 0x01 && caps.Usage == 0x04) {
|
||||
if (states[controller_found].handle_controller != NULL) {
|
||||
++controller_found;
|
||||
}
|
||||
|
||||
states[controller_found].handle_controller = device_handle;
|
||||
// @bug This is not always true, how to check?
|
||||
states[controller_found].connection_type = INPUT_CONNECTION_TYPE_USB;
|
||||
states[controller_found].controller_type = CONTROLLER_TYPE_OTHER;
|
||||
} else {
|
||||
CloseHandle(device_handle);
|
||||
}
|
||||
|
||||
HidD_FreePreparsedData(preparsed_data);
|
||||
}
|
||||
|
||||
SetupDiDestroyDeviceInfoList(device_info_set);
|
||||
}
|
||||
|
||||
uint32 hid_divice_poll(Input* state, uint64 time) {
|
||||
UCHAR buffer[128];
|
||||
DWORD bytes_read;
|
||||
|
||||
if (!ReadFile(state->handle_controller, buffer, sizeof(buffer), &bytes_read, NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ControllerInput controller = {};
|
||||
switch(state->controller_type) {
|
||||
case CONTROLLER_TYPE_DUALSHOCK4: {
|
||||
input_map_dualshock4(&controller, state->connection_type, buffer);
|
||||
} break;
|
||||
default: {
|
||||
};
|
||||
}
|
||||
input_set_controller_state(state, &controller, time);
|
||||
|
||||
state->state_change_button = true;
|
||||
state->time_last_input_check = time;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "../../../stdlib/Types.h"
|
||||
#include "../../../input/Input.h"
|
||||
#include "../../../input/ControllerType.h"
|
||||
#include "../../../input/ControllerInput.h"
|
||||
#include "controller/DualShock4.h"
|
||||
#include "../../../utils/TestUtils.h"
|
||||
|
|
@ -24,9 +25,11 @@
|
|||
|
||||
#define INPUT_MOUSE_BUTTON_1 1
|
||||
#define INPUT_MOUSE_BUTTON_2 2
|
||||
#define INPUT_MOUSE_BUTTON_3 4
|
||||
#define INPUT_MOUSE_BUTTON_4 8
|
||||
#define INPUT_MOUSE_BUTTON_5 16
|
||||
#define INPUT_MOUSE_BUTTON_3 3
|
||||
#define INPUT_MOUSE_BUTTON_4 4
|
||||
#define INPUT_MOUSE_BUTTON_5 5
|
||||
#define INPUT_MOUSE_BUTTON_WHEEL 6
|
||||
#define INPUT_MOUSE_BUTTON_HWHEEL 7
|
||||
|
||||
// IMPORTANT:
|
||||
// Even if it is nowhere documented (at least not to our knowledge) the GetRawInputDeviceInfoA, GetRawInputBuffer functions requried
|
||||
|
|
@ -53,7 +56,6 @@ int rawinput_init_mousekeyboard(HWND hwnd, Input* __restrict states, RingMemory*
|
|||
|
||||
int32 mouse_found = 0;
|
||||
int32 keyboard_found = 0;
|
||||
int32 controller_found = 0;
|
||||
|
||||
int32 i;
|
||||
for (i = 0; i < device_count; ++i) {
|
||||
|
|
@ -108,6 +110,7 @@ int rawinput_init_mousekeyboard(HWND hwnd, Input* __restrict states, RingMemory*
|
|||
return i;
|
||||
}
|
||||
|
||||
// WARNING: While this works we highly recommend to use hid_init_contorllers
|
||||
int rawinput_init_controllers(HWND hwnd, Input* __restrict states, RingMemory* ring)
|
||||
{
|
||||
uint32 device_count;
|
||||
|
|
@ -126,9 +129,6 @@ int rawinput_init_controllers(HWND hwnd, Input* __restrict states, RingMemory* r
|
|||
}
|
||||
|
||||
uint32 cb_size = 256;
|
||||
|
||||
int32 mouse_found = 0;
|
||||
int32 keyboard_found = 0;
|
||||
int32 controller_found = 0;
|
||||
|
||||
int32 i;
|
||||
|
|
@ -150,6 +150,24 @@ int rawinput_init_controllers(HWND hwnd, Input* __restrict states, RingMemory* r
|
|||
// @bug This is not always true, how to check?
|
||||
states[controller_found].connection_type = INPUT_CONNECTION_TYPE_USB;
|
||||
|
||||
if (rdi.hid.dwVendorId == 0x054C
|
||||
&& (rdi.hid.dwProductId == 0x05C4 || rdi.hid.dwProductId == 0x09CC)
|
||||
) {
|
||||
states[controller_found].controller_type = CONTROLLER_TYPE_DUALSHOCK4;
|
||||
} else if (rdi.hid.dwVendorId == 0x054C
|
||||
&& (rdi.hid.dwProductId == 0x0CE6 || rdi.hid.dwProductId == 0x0DF2)
|
||||
) {
|
||||
states[controller_found].controller_type = CONTROLLER_TYPE_DUALSENSE;
|
||||
} else if (rdi.hid.dwVendorId == 0x045E && rdi.hid.dwProductId == 0x02E0) {
|
||||
states[controller_found].controller_type = CONTROLLER_TYPE_XBOX_360;
|
||||
} else if (rdi.hid.dwVendorId == 0x045E && rdi.hid.dwProductId == 0x02FF) {
|
||||
states[controller_found].controller_type = CONTROLLER_TYPE_XBOX_ONE;
|
||||
} else if (rdi.hid.dwVendorId == 0x045E && rdi.hid.dwProductId == 0x028E) {
|
||||
states[controller_found].controller_type = CONTROLLER_TYPE_XBOX_S;
|
||||
} else {
|
||||
states[controller_found].controller_type = CONTROLLER_TYPE_OTHER;
|
||||
}
|
||||
|
||||
// Gamepad
|
||||
rid[0].usUsagePage = 0x01;
|
||||
rid[0].usUsage = 0x05;
|
||||
|
|
@ -168,6 +186,7 @@ int rawinput_init_controllers(HWND hwnd, Input* __restrict states, RingMemory* r
|
|||
states[controller_found].handle_controller = pRawInputDeviceList[i].hDevice;
|
||||
// @bug This is not always true, how to check?
|
||||
states[controller_found].connection_type = INPUT_CONNECTION_TYPE_USB;
|
||||
states[controller_found].controller_type = CONTROLLER_TYPE_OTHER;
|
||||
|
||||
// Joystick
|
||||
rid[0].usUsagePage = 0x01;
|
||||
|
|
@ -222,54 +241,51 @@ int32 input_raw_handle(RAWINPUT* __restrict raw, Input* states, int32 state_coun
|
|||
|
||||
if (raw->data.mouse.usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN) {
|
||||
key.key_state = KEY_STATE_PRESSED;
|
||||
key.key_id = 1;
|
||||
key.key_id = INPUT_MOUSE_BUTTON_1;
|
||||
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_LEFT_BUTTON_UP) {
|
||||
key.key_state = KEY_STATE_RELEASED;
|
||||
key.key_id = 1;
|
||||
key.key_id = INPUT_MOUSE_BUTTON_1;
|
||||
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN) {
|
||||
key.key_state = KEY_STATE_PRESSED;
|
||||
key.key_id = 2;
|
||||
key.key_id = INPUT_MOUSE_BUTTON_2;
|
||||
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP) {
|
||||
key.key_state = KEY_STATE_RELEASED;
|
||||
key.key_id = 2;
|
||||
key.key_id = INPUT_MOUSE_BUTTON_2;
|
||||
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_DOWN) {
|
||||
key.key_state = KEY_STATE_PRESSED;
|
||||
key.key_id = 3;
|
||||
key.key_id = INPUT_MOUSE_BUTTON_3;
|
||||
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_UP) {
|
||||
key.key_state = KEY_STATE_RELEASED;
|
||||
key.key_id = 3;
|
||||
key.key_id = INPUT_MOUSE_BUTTON_3;
|
||||
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_DOWN) {
|
||||
key.key_state = KEY_STATE_PRESSED;
|
||||
key.key_id = 4;
|
||||
key.key_id = INPUT_MOUSE_BUTTON_4;
|
||||
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_UP) {
|
||||
key.key_state = KEY_STATE_RELEASED;
|
||||
key.key_id = 4;
|
||||
key.key_id = INPUT_MOUSE_BUTTON_4;
|
||||
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_DOWN) {
|
||||
key.key_state = KEY_STATE_PRESSED;
|
||||
key.key_id = 5;
|
||||
key.key_id = INPUT_MOUSE_BUTTON_5;
|
||||
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_UP) {
|
||||
key.key_state = KEY_STATE_RELEASED;
|
||||
key.key_id = 5;
|
||||
key.key_id = INPUT_MOUSE_BUTTON_5;
|
||||
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_WHEEL) {
|
||||
key.key_state = KEY_STATE_RELEASED;
|
||||
key.key_id = INPUT_MOUSE_BUTTON_WHEEL;
|
||||
key.value = (int16) raw->data.mouse.usButtonData;
|
||||
} else if (raw->data.mouse.usButtonFlags & RI_MOUSE_HWHEEL) {
|
||||
key.key_state = KEY_STATE_RELEASED;
|
||||
key.key_id = INPUT_MOUSE_BUTTON_HWHEEL;
|
||||
key.value = (int16) raw->data.mouse.usButtonData;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* @todo implement
|
||||
if (raw->data.mouse.usButtonFlags & RI_MOUSE_WHEEL) {
|
||||
states[i].state.wheel_delta += raw->data.mouse.usButtonData;
|
||||
}
|
||||
|
||||
if (raw->data.mouse.usButtonFlags & RI_MOUSE_HWHEEL) {
|
||||
states[i].state.hwheel_delta += raw->data.mouse.usButtonData;
|
||||
}
|
||||
*/
|
||||
|
||||
// @question is mouse wheel really considered a button change?
|
||||
|
||||
++input_count;
|
||||
|
||||
key.key_id |= INPUT_MOUSE_PREFIX;
|
||||
key.value = 0;
|
||||
key.time = time;
|
||||
|
||||
input_set_state(&states[i].state, &key);
|
||||
|
|
@ -337,34 +353,38 @@ int32 input_raw_handle(RAWINPUT* __restrict raw, Input* states, int32 state_coun
|
|||
InputKey key = {(uint16) (raw->data.keyboard.VKey | INPUT_KEYBOARD_PREFIX), new_state, 0, time};
|
||||
input_set_state(&states[i].state, &key);
|
||||
states[i].state_change_button = true;
|
||||
} else if (raw->header.dwType == RIM_TYPEHID) {
|
||||
if (raw->header.dwSize > sizeof(RAWINPUT)) {
|
||||
// @performance This shouldn't be done every time, it should be polling based
|
||||
// Controllers often CONSTANTLY send data -> really bad
|
||||
// Maybe we can add timer usage instead of polling?
|
||||
while (i < state_count
|
||||
&& states[i].handle_controller != raw->header.hDevice
|
||||
) {
|
||||
++i;
|
||||
}
|
||||
|
||||
if (i >= state_count || !states[i].connection_type
|
||||
|| time - states[i].time_last_input_check < 5
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// @todo Find a way to handle most common controllers
|
||||
// DualSense
|
||||
// Xbox
|
||||
// Xinput
|
||||
// Best way would probably to define the controller type in the input
|
||||
ControllerInput controller = {};
|
||||
input_map_dualshock4(&controller, states[i].connection_type, raw->data.hid.bRawData);
|
||||
input_set_controller_state(&states[i], &controller, time);
|
||||
|
||||
states[i].time_last_input_check = time;
|
||||
} else if (raw->header.dwType == RIM_TYPEHID
|
||||
&& raw->header.dwSize > sizeof(RAWINPUT)
|
||||
) {
|
||||
// @performance This shouldn't be done every time, it should be polling based
|
||||
// Controllers often CONSTANTLY send data -> really bad
|
||||
// Maybe we can add timer usage instead of polling?
|
||||
// But we would still need to register them, right?
|
||||
// Ideally we wouldn't even have to register them then because they would still pollute the general buffer
|
||||
while (i < state_count
|
||||
&& states[i].handle_controller != raw->header.hDevice
|
||||
) {
|
||||
++i;
|
||||
}
|
||||
|
||||
if (i >= state_count || !states[i].connection_type
|
||||
|| time - states[i].time_last_input_check < 5
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ControllerInput controller = {};
|
||||
switch(states[i].controller_type) {
|
||||
case CONTROLLER_TYPE_DUALSHOCK4: {
|
||||
input_map_dualshock4(&controller, states[i].connection_type, raw->data.hid.bRawData);
|
||||
} break;
|
||||
default: {
|
||||
};
|
||||
}
|
||||
input_set_controller_state(&states[i], &controller, time);
|
||||
|
||||
states[i].state_change_button = true;
|
||||
states[i].time_last_input_check = time;
|
||||
}
|
||||
|
||||
return input_count;
|
||||
|
|
@ -389,9 +409,7 @@ void input_handle(LPARAM lParam, Input* __restrict states, int state_count, Ring
|
|||
|
||||
int32 input_handle_buffered(int buffer_size, Input* __restrict states, int state_count, RingMemory* ring, uint64 time)
|
||||
{
|
||||
int32 input_count = 0;
|
||||
uint32 cb_size;
|
||||
|
||||
GetRawInputBuffer(NULL, &cb_size, sizeof(RAWINPUTHEADER));
|
||||
if (!cb_size) {
|
||||
return 0;
|
||||
|
|
@ -402,6 +420,7 @@ int32 input_handle_buffered(int buffer_size, Input* __restrict states, int state
|
|||
|
||||
PRAWINPUT raw_input = (PRAWINPUT) ring_get_memory(ring, cb_size, 4);
|
||||
|
||||
int32 input_count = 0;
|
||||
uint32 input;
|
||||
|
||||
while (true) {
|
||||
|
|
|
|||
|
|
@ -161,6 +161,10 @@ struct v4_f32 {
|
|||
f32 x, y, z, w;
|
||||
};
|
||||
|
||||
struct {
|
||||
f32 x1, y1, x2, y2;
|
||||
};
|
||||
|
||||
struct {
|
||||
f32 r, g, b, a;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -789,4 +789,85 @@ inline bool all_false(int16_32 a)
|
|||
// @todo from down here we can optimize some of the code by NOT using the wrappers
|
||||
// the code is self contained and we could use te intrinsic functions directly
|
||||
|
||||
inline
|
||||
void simd_mult(const int16* a, f32 b, int16* result, int32 size, int32 steps)
|
||||
{
|
||||
int32 i = 0;
|
||||
|
||||
if (steps == 16) {
|
||||
__m512i a_16;
|
||||
__m512 af_lo, af_hi;
|
||||
__m512 b_16 = _mm512_set1_ps(b);
|
||||
__m512 result_lo, result_hi;
|
||||
__m512i result_16;
|
||||
|
||||
for (; i <= size - steps; i += steps) {
|
||||
a_16 = _mm512_loadu_si512((__m512i*) a);
|
||||
|
||||
af_lo = _mm512_cvtepi32_ps(_mm512_cvtepi16_epi32(_mm512_extracti64x4_epi64(a_16, 0)));
|
||||
af_hi = _mm512_cvtepi32_ps(_mm512_cvtepi16_epi32(_mm512_extracti64x4_epi64(a_16, 1)));
|
||||
|
||||
result_lo = _mm512_mul_ps(af_lo, b_16);
|
||||
result_hi = _mm512_mul_ps(af_hi, b_16);
|
||||
|
||||
result_16 = _mm512_packs_epi32(_mm512_cvtps_epi32(result_lo), _mm512_cvtps_epi32(result_hi));
|
||||
_mm512_storeu_si512((__m512i*) result, result_16);
|
||||
|
||||
a += steps;
|
||||
result += steps;
|
||||
}
|
||||
} else if (steps == 8) {
|
||||
__m256i a_8;
|
||||
__m256 af_lo, af_hi;
|
||||
__m256 b_8 = _mm256_set1_ps(b);
|
||||
__m256 result_lo, result_hi;
|
||||
__m256i result_8;
|
||||
|
||||
for (; i <= size - steps; i += steps) {
|
||||
a_8 = _mm256_loadu_si256((__m256i*) a);
|
||||
|
||||
af_lo = _mm256_cvtepi32_ps(_mm256_cvtepi16_epi32(_mm256_extracti128_si256(a_8, 0)));
|
||||
af_hi = _mm256_cvtepi32_ps(_mm256_cvtepi16_epi32(_mm256_extracti128_si256(a_8, 1)));
|
||||
|
||||
result_lo = _mm256_mul_ps(af_lo, b_8);
|
||||
result_hi = _mm256_mul_ps(af_hi, b_8);
|
||||
|
||||
result_8 = _mm256_packs_epi32(_mm256_cvtps_epi32(result_lo), _mm256_cvtps_epi32(result_hi));
|
||||
_mm256_storeu_si256((__m256i*) result, result_8);
|
||||
|
||||
a += steps;
|
||||
result += steps;
|
||||
}
|
||||
} else if (steps == 4) {
|
||||
__m128i a_4;
|
||||
__m128 af_lo, af_hi;
|
||||
__m128 b_4 = _mm_set1_ps(b);
|
||||
__m128 result_lo, result_hi;
|
||||
__m128i result_4;
|
||||
|
||||
for (; i <= size - steps; i += steps) {
|
||||
a_4 = _mm_loadu_si128((__m128i*) a);
|
||||
|
||||
af_lo = _mm_cvtepi32_ps(_mm_cvtepi16_epi32(a_4));
|
||||
af_hi = _mm_cvtepi32_ps(_mm_cvtepi16_epi32(_mm_srli_si128(a_4, 8)));
|
||||
|
||||
result_lo = _mm_mul_ps(af_lo, b_4);
|
||||
result_hi = _mm_mul_ps(af_hi, b_4);
|
||||
|
||||
result_4 = _mm_packs_epi32(_mm_cvtps_epi32(result_lo), _mm_cvtps_epi32(result_hi));
|
||||
_mm_storeu_si128((__m128i*) result, result_4);
|
||||
|
||||
a += steps;
|
||||
result += steps;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle any remaining elements
|
||||
for (; i < size; ++i) {
|
||||
*result = (int16) ((f32) (*a) * b);
|
||||
++a;
|
||||
++result;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -467,11 +467,25 @@ inline
|
|||
int32 chars_to_eol(const char* str)
|
||||
{
|
||||
int32 offset = 0;
|
||||
while (!is_eol(str) && *str != '\0') {
|
||||
while (!is_eol(str) && *str++ != '\0') {
|
||||
++offset;
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
inline
|
||||
int32 strcpy_to_eol(const char* src, char* dst)
|
||||
{
|
||||
int32 offset = 0;
|
||||
while (!is_eol(src) && *src != '\0') {
|
||||
*dst++ = *src++;
|
||||
++offset;
|
||||
}
|
||||
|
||||
*dst = '\0';
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -10,6 +10,7 @@
|
|||
#define TOS_UTILS_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "../stdlib/Types.h"
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user