mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-10-07 06:18:14 +03:00
Merge pull request #331 from kichikuou/POLv4
SealEngine: Support POL v4 format
This commit is contained in:
@@ -76,6 +76,8 @@ vec3 dir_lights_diffuse(vec3 norm)
|
||||
#endif // ENGINE == REIGN_ENGINE
|
||||
|
||||
uniform sampler2D tex;
|
||||
uniform sampler2D blend_tex;
|
||||
uniform bool use_blend_texture;
|
||||
uniform sampler2D alpha_texture;
|
||||
uniform sampler2D light_texture;
|
||||
uniform sampler2D shadow_texture;
|
||||
@@ -98,6 +100,8 @@ in vec4 shadow_frag_pos;
|
||||
in float dist;
|
||||
in vec3 eye;
|
||||
in vec3 normal;
|
||||
in float blend_weight;
|
||||
in vec2 blend_tex_coord;
|
||||
out vec4 frag_color;
|
||||
|
||||
void main() {
|
||||
@@ -119,6 +123,9 @@ void main() {
|
||||
frag_rgb = texel.rgb;
|
||||
} else {
|
||||
texel = texture(tex, tex_coord);
|
||||
if (use_blend_texture) {
|
||||
texel = mix(texel, texture(blend_tex, blend_tex_coord), blend_weight);
|
||||
}
|
||||
if (diffuse_type == DIFFUSE_EMISSIVE) {
|
||||
frag_rgb = texel.rgb;
|
||||
} else {
|
||||
|
||||
@@ -72,6 +72,8 @@ in vec4 vertex_color;
|
||||
in vec4 vertex_tangent;
|
||||
in ivec4 vertex_bone_index;
|
||||
in vec4 vertex_bone_weight;
|
||||
in float vertex_blend_weight;
|
||||
in vec2 vertex_blend_uv;
|
||||
|
||||
out vec2 tex_coord;
|
||||
out vec2 light_tex_coord;
|
||||
@@ -81,6 +83,8 @@ out vec4 shadow_frag_pos;
|
||||
out float dist;
|
||||
out vec3 eye;
|
||||
out vec3 normal;
|
||||
out float blend_weight;
|
||||
out vec2 blend_tex_coord;
|
||||
|
||||
void main() {
|
||||
mat4 local_bone_transform = local_transform;
|
||||
@@ -117,6 +121,8 @@ void main() {
|
||||
tex_coord = vertex_uv + uv_scroll;
|
||||
light_tex_coord = vertex_light_uv + uv_scroll;
|
||||
color_mod = vertex_color;
|
||||
blend_weight = vertex_blend_weight;
|
||||
blend_tex_coord = vertex_blend_uv + uv_scroll;
|
||||
dist = -view_pos.z;
|
||||
shadow_frag_pos = shadow_transform * world_pos;
|
||||
|
||||
|
||||
+12
-1
@@ -74,6 +74,7 @@ struct material {
|
||||
GLuint alpha_map;
|
||||
GLuint light_map;
|
||||
GLuint normal_map;
|
||||
GLuint blend_texture;
|
||||
float specular_strength;
|
||||
float specular_shininess;
|
||||
float shadow_darkness;
|
||||
@@ -108,6 +109,8 @@ enum RE_attribute_location {
|
||||
VATTR_LIGHT_UV,
|
||||
VATTR_COLOR,
|
||||
VATTR_TANGENT,
|
||||
VATTR_BLEND_WEIGHT,
|
||||
VATTR_BLEND_UV,
|
||||
};
|
||||
|
||||
struct shadow_renderer {
|
||||
@@ -185,6 +188,8 @@ struct RE_renderer {
|
||||
GLint alpha_mode;
|
||||
GLint alpha_texture;
|
||||
GLint uv_scroll;
|
||||
GLint blend_tex;
|
||||
GLint use_blend_texture;
|
||||
|
||||
GLuint billboard_vao;
|
||||
GLuint billboard_attr_buffer;
|
||||
@@ -431,7 +436,7 @@ struct pol_material {
|
||||
struct pol_material_group {
|
||||
struct pol_material m;
|
||||
uint32_t nr_children;
|
||||
struct pol_material *children;
|
||||
struct pol_material_group *children;
|
||||
};
|
||||
|
||||
enum mesh_flags {
|
||||
@@ -461,6 +466,10 @@ struct pol_mesh {
|
||||
vec3 *colors;
|
||||
uint32_t nr_alphas;
|
||||
float *alphas;
|
||||
uint32_t nr_blend_uvs;
|
||||
vec2 *blend_uvs;
|
||||
uint32_t nr_blend_weights;
|
||||
float *blend_weights;
|
||||
uint32_t nr_triangles;
|
||||
struct pol_triangle *triangles;
|
||||
// Parameters in .opr file.
|
||||
@@ -486,6 +495,8 @@ struct pol_triangle {
|
||||
uint32_t light_uv_index[3];
|
||||
uint32_t color_index[3];
|
||||
uint32_t alpha_index[3];
|
||||
uint32_t blend_uv_index[3];
|
||||
uint32_t blend_weight_index[3];
|
||||
vec3 normals[3];
|
||||
uint32_t material_group_index;
|
||||
};
|
||||
|
||||
+43
-2
@@ -54,6 +54,11 @@ struct vertex_bones {
|
||||
GLfloat bone_weight[NR_WEIGHTS];
|
||||
};
|
||||
|
||||
struct vertex_blend {
|
||||
GLfloat blend_weight;
|
||||
GLfloat blend_uv[2];
|
||||
};
|
||||
|
||||
static bool is_transparent_mesh(const struct pol_mesh *mesh)
|
||||
{
|
||||
if (re_plugin_version == RE_REIGN_PLUGIN)
|
||||
@@ -202,6 +207,8 @@ static void destroy_material(struct material *material)
|
||||
glDeleteTextures(1, &material->light_map);
|
||||
if (material->normal_map)
|
||||
glDeleteTextures(1, &material->normal_map);
|
||||
if (material->blend_texture)
|
||||
glDeleteTextures(1, &material->blend_texture);
|
||||
}
|
||||
|
||||
static int cmp_by_bone_weight(const void *lhs, const void *rhs)
|
||||
@@ -276,6 +283,7 @@ static void add_mesh(struct model *model, struct pol_mesh *m, uint32_t material_
|
||||
bool has_vertex_colors = m->nr_colors > 0 || m->nr_alphas > 0;
|
||||
bool has_normal_map = model->materials[material].normal_map != 0;
|
||||
bool has_bones = !!model->bone_map;
|
||||
bool has_blend = m->blend_weights && model->materials[material].blend_texture;
|
||||
|
||||
GLsizei stride = sizeof(struct vertex_common);
|
||||
if (has_light_map)
|
||||
@@ -286,6 +294,8 @@ static void add_mesh(struct model *model, struct pol_mesh *m, uint32_t material_
|
||||
stride += sizeof(struct vertex_tangent);
|
||||
if (has_bones)
|
||||
stride += sizeof(struct vertex_bones);
|
||||
if (has_blend)
|
||||
stride += sizeof(struct vertex_blend);
|
||||
|
||||
void *buffer = xmalloc(m->nr_triangles * 3 * stride);
|
||||
uint8_t *ptr = buffer;
|
||||
@@ -336,6 +346,14 @@ static void add_mesh(struct model *model, struct pol_mesh *m, uint32_t material_
|
||||
}
|
||||
}
|
||||
}
|
||||
if (has_blend) {
|
||||
struct vertex_blend *v_blend = buf_alloc(&ptr, sizeof(struct vertex_blend));
|
||||
v_blend->blend_weight = m->blend_weights[t->blend_weight_index[j]];
|
||||
if (m->blend_uvs)
|
||||
glm_vec2_copy(m->blend_uvs[t->blend_uv_index[j]], v_blend->blend_uv);
|
||||
else
|
||||
glm_vec2_copy(m->uvs[t->uv_index[j]], v_blend->blend_uv);
|
||||
}
|
||||
nr_vertices++;
|
||||
}
|
||||
}
|
||||
@@ -412,6 +430,18 @@ static void add_mesh(struct model *model, struct pol_mesh *m, uint32_t material_
|
||||
glDisableVertexAttribArray(VATTR_BONE_WEIGHT);
|
||||
glVertexAttrib4f(VATTR_BONE_WEIGHT, 0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
if (has_blend) {
|
||||
glEnableVertexAttribArray(VATTR_BLEND_WEIGHT);
|
||||
glVertexAttribPointer(VATTR_BLEND_WEIGHT, 1, GL_FLOAT, GL_FALSE, stride, base + offsetof(struct vertex_blend, blend_weight));
|
||||
glEnableVertexAttribArray(VATTR_BLEND_UV);
|
||||
glVertexAttribPointer(VATTR_BLEND_UV, 2, GL_FLOAT, GL_FALSE, stride, base + offsetof(struct vertex_blend, blend_uv));
|
||||
base += sizeof(struct vertex_blend);
|
||||
} else {
|
||||
glDisableVertexAttribArray(VATTR_BLEND_WEIGHT);
|
||||
glVertexAttrib1f(VATTR_BLEND_WEIGHT, 0.0);
|
||||
glDisableVertexAttribArray(VATTR_BLEND_UV);
|
||||
glVertexAttrib2f(VATTR_BLEND_UV, 0.0, 0.0);
|
||||
}
|
||||
assert((intptr_t)base == stride);
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, mesh->nr_vertices * stride, buffer, GL_STATIC_DRAW);
|
||||
@@ -543,8 +573,19 @@ struct model *model_load(struct archive *aar, const char *path)
|
||||
continue;
|
||||
}
|
||||
for (uint32_t j = 0; j < pol->materials[i].nr_children; j++) {
|
||||
init_material(&model->materials[material_offsets[i] + j],
|
||||
&pol->materials[i].children[j], amt, aar, path);
|
||||
struct pol_material_group *child = &pol->materials[i].children[j];
|
||||
if (child->nr_children >= 2) {
|
||||
// Group node: texture blending (base + blend)
|
||||
init_material(&model->materials[material_offsets[i] + j],
|
||||
&child->children[0].m, amt, aar, path);
|
||||
if (child->children[1].m.textures[COLOR_MAP]) {
|
||||
model->materials[material_offsets[i] + j].blend_texture =
|
||||
load_texture(aar, path, child->children[1].m.textures[COLOR_MAP], NULL);
|
||||
}
|
||||
} else {
|
||||
init_material(&model->materials[material_offsets[i] + j],
|
||||
&child->m, amt, aar, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+83
-20
@@ -70,15 +70,14 @@ static uint32_t parse_material_attributes(const char *name)
|
||||
return flags;
|
||||
}
|
||||
|
||||
static void parse_material(struct buffer *r, struct pol_material *m)
|
||||
static void parse_textures(struct buffer *r, int pol_version, struct pol_material *m)
|
||||
{
|
||||
m->name = read_cstring(r);
|
||||
m->flags = parse_material_attributes(m->name);
|
||||
|
||||
int nr_textures = buffer_read_int32(r);
|
||||
for (int i = 0; i < nr_textures; i++) {
|
||||
char *filename = read_cstring(r);
|
||||
int type = buffer_read_int32(r);
|
||||
if (pol_version >= 3)
|
||||
buffer_skip(r, 8); // 2 unknown float params
|
||||
if ((unsigned)type < MAX_TEXTURE_TYPE) {
|
||||
m->textures[type] = filename;
|
||||
} else {
|
||||
@@ -95,29 +94,60 @@ static void destroy_material(struct pol_material *m)
|
||||
free(m->textures[i]);
|
||||
}
|
||||
|
||||
static void parse_material_group(struct buffer *r, struct pol_material_group *mg)
|
||||
{
|
||||
parse_material(r, &mg->m);
|
||||
|
||||
mg->nr_children = buffer_read_int32(r);
|
||||
if (mg->nr_children > 0) {
|
||||
mg->children = xcalloc(mg->nr_children, sizeof(struct pol_material));
|
||||
for (uint32_t i = 0; i < mg->nr_children; i++) {
|
||||
parse_material(r, &mg->children[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void destroy_material_group(struct pol_material_group *mg)
|
||||
{
|
||||
destroy_material(&mg->m);
|
||||
if (mg->children) {
|
||||
for (uint32_t i = 0; i < mg->nr_children; i++)
|
||||
destroy_material(&mg->children[i]);
|
||||
destroy_material_group(&mg->children[i]);
|
||||
free(mg->children);
|
||||
}
|
||||
}
|
||||
|
||||
// Material tree layout:
|
||||
// level 0: top-level material per pol->materials[]. Either a textured leaf
|
||||
// or a group containing sub-materials, never both.
|
||||
// level 1: sub-material. Either a textured leaf or, in v4 only, a "blend
|
||||
// group" (is_group=1) with exactly 2 leaf children.
|
||||
// level 2: leaf children of a v4 blend group; cannot themselves be a group.
|
||||
static void parse_material_group(struct buffer *r, int pol_version,
|
||||
struct pol_material_group *mg, int level)
|
||||
{
|
||||
mg->m.name = read_cstring(r);
|
||||
mg->m.flags = parse_material_attributes(mg->m.name);
|
||||
|
||||
bool is_group = false;
|
||||
if (pol_version >= 4)
|
||||
is_group = buffer_read_int32(r);
|
||||
|
||||
if (is_group) {
|
||||
if (level >= 2)
|
||||
ERROR("material group nesting too deep");
|
||||
uint32_t uk = buffer_read_int32(r);
|
||||
if (uk != 0)
|
||||
ERROR("unexpected nonzero value in material group: %u", uk);
|
||||
|
||||
mg->nr_children = buffer_read_int32(r);
|
||||
if (level == 1 && mg->nr_children != 2)
|
||||
ERROR("blend group must have 2 children, got %u", mg->nr_children);
|
||||
} else {
|
||||
parse_textures(r, pol_version, &mg->m);
|
||||
|
||||
if (pol_version >= 4) {
|
||||
uint32_t uk = buffer_read_int32(r);
|
||||
if (uk != 0)
|
||||
ERROR("unexpected nonzero value in material leaf: %u", uk);
|
||||
} else if (level == 0) {
|
||||
mg->nr_children = buffer_read_int32(r);
|
||||
}
|
||||
}
|
||||
if (mg->nr_children > 0) {
|
||||
mg->children = xcalloc(mg->nr_children, sizeof(struct pol_material_group));
|
||||
for (uint32_t i = 0; i < mg->nr_children; i++)
|
||||
parse_material_group(r, pol_version, &mg->children[i], level + 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void parse_vertex(struct buffer *r, int pol_version, struct pol_vertex *v)
|
||||
{
|
||||
read_position(r, v->pos);
|
||||
@@ -151,6 +181,11 @@ static void parse_triangle(struct buffer *r, struct pol_mesh *mesh, int triangle
|
||||
t->light_uv_index[1] = buffer_read_int32(r) - mesh->nr_uvs;
|
||||
t->light_uv_index[2] = buffer_read_int32(r) - mesh->nr_uvs;
|
||||
}
|
||||
if (mesh->blend_uvs) {
|
||||
t->blend_uv_index[0] = buffer_read_int32(r) - mesh->nr_uvs - mesh->nr_light_uvs;
|
||||
t->blend_uv_index[1] = buffer_read_int32(r) - mesh->nr_uvs - mesh->nr_light_uvs;
|
||||
t->blend_uv_index[2] = buffer_read_int32(r) - mesh->nr_uvs - mesh->nr_light_uvs;
|
||||
}
|
||||
|
||||
t->color_index[0] = buffer_read_int32(r);
|
||||
t->color_index[1] = buffer_read_int32(r);
|
||||
@@ -160,6 +195,11 @@ static void parse_triangle(struct buffer *r, struct pol_mesh *mesh, int triangle
|
||||
t->alpha_index[1] = buffer_read_int32(r);
|
||||
t->alpha_index[2] = buffer_read_int32(r);
|
||||
}
|
||||
if (mesh->blend_weights) {
|
||||
t->blend_weight_index[0] = buffer_read_int32(r);
|
||||
t->blend_weight_index[1] = buffer_read_int32(r);
|
||||
t->blend_weight_index[2] = buffer_read_int32(r);
|
||||
}
|
||||
|
||||
read_direction(r, t->normals[0]);
|
||||
read_direction(r, t->normals[1]);
|
||||
@@ -227,6 +267,17 @@ static struct pol_mesh *parse_mesh(struct buffer *r, const struct pol *pol)
|
||||
}
|
||||
}
|
||||
|
||||
if (pol->version >= 4) {
|
||||
mesh->nr_blend_uvs = buffer_read_int32(r);
|
||||
if (mesh->nr_blend_uvs > 0) {
|
||||
mesh->blend_uvs = xcalloc(mesh->nr_blend_uvs, sizeof(vec2));
|
||||
for (uint32_t i = 0; i < mesh->nr_blend_uvs; i++) {
|
||||
mesh->blend_uvs[i][0] = buffer_read_float(r);
|
||||
mesh->blend_uvs[i][1] = buffer_read_float(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mesh->nr_colors = buffer_read_int32(r);
|
||||
if (mesh->nr_colors > 0) {
|
||||
mesh->colors = xcalloc(mesh->nr_colors, sizeof(vec3));
|
||||
@@ -254,6 +305,16 @@ static struct pol_mesh *parse_mesh(struct buffer *r, const struct pol *pol)
|
||||
}
|
||||
}
|
||||
|
||||
if (pol->version >= 4) {
|
||||
mesh->nr_blend_weights = buffer_read_int32(r);
|
||||
if (mesh->nr_blend_weights > 0) {
|
||||
mesh->blend_weights = xcalloc(mesh->nr_blend_weights, sizeof(float));
|
||||
for (uint32_t i = 0; i < mesh->nr_blend_weights; i++) {
|
||||
mesh->blend_weights[i] = buffer_read_u8(r) / 255.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mesh->nr_triangles = buffer_read_int32(r);
|
||||
mesh->triangles = xcalloc(mesh->nr_triangles, sizeof(struct pol_triangle));
|
||||
for (uint32_t i = 0; i < mesh->nr_triangles; i++) {
|
||||
@@ -280,8 +341,10 @@ static void free_mesh(struct pol_mesh *mesh)
|
||||
free(mesh->vertices);
|
||||
free(mesh->uvs);
|
||||
free(mesh->light_uvs);
|
||||
free(mesh->blend_uvs);
|
||||
free(mesh->colors);
|
||||
free(mesh->alphas);
|
||||
free(mesh->blend_weights);
|
||||
free(mesh->triangles);
|
||||
free(mesh);
|
||||
}
|
||||
@@ -310,7 +373,7 @@ struct pol *pol_parse(uint8_t *data, size_t size)
|
||||
|
||||
struct pol *pol = xcalloc(1, sizeof(struct pol));
|
||||
pol->version = buffer_read_int32(&r);
|
||||
if (pol->version != 1 && pol->version != 2) {
|
||||
if (pol->version != 1 && pol->version != 2 && pol->version != 4) {
|
||||
WARNING("unknown POL version: %d", pol->version);
|
||||
free(pol);
|
||||
return NULL;
|
||||
@@ -318,7 +381,7 @@ struct pol *pol_parse(uint8_t *data, size_t size)
|
||||
pol->nr_materials = buffer_read_int32(&r);
|
||||
pol->materials = xcalloc(pol->nr_materials, sizeof(struct pol_material_group));
|
||||
for (uint32_t i = 0; i < pol->nr_materials; i++) {
|
||||
parse_material_group(&r, &pol->materials[i]);
|
||||
parse_material_group(&r, pol->version, &pol->materials[i], 0);
|
||||
}
|
||||
|
||||
pol->nr_meshes = buffer_read_int32(&r);
|
||||
|
||||
@@ -39,6 +39,7 @@ enum {
|
||||
LIGHT_TEXTURE_UNIT,
|
||||
NORMAL_TEXTURE_UNIT,
|
||||
SHADOW_TEXTURE_UNIT,
|
||||
BLEND_TEXTURE_UNIT,
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -89,6 +90,8 @@ static GLuint load_shader(const char *vertex_shader_path, const char *fragment_s
|
||||
glBindAttribLocation(program, VATTR_LIGHT_UV, "vertex_light_uv");
|
||||
glBindAttribLocation(program, VATTR_COLOR, "vertex_color");
|
||||
glBindAttribLocation(program, VATTR_TANGENT, "vertex_tangent");
|
||||
glBindAttribLocation(program, VATTR_BLEND_WEIGHT, "vertex_blend_weight");
|
||||
glBindAttribLocation(program, VATTR_BLEND_UV, "vertex_blend_uv");
|
||||
|
||||
glLinkProgram(program);
|
||||
|
||||
@@ -258,6 +261,8 @@ struct RE_renderer *RE_renderer_new(void)
|
||||
r->alpha_mode = glGetUniformLocation(r->program, "alpha_mode");
|
||||
r->alpha_texture = glGetUniformLocation(r->program, "alpha_texture");
|
||||
r->uv_scroll = glGetUniformLocation(r->program, "uv_scroll");
|
||||
r->blend_tex = glGetUniformLocation(r->program, "blend_tex");
|
||||
r->use_blend_texture = glGetUniformLocation(r->program, "use_blend_texture");
|
||||
|
||||
glGenRenderbuffers(1, &r->depth_buffer);
|
||||
|
||||
@@ -447,6 +452,15 @@ static void render_model(struct RE_instance *inst, struct RE_renderer *r, enum d
|
||||
glUniform1i(r->alpha_mode, mesh->is_transparent ? ALPHA_BLEND : ALPHA_TEST);
|
||||
}
|
||||
|
||||
if (material->blend_texture) {
|
||||
glUniform1i(r->use_blend_texture, GL_TRUE);
|
||||
glActiveTexture(GL_TEXTURE0 + BLEND_TEXTURE_UNIT);
|
||||
glBindTexture(GL_TEXTURE_2D, material->blend_texture);
|
||||
glUniform1i(r->blend_tex, BLEND_TEXTURE_UNIT);
|
||||
} else {
|
||||
glUniform1i(r->use_blend_texture, GL_FALSE);
|
||||
}
|
||||
|
||||
vec2 uv_scroll;
|
||||
glm_vec2_scale(mesh->uv_scroll, r->last_frame_timestamp / 1000.f, uv_scroll);
|
||||
glUniform2fv(r->uv_scroll, 1, uv_scroll);
|
||||
|
||||
Reference in New Issue
Block a user