⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mesh_builder.cpp

📁 国外游戏开发者杂志2003年第七期配套代码
💻 CPP
字号:
#include "../framework.h"
#include "../mesh.h"
#include "mesh_builder.h"

#include <float.h>
#include <math.h>

Mesh_Builder::Mesh_Builder(int _max_vertices, int _max_faces) {
    max_vertices = _max_vertices;
    max_faces = _max_faces;

    num_vertices = 0;
    num_faces = 0;

    vertex_positions = new Vector3[max_vertices];
    vertex_uvs = new Vector2[max_vertices];
    tangent_frames = new Quaternion[max_vertices];
    faces = new Face[max_faces];
}

void Mesh_Builder::add_material(Mesh_Material_Info *info) {
    Mesh_Material_Info *new_info = new Mesh_Material_Info;
    copy_material_info(new_info, info);
    materials.add(new_info);
}

Mesh_Builder::~Mesh_Builder() {
    delete [] vertex_positions;
    delete [] vertex_uvs;
    delete [] faces;

    Mesh_Material_Info *info;
    Foreach(&materials, info) {
        delete info;
    } Endeach;
}

void Mesh_Builder::add_triangle(int n0, int n1, int n2, int material_index) {
    Face *face = &faces[num_faces++];
    face->n0 = n0;
    face->n1 = n1;
    face->n2 = n2;
    face->material_index = material_index;
}

int Mesh_Builder::add_vertex(Vector3 position, Vector2 uv, Quaternion tangent_frame) {
    vertex_positions[num_vertices] = position;
    vertex_uvs[num_vertices] = uv;
    tangent_frames[num_vertices] = tangent_frame;

    int result = num_vertices;
    num_vertices++;
    return result;
}

int Mesh_Builder::find_end_of_matching_materials(int cursor) {
    int material_to_match = faces[cursor].material_index;

    cursor++;
    while (cursor < num_faces) {
        if (faces[cursor].material_index != material_to_match) break;
        cursor++;
    }

    return cursor;
}

int Mesh_Builder::count_triangle_lists() {
    int cursor = 0;
    int num_lists = 0;

    while (cursor < num_faces) {
        cursor = find_end_of_matching_materials(cursor);
        num_lists++;
    }

    return num_lists;
}

int Mesh_Builder::do_one_triangle_list(int cursor, int list_index,
                                               Triangle_List_Mesh *result) {
    assert(list_index < result->num_triangle_lists);

    int cursor_end = find_end_of_matching_materials(cursor);
    int num_faces = cursor_end - cursor;

    Triangle_List_Info *info = &result->triangle_list_info[list_index];
    info->material_index = faces[cursor].material_index;
    info->num_vertices = num_faces * 3;
    info->start_of_list = cursor * 3;

    while (cursor < cursor_end) {
        Face *face = &faces[cursor];

        assert(face->n0 < num_vertices);
        assert(face->n1 < num_vertices);
        assert(face->n2 < num_vertices);

        result->indices[cursor*3 + 0] = face->n0;
        result->indices[cursor*3 + 1] = face->n1;
        result->indices[cursor*3 + 2] = face->n2;

        cursor++;
    }

    return cursor_end;
}

int compare_face_materials(const void *fp1, const void *fp2) {
    Mesh_Builder::Face *face1 = (Mesh_Builder::Face *)fp1;
    Mesh_Builder::Face *face2 = (Mesh_Builder::Face *)fp2;

    return face1->material_index - face2->material_index;
}

Triangle_List_Mesh *Mesh_Builder::build_mesh() {
    Triangle_List_Mesh *result = new Triangle_List_Mesh();
    result->allocate_geometry(num_vertices, num_faces);

    memcpy(result->vertices, vertex_positions, sizeof(Vector3) * num_vertices);
    memcpy(result->uvs, vertex_uvs, sizeof(Vector2) * num_vertices);
    memcpy(result->tangent_frames, tangent_frames, sizeof(Quaternion) * num_vertices);
    
    qsort(faces, num_faces, sizeof(Face), compare_face_materials);

    result->allocate_materials(materials.items);
    Mesh_Material_Info *src_material;
    int material_cursor = 0;
    Foreach(&materials, src_material) {
        copy_material_info(&result->material_info[material_cursor], src_material);
        material_cursor++;
    } Endeach;

    int num_triangle_lists = count_triangle_lists();
    result->num_triangle_lists = num_triangle_lists;
    result->triangle_list_info = new Triangle_List_Info[num_triangle_lists];


    int face_cursor = 0;
    int list_index = 0;
    while (face_cursor < num_faces) {
        face_cursor = do_one_triangle_list(face_cursor, list_index, result);
        list_index++;
    }

    int i;
    for (i = 0; i < result->num_vertices; i++) result->canonical_vertex_map[i] = i;

    return result;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -