QuelSolaar/p2_sds_obj.c

559 lines
17 KiB
C

#define PERSUADE_INTERNAL
#include <stdlib.h>
#include "persuade2.h"
#include "p2_sds_geo.h"
#include "p2_sds_table.h"
#include "p2_sds_obj.h"
#include <math.h>
extern void p_get_tri_tess_index(uint *index, uint base_tess);
extern void p_get_quad_tess_index(uint *index, uint base_tess);
extern boolean p_lod_displacement_update_test(PMesh *mesh);
static uint p_sds_force_level = 4;
static float p_sds_mesh_factor = 1;
void p_geo_set_sds_force_level(uint level)
{
p_sds_force_level = level;
}
uint p_geo_get_sds_force_level(void)
{
return p_sds_force_level;
}
void p_geo_set_sds_mesh_factor(float factor)
{
p_sds_mesh_factor = factor;
}
float p_geo_get_sds_mesh_factor(void)
{
return p_sds_mesh_factor;
}
PMesh *p_rm_create(float compexity, uint force_tess_level)
{
PMesh *mesh;
mesh = malloc(sizeof *mesh);
mesh->stage = 0;
mesh->sub_stages[0] = 0;
mesh->sub_stages[1] = 0;
mesh->sub_stages[2] = 0;
mesh->sub_stages[3] = 0;
mesh->tess.force = force_tess_level;
mesh->tess.factor = compexity;
mesh->tess.edge_tess_func = p_sds_edge_tesselation_global_func;
mesh->temp = NULL;
mesh->next = NULL;
mesh->tess.tess = NULL;
mesh->tess.order_node = NULL;
mesh->tess.order_temp_mesh = NULL;
mesh->tess.order_temp_mesh_rev = NULL;
mesh->tess.order_temp_poly_start = NULL;
mesh->render.vertex_array = NULL;
mesh->render.normal_array = NULL;
mesh->render.reference = NULL;
mesh->render.mat = NULL;
mesh->render.shadows = TRUE;
mesh->depend.reference = NULL;
mesh->depend.weight = NULL;
mesh->depend.ref_count = NULL;
mesh->normal.normal_ref = NULL;
mesh->normal.normals = NULL;
mesh->normal.draw_normals = NULL;
mesh->param.array = NULL;
mesh->param.version = NULL;
return mesh;
}
void p_rm_set_eay(PMesh *mesh, pgreal *eye)
{
mesh->tess.eye[0] = eye[0];
mesh->tess.eye[1] = eye[1];
mesh->tess.eye[2] = eye[2];
mesh->tess.edge_tess_func = p_sds_edge_tesselation_global_func;
}
void persuade_lod_destroy(PMesh *mesh)
{
uint i;
if(mesh->temp != NULL)
free(mesh->temp);
if(mesh->tess.tess != NULL)
free(mesh->tess.tess);
if(mesh->tess.order_node != NULL)
free(mesh->tess.order_node);
if(mesh->tess.order_temp_mesh != NULL)
free(mesh->tess.order_temp_mesh);
if(mesh->tess.order_temp_mesh_rev != NULL)
free(mesh->tess.order_temp_mesh_rev);
if(mesh->tess.order_temp_poly_start != NULL)
free(mesh->tess.order_temp_poly_start);
if(mesh->render.vertex_array != NULL)
free(mesh->render.vertex_array);
if(mesh->render.normal_array != NULL)
free(mesh->render.normal_array);
if(mesh->render.reference != NULL)
free(mesh->render.reference);
if(mesh->render.mat != NULL)
free(mesh->render.mat);
if(mesh->depend.reference != NULL)
free(mesh->depend.reference);
if(mesh->depend.weight != NULL)
free(mesh->depend.weight);
if(mesh->depend.ref_count != NULL)
free(mesh->depend.ref_count);
if(mesh->normal.normal_ref != NULL)
free(mesh->normal.normal_ref);
if(mesh->normal.normals != NULL)
free(mesh->normal.normals);
if(mesh->normal.draw_normals != NULL)
free(mesh->normal.draw_normals);
if(mesh->param.version != NULL)
free(mesh->param.version);
free(mesh);
}
uint p_rm_get_param_count(PMesh *mesh)
{
return mesh->param.array_count;
}
#define P_TRI_TESS_SELECT 10000
#define P_QUAD_TESS_SELECT 7500
#define P_TRI_TESS_REF 10000
#define P_QUAD_TESS_REF 7500
double *p_lod_get_view_pos(void);
void p_lod_set(PPolyStore *geometry, PMesh *mesh);
PMesh *persuade2_lod_create(PPolyStore *smesh, uint *ref, pgreal *vertex, float compexity, uint force_tess_level, float *eye)
{
PMesh *mesh;
PTessTableElement *table;
uint i, j, k, l, material, polygon, poly_size = 4;
mesh = p_rm_create(compexity, force_tess_level);
for(i = 1 ; i < smesh->level; i++)
poly_size *= 4;
mesh->tess.tri_count = smesh->base_tri_count;
mesh->tess.quad_count = smesh->base_quad_count;
mesh->tess.tess = malloc((sizeof *mesh->tess.tess) * (mesh->tess.tri_count + mesh->tess.quad_count));
for(i = 0; i < (mesh->tess.tri_count + mesh->tess.quad_count); i++)
mesh->tess.tess[i] = NULL;
mesh->tess.eye[0] = eye[0];
mesh->tess.eye[1] = eye[1];
mesh->tess.eye[2] = eye[2];
mesh->temp = NULL;
mesh->render.element_count = 0;
mesh->render.vertex_count = 0;
mesh->render.open_edges = smesh->open_edges != 0;
mesh->render.shadows = smesh->open_edges == 0;
mesh->depend.length = 0;
mesh->sub_stages[0] = 0;
mesh->sub_stages[1] = 0;
mesh->sub_stages[2] = 0;
mesh->sub_stages[3] = 0;
mesh->stage++;
p_lod_set(smesh, mesh);
p_lod_select_tesselation(mesh, smesh, vertex);
mesh->render.vertex_array = malloc((sizeof *mesh->render.vertex_array) * mesh->render.vertex_count * 3);
mesh->render.normal_array = malloc((sizeof *mesh->render.normal_array) * mesh->render.vertex_count * 3);
mesh->normal.normal_ref = malloc((sizeof *mesh->normal.normal_ref) * mesh->render.vertex_count * 4);
mesh->render.reference = malloc((sizeof *mesh->render.reference) * mesh->render.element_count * 3);
mesh->depend.reference = malloc((sizeof *mesh->depend.reference) * mesh->depend.length);
mesh->depend.weight = malloc((sizeof *mesh->depend.weight) * mesh->depend.length);
mesh->depend.length_temp = mesh->depend.length;
mesh->depend.length_temp2 = mesh->render.vertex_count;
mesh->depend.length_temp3 = mesh->render.element_count;
mesh->depend.ref_count = malloc((sizeof *mesh->depend.ref_count) * mesh->render.vertex_count);
mesh->render.element_count = 0;
mesh->render.vertex_count = 0;
mesh->depend.length = 0;
/* building reference */
for(i = k = l = 0; i < mesh->tess.tri_count + mesh->tess.quad_count; i++)
{
if(i == mesh->render.mat[l].tri_end)
{
mesh->render.mat[l].render_end = mesh->render.element_count;
l++;
}
table = mesh->tess.tess[i];
for(j = 0; j < table->element_count;)
{
mesh->render.reference[mesh->render.element_count++] = table->index[j++] + k;
mesh->render.reference[mesh->render.element_count++] = table->index[j++] + k;
mesh->render.reference[mesh->render.element_count++] = table->index[j++] + k;
}
k += table->vertex_count;
}
mesh->render.mat[l].render_end = mesh->render.element_count;
/* building depend */
{
// uint poly, temp = 0;
for(i = material = l = 0; i < mesh->tess.tri_count + mesh->tess.quad_count; i++)
{
table = mesh->tess.tess[i];
if(i == mesh->render.mat[material].tri_end)
material++;
if(i < mesh->render.mat[material].quad_end)
polygon = mesh->tess.order_temp_mesh[i] * smesh->poly_per_base * 4;
else
polygon = smesh->base_quad_count * smesh->poly_per_base * 4 + (mesh->tess.order_temp_mesh[i] - smesh->base_quad_count) * smesh->poly_per_base * 3;
for(j = 0; j < table->vertex_count; j++)
{
PDepend *dep;
// temp++;
dep = &smesh->vertex_dependency[smesh->ref[table->reference[j] + polygon]];
mesh->depend.ref_count[mesh->render.vertex_count++] = dep->length;
for(k = 0; k < dep->length; k++)
{
mesh->depend.reference[mesh->depend.length] = dep->element[k].vertex * 3;
mesh->depend.weight[mesh->depend.length] = dep->element[k].value;
mesh->depend.length++;
}
}
mesh->tess.order_temp_poly_start[i] = l;
l += table->vertex_count;
}
}
p_lod_compute_vertex_normals(smesh, mesh);
p_lod_create_normal_ref_and_shadow_skirts(smesh, mesh);
/* p_lod_create_layer_param(g_node, mesh);
if(o_node != NULL)
{
if(p_lod_displacement_update_test(mesh))
{
uint ii;
mesh->displacement.displacement = malloc((sizeof *mesh->displacement.displacement) * mesh->render.vertex_count);
p_lod_create_displacement_array(g_node, o_node, mesh, smesh->level);
// for(ii = 0; ii < mesh->render.vertex_count; ii++)
// mesh->displacement.displacement[ii] = 0;
}
}
p_lod_anim_bones_update_test(mesh, o_node, g_node);
p_lod_anim_scale_update_test(mesh, o_node);
p_lod_anim_layer_update_test(mesh, o_node, g_node);
case POS_ANIMATE :
if(o_node != NULL)
p_lod_anim_vertex_array(mesh->anim.cvs, mesh->anim.cv_count, mesh, g_node);
mesh->stage++;
break;
case POS_CREATE_VERTICES :
j = 0;
for(i = 0; i < mesh->render.vertex_count; i++)
j += mesh->depend.ref_count[i];
if(o_node != NULL)
p_lod_compute_vertex_array(mesh->render.vertex_array, mesh->render.vertex_count, mesh->depend.ref_count, mesh->depend.reference, mesh->depend.weight, mesh->anim.cvs);
else
p_lod_compute_vertex_array(mesh->render.vertex_array, mesh->render.vertex_count, mesh->depend.ref_count, mesh->depend.reference, mesh->depend.weight, vertex);
p_lod_compute_normal_array(mesh->render.normal_array, mesh->render.vertex_count, mesh->normal.normal_ref, mesh->render.vertex_array);
// if(o_node != NULL)
// p_lod_create_displacement_array(g_node, o_node, mesh, smesh->level);
if(mesh->displacement.displacement != NULL)
{
p_lod_compute_displacement_array(mesh->render.vertex_array, mesh->render.vertex_count, mesh->render.normal_array, mesh->displacement.displacement);
p_lod_compute_normal_array(mesh->render.normal_array, mesh->render.vertex_count, mesh->normal.normal_ref, mesh->render.vertex_array);
}
mesh->stage++;
if(store != NULL)
p_rm_destroy(store);
store = NULL;
break;
case POS_DONE :
if(o_node != NULL)
{
boolean update = FALSE;
static double timer = 0;
timer += 0.1;
p_lod_update_shadow(g_node, mesh);
p_lod_update_layer_param(g_node, mesh);
if(p_lod_anim_bones_update_test(mesh, o_node, g_node))
update = TRUE;
if(p_lod_anim_scale_update_test(mesh, o_node))
update = TRUE;
if(p_lod_anim_layer_update_test(mesh, o_node, g_node))
update = TRUE;
if(p_lod_displacement_update_test(mesh))
{
uint ii;
p_lod_update_displacement_array(g_node, o_node, mesh, smesh->level);
update = TRUE;
}
if(update)
{
p_lod_anim_vertex_array(mesh->anim.cvs, mesh->anim.cv_count, mesh, g_node);
p_lod_compute_vertex_array(mesh->render.vertex_array, mesh->render.vertex_count, mesh->depend.ref_count, mesh->depend.reference, mesh->depend.weight, mesh->anim.cvs);
p_lod_compute_normal_array(mesh->render.normal_array, mesh->render.vertex_count, mesh->normal.normal_ref, mesh->render.vertex_array);
if(mesh->displacement.displacement != NULL)
{
p_lod_compute_displacement_array(mesh->render.vertex_array, mesh->render.vertex_count, mesh->render.normal_array, mesh->displacement.displacement);
p_lod_compute_normal_array(mesh->render.normal_array, mesh->render.vertex_count, mesh->normal.normal_ref, mesh->render.vertex_array);
}
}
}
return mesh;
}
}
if(store != NULL)
return store;*/
return mesh;
}
uint persuade2_lod_vertex_length_get(PMesh *mesh)
{
return mesh->render.vertex_count;
}
void persuade2_lod_vertex_shape(PMesh *mesh, pgreal *render_vertex, uint output_stride, pgreal *cvs)
{
p_lod_compute_vertex_array(render_vertex, output_stride, mesh->render.vertex_count, mesh->depend.ref_count, mesh->depend.reference, mesh->depend.weight, cvs);
}
void persuade2_lod_normal_shape(PMesh *mesh, pgreal *render_normal, uint normal_stride, pgreal *render_vertex, uint vertex_stride)
{
p_lod_compute_normal_array(render_normal, normal_stride, mesh->render.vertex_count, mesh->normal.normal_ref, render_vertex, vertex_stride);
}
/*
void p_rm_compute(PMesh *mesh, pgreal *vertex, uint start, uint length)
{
uint i, j, k = 0, l, count, *ref;
pgreal f;
ref = mesh->depend.reference;
for(i = 0; i < mesh->render.vertex_count; i++)
{
mesh->render.vertex_array[i * 3] = 0;
mesh->render.vertex_array[i * 3 + 1] = 0;
mesh->render.vertex_array[i * 3 + 2] = 0;
count = mesh->depend.ref_count[i];
for(j = 0; j < count; j++)
{
l = mesh->depend.reference[k];
f = mesh->depend.weight[k];
mesh->render.vertex_array[i * 3] += vertex[l++] * f;
mesh->render.vertex_array[i * 3 + 1] += vertex[l++] * f;
mesh->render.vertex_array[i * 3 + 2] += vertex[l] * f;
k++;
}
}
}
*/
boolean p_rm_draw_ready(PMesh *mesh)
{
return mesh->stage > 7;
}
#define NORMAL_ADD 0.001
void p_lod_compute_vertex_array(pgreal *vertex, uint output_stride, uint vertex_count, const uint *ref_count, const uint *reference, const pgreal *weight, const pgreal *cvs)
{
uint i, j, k = 0, count, r;
pgreal f;
// printf("vertex_count %u\n", vertex_count);
for(i = 0; i < vertex_count; i++)
{
vertex[0] = 0;
vertex[1] = 0;
vertex[2] = 0;
count = ref_count[i];
for(j = 0; j < count; j++)
{
r = reference[k];
f = weight[k++];
// printf("cvs %u %f %f %f\n", r / 3, cvs[r], cvs[r + 1], cvs[r + 2]);
vertex[0] += cvs[r++] * f;
vertex[1] += cvs[r++] * f;
vertex[2] += cvs[r] * f;
}
// printf("float %f %f %f\n", vertex[v + 0], vertex[v + 1], vertex[v + 2]);
vertex = (pgreal *)(&((uint8 *)vertex)[output_stride]);
}
}
void p_lod_compute_displacement_array(pgreal *vertex, uint vertex_count, const pgreal *normals, const pgreal *displacement)
{
uint i;
for(i = 0; i < vertex_count; i++)
{
*vertex++ += *normals++ * *displacement * 100;
*vertex++ += *normals++ * *displacement * 100;
*vertex++ += *normals++ * *displacement++ * 100;
}
}
void p_lod_compute_normal_array(pgreal *normals, uint normal_stride, uint vertex_count, const uint *normal_ref, const pgreal *vertex, uint vertex_stride)
{
uint i = 0, j = 0, k = 0;
pgreal x, y, z, f, vec0[3], vec1[3], vec2[3], vec3[3];
normal_stride /= sizeof(pgreal);
vertex_stride /= sizeof(pgreal);
vertex_count *= normal_stride;
if(TRUE)
{
while(i < vertex_count)
{
x = vertex[k];
y = vertex[k + 1];
z = vertex[k + 2];
k += vertex_stride;
vec0[0] = vertex[normal_ref[j] * vertex_stride] - x;
vec0[1] = vertex[normal_ref[j] * vertex_stride + 1] - y;
vec0[2] = vertex[normal_ref[j] * vertex_stride + 2] - z;
j++;
vec1[0] = vertex[normal_ref[j] * vertex_stride] - x;
vec1[1] = vertex[normal_ref[j] * vertex_stride + 1] - y;
vec1[2] = vertex[normal_ref[j] * vertex_stride + 2] - z;
j++;
vec2[0] = vertex[normal_ref[j] * vertex_stride] - x;
vec2[1] = vertex[normal_ref[j] * vertex_stride + 1] - y;
vec2[2] = vertex[normal_ref[j] * vertex_stride + 2] - z;
j++;
vec3[0] = vertex[normal_ref[j] * vertex_stride] - x;
vec3[1] = vertex[normal_ref[j] * vertex_stride + 1] - y;
vec3[2] = vertex[normal_ref[j] * vertex_stride + 2] - z;
j++;
x = (vec0[1] * vec1[2] - vec0[2] * vec1[1]) + (vec2[1] * vec3[2] - vec2[2] * vec3[1]);
y = (vec0[2] * vec1[0] - vec0[0] * vec1[2]) + (vec2[2] * vec3[0] - vec2[0] * vec3[2]);
z = (vec0[0] * vec1[1] - vec0[1] * vec1[0]) + (vec2[0] * vec3[1] - vec2[1] * vec3[0]);
f = sqrt(x * x + y * y + z * z);
normals[i] = x / f;
normals[i + 1] = y / f;
normals[i + 2] = z / f;
i += normal_stride;
}
}else
{
while(i < vertex_count)
{
x = vertex[k];
y = vertex[k + 1];
z = vertex[k + 2];
k += vertex_stride;
vec0[0] = vertex[normal_ref[j] * vertex_stride] - x;
vec0[1] = vertex[normal_ref[j] * vertex_stride + 1] - y;
vec0[2] = vertex[normal_ref[j] * vertex_stride + 2] - z;
f = sqrt(vec0[0] * vec0[0] + vec0[1] * vec0[1] + vec0[2] * vec0[2]);
vec0[0] /= f;
vec0[1] /= f;
vec0[2] /= f;
j++;
vec1[0] = vertex[normal_ref[j] * vertex_stride] - x;
vec1[1] = vertex[normal_ref[j] * vertex_stride + 1] - y;
vec1[2] = vertex[normal_ref[j] * vertex_stride + 2] - z;
f = sqrt(vec1[0] * vec1[0] + vec1[1] * vec1[1] + vec1[2] * vec1[2]);
vec1[0] /= f;
vec1[1] /= f;
vec1[2] /= f;
j++;
vec2[0] = vertex[normal_ref[j] * vertex_stride] - x;
vec2[1] = vertex[normal_ref[j] * vertex_stride + 1] - y;
vec2[2] = vertex[normal_ref[j] * vertex_stride + 2] - z;
f = sqrt(vec2[0] * vec2[0] + vec2[1] * vec2[1] + vec2[2] * vec2[2]);
vec2[0] /= f;
vec2[1] /= f;
vec2[2] /= f;
j++;
vec3[0] = vertex[normal_ref[j] * vertex_stride] - x;
vec3[1] = vertex[normal_ref[j] * vertex_stride + 1] - y;
vec3[2] = vertex[normal_ref[j] * vertex_stride + 2] - z;
f = sqrt(vec3[0] * vec3[0] + vec3[1] * vec3[1] + vec3[2] * vec3[2]);
vec3[0] /= f;
vec3[1] /= f;
vec3[2] /= f;
j++;
x = (vec0[1] * vec1[2] - vec0[2] * vec1[1]) + (vec2[1] * vec3[2] - vec2[2] * vec3[1]);
y = (vec0[2] * vec1[0] - vec0[0] * vec1[2]) + (vec2[2] * vec3[0] - vec2[0] * vec3[2]);
z = (vec0[0] * vec1[1] - vec0[1] * vec1[0]) + (vec2[0] * vec3[1] - vec2[1] * vec3[0]);
f = sqrt(x * x + y * y + z * z);
normals[i] = x / f;
normals[i + 1] = y / f;
normals[i + 2] = z / f;
i += normal_stride;
}
}
}
pgreal *p_rm_get_vertex(PMesh *mesh)
{
return mesh->render.vertex_array;
}
pgreal *p_rm_get_normal(PMesh *mesh)
{
return mesh->render.normal_array;
}
uint p_rm_get_vertex_length(PMesh *mesh)
{
return mesh->render.vertex_count;
}
uint *p_rm_get_reference(PMesh *mesh)
{
return mesh->render.reference;
}
uint p_rm_get_ref_length(PMesh *mesh)
{
return mesh->render.element_count;
}
uint p_rm_get_mat_count(PMesh *mesh)
{
return mesh->render.mat_count;
}
uint p_rm_get_material_range(PMesh *mesh, uint mat)
{
return mesh->render.mat[mat].render_end;
}
uint p_rm_get_material(PMesh *mesh, uint mat)
{
return mesh->render.mat[mat].material;
}
boolean p_rm_get_shadow(PMesh *mesh)
{
return mesh->render.shadows;
}