278 lines
7.3 KiB
C
278 lines
7.3 KiB
C
#include "../h/surface_gatherer.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
|
|
#include "../h/map_data.h"
|
|
#include "../h/face.h"
|
|
#include "../h/brush.h"
|
|
#include "../h/entity.h"
|
|
|
|
enum surface_split_type split_type = SST_NONE;
|
|
int entity_filter_idx = -1;
|
|
int texture_filter_idx = -1;
|
|
int brush_filter_texture_idx;
|
|
int face_filter_texture_idx;
|
|
bool filter_worldspawn_layers;
|
|
|
|
surfaces out_surfaces;
|
|
|
|
void surface_gatherer_set_split_type(enum surface_split_type new_split_type)
|
|
{
|
|
split_type = new_split_type;
|
|
}
|
|
|
|
void surface_gatherer_set_entity_index_filter(int entity_idx)
|
|
{
|
|
entity_filter_idx = entity_idx;
|
|
}
|
|
|
|
void surface_gatherer_set_texture_filter(const char *texture_name)
|
|
{
|
|
texture_filter_idx = map_data_find_texture(texture_name);
|
|
}
|
|
|
|
void surface_gatherer_set_brush_filter_texture(const char *texture_name)
|
|
{
|
|
brush_filter_texture_idx = map_data_find_texture(texture_name);
|
|
}
|
|
|
|
void surface_gatherer_set_face_filter_texture(const char *texture_name)
|
|
{
|
|
face_filter_texture_idx = map_data_find_texture(texture_name);
|
|
}
|
|
|
|
void surface_gatherer_set_worldspawn_layer_filter(bool filter)
|
|
{
|
|
filter_worldspawn_layers = filter;
|
|
}
|
|
|
|
bool surface_gatherer_filter_entity(int entity_idx)
|
|
{
|
|
const entity *ents = map_data_get_entities();
|
|
const entity *ent = &ents[entity_idx];
|
|
|
|
// Omit filtered entity indices
|
|
if(entity_filter_idx != -1 && entity_idx != entity_filter_idx)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool surface_gatherer_filter_brush(int entity_idx, int brush_idx)
|
|
{
|
|
const entity *ents = map_data_get_entities();
|
|
brush *brush_inst = &ents[entity_idx].brushes[brush_idx];
|
|
|
|
// Omit brushes that are fully-textured with clip
|
|
if (brush_filter_texture_idx != -1)
|
|
{
|
|
bool fully_textured = true;
|
|
|
|
for (int f = 0; f < brush_inst->face_count; ++f)
|
|
{
|
|
face *face_inst = &brush_inst->faces[f];
|
|
if (face_inst->texture_idx != brush_filter_texture_idx)
|
|
{
|
|
fully_textured = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(fully_textured)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// Omit brushes that are part of a worldspawn layer
|
|
for (int f = 0; f < brush_inst->face_count; ++f)
|
|
{
|
|
face *face_inst = &brush_inst->faces[f];
|
|
for (int l = 0; l < worldspawn_layer_count; ++l)
|
|
{
|
|
worldspawn_layer *layer = &worldspawn_layers[l];
|
|
if (face_inst->texture_idx == layer->texture_idx)
|
|
{
|
|
return filter_worldspawn_layers;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool surface_gatherer_filter_face(int entity_idx, int brush_idx, int face_idx)
|
|
{
|
|
const entity *ents = map_data_get_entities();
|
|
face *face_inst = &ents[entity_idx].brushes[brush_idx].faces[face_idx];
|
|
face_geometry *face_geo_inst = &entity_geo[entity_idx].brushes[brush_idx].faces[face_idx];
|
|
|
|
// Omit faces with less than 3 vertices
|
|
if (face_geo_inst->vertex_count < 3)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// Omit faces that are textured with skip
|
|
if (face_filter_texture_idx != -1 && face_inst->texture_idx == face_filter_texture_idx)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// Omit filtered texture indices
|
|
if (texture_filter_idx != -1 && face_inst->texture_idx != texture_filter_idx)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void surface_gatherer_reset_state()
|
|
{
|
|
for (int s = 0; s < out_surfaces.surface_count; ++s)
|
|
{
|
|
surface *surf = &out_surfaces.surfaces[s];
|
|
if (surf->vertices != NULL)
|
|
{
|
|
free(surf->vertices);
|
|
surf->vertices = NULL;
|
|
}
|
|
|
|
if (surf->indices != NULL)
|
|
{
|
|
free(surf->indices);
|
|
surf->indices = NULL;
|
|
}
|
|
}
|
|
|
|
if (out_surfaces.surfaces != NULL)
|
|
{
|
|
free(out_surfaces.surfaces);
|
|
out_surfaces.surfaces = NULL;
|
|
}
|
|
|
|
out_surfaces.surface_count = 0;
|
|
}
|
|
|
|
void surface_gatherer_run()
|
|
{
|
|
surface_gatherer_reset_state();
|
|
|
|
int index_offset = 0;
|
|
surface *surf_inst = NULL;
|
|
|
|
if (split_type == SST_NONE)
|
|
{
|
|
index_offset = 0;
|
|
surf_inst = surface_gatherer_add_surface();
|
|
}
|
|
|
|
for (int e = 0; e < entity_count; ++e)
|
|
{
|
|
const entity *entity_inst = &entities[e];
|
|
const entity_geometry *entity_geo_inst = &entity_geo[e];
|
|
|
|
if (surface_gatherer_filter_entity(e))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (split_type == SST_ENTITY)
|
|
{
|
|
if(entity_inst->spawn_type == EST_MERGE_WORLDSPAWN)
|
|
{
|
|
surface_gatherer_add_surface();
|
|
surf_inst = &out_surfaces.surfaces[0];
|
|
index_offset = surf_inst->vertex_count;
|
|
}
|
|
else
|
|
{
|
|
surf_inst = surface_gatherer_add_surface();
|
|
index_offset = surf_inst->vertex_count;
|
|
}
|
|
}
|
|
|
|
for (int b = 0; b < entity_inst->brush_count; ++b)
|
|
{
|
|
brush *brush_inst = &entity_inst->brushes[b];
|
|
brush_geometry *brush_geo_inst = &entity_geo_inst->brushes[b];
|
|
|
|
if (surface_gatherer_filter_brush(e, b))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (split_type == SST_BRUSH)
|
|
{
|
|
index_offset = 0;
|
|
surf_inst = surface_gatherer_add_surface();
|
|
}
|
|
|
|
for (int f = 0; f < brush_inst->face_count; ++f)
|
|
{
|
|
face_geometry *face_geo_inst = &brush_geo_inst->faces[f];
|
|
|
|
if (surface_gatherer_filter_face(e, b, f))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
for (int v = 0; v < face_geo_inst->vertex_count; ++v)
|
|
{
|
|
face_vertex vertex = face_geo_inst->vertices[v];
|
|
|
|
if(entity_inst->spawn_type == EST_ENTITY || entity_inst->spawn_type == EST_GROUP)
|
|
{
|
|
vertex.vertex = vec3_sub(vertex.vertex, entity_inst->center);
|
|
}
|
|
|
|
surf_inst->vertices = realloc(surf_inst->vertices, (surf_inst->vertex_count + 1) * sizeof(face_vertex));
|
|
surf_inst->vertices[surf_inst->vertex_count] = vertex;
|
|
surf_inst->vertex_count++;
|
|
}
|
|
|
|
for (int i = 0; i < (face_geo_inst->vertex_count - 2) * 3; ++i)
|
|
{
|
|
surf_inst->indices = realloc(surf_inst->indices, (surf_inst->index_count + 1) * sizeof(int));
|
|
surf_inst->indices[surf_inst->index_count] = face_geo_inst->indices[i] + index_offset;
|
|
surf_inst->index_count++;
|
|
}
|
|
|
|
index_offset += face_geo_inst->vertex_count;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const surfaces *surface_gatherer_fetch()
|
|
{
|
|
return &out_surfaces;
|
|
}
|
|
|
|
surface *surface_gatherer_add_surface()
|
|
{
|
|
out_surfaces.surfaces = realloc(out_surfaces.surfaces, (out_surfaces.surface_count + 1) * sizeof(surface));
|
|
surface *surf_inst = &out_surfaces.surfaces[out_surfaces.surface_count];
|
|
*surf_inst = (surface){0};
|
|
out_surfaces.surface_count++;
|
|
|
|
return surf_inst;
|
|
}
|
|
|
|
void surface_gatherer_reset_params()
|
|
{
|
|
split_type = SST_NONE;
|
|
entity_filter_idx = -1;
|
|
texture_filter_idx = -1;
|
|
brush_filter_texture_idx = -1;
|
|
face_filter_texture_idx = -1;
|
|
filter_worldspawn_layers = true;
|
|
}
|