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

📄 preprocess_world.cpp

📁 国外游戏开发者杂志2003年第七期配套代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
        for (j = 0; j < 3; j++) {
            Seam_Index *index = &seam->indices[i*3+j];
            orig_index[j] = index->vertex_index;

            World_Block *block = seam->block_membership[index->which_mesh];

            if (block == root) {
                spec_a[j] = get_spec(index, result_a);
                spec_b[j] = get_spec(index, result_b);

                int xref_a, xref_b;
                xref_a = find_output_vertex(index, result_a);
                xref_b = find_output_vertex(index, result_b);
                if (xref_a != -1) {
                    block = block_a;
                    results[j] = result_a;

                    tmp_indices[j] = *index;
                    tmp_indices[j].vertex_index = xref_a;
                    tmp_indices_a[j] = tmp_indices[j];

                    dest_seams[j] = result_seam_a;
                    num_a_indices++;
                }

                if (xref_b != -1) {
                    block = block_b;
                    results[j] = result_b;

                    tmp_indices[j] = *index;
                    tmp_indices[j].vertex_index = xref_b;
                    tmp_indices_b[j] = tmp_indices[j];

                    dest_seams[j] = result_seam_b;
                    num_b_indices++;
                }
            } else {
                tmp_indices[j] = *index;
                tmp_indices_a[j] = *index;
                tmp_indices_b[j] = *index;
                results[j] = NULL;
                dest_seams[j] = NULL;

                n0 = j;
                n1 = (j + 1) % 3;
                n2 = (j + 2) % 3;

                num_c_indices++;
            }

            blocks[j] = block;
        }

        if ((num_c_indices == 2) && (num_a_indices + num_b_indices > 1)) {
            // XXX Fucking fuck it for now
        }

        if (num_a_indices + num_c_indices == 3) {
            add_face(result_seam_a, tmp_indices_a);
        } 

        if (num_b_indices + num_c_indices == 3) {
            add_face(result_seam_b, tmp_indices_b);
        }

        if ((num_a_indices == 1) && (num_b_indices == 1) && (num_c_indices == 1)) {
            // This face spans 3 blocks now... gotta clip it!

            // n0 is the vertex that is not on the block being
            // split... which must exist, so n0 != -1.
            assert(n0 != -1);


            Vertex_Specifier spec(orig_index[n1], orig_index[n2]);
            rectify(&spec);

            Seam_Index new_face[3];
            new_face[0] = tmp_indices[n0];

            int xref_1 = find_clip_vertex(&spec, results[n1]);
            if (xref_1 == -1) continue;  // XXX Think harder about this

            new_face[1] = tmp_indices[n1];
            new_face[2] = tmp_indices[n1];
            new_face[2].vertex_index = xref_1;

            add_face(dest_seams[n1], new_face);


            int xref_2 = find_clip_vertex(&spec, results[n2]);
            if (xref_2 == -1) continue;  // XXX Think harder about this

            new_face[1] = tmp_indices[n2];
            new_face[1].vertex_index = xref_2;
            new_face[2] = tmp_indices[n2];
            add_face(dest_seams[n2], new_face);



            Mesh_Seam *new_seam = new Mesh_Seam(1); // XXX spammy!
            new_seam->num_faces = 0;
            new_seam->block_membership[0] = blocks[n0];
            new_seam->block_membership[1] = blocks[n1];
            new_seam->block_membership[2] = blocks[n2];

            // new_face[0].vertex_index stays the same from above.
            new_face[0].which_mesh = 0;
            new_face[1].which_mesh = 1;
            new_face[2].which_mesh = 2;

            new_face[1].vertex_index = xref_1;
            new_face[2].vertex_index = xref_2;

            add_face(new_seam, new_face);
            maybe_add(construction_database, new_seam);
        }
    }

//    sanity_check(result_seam_a);
//    sanity_check(result_seam_b);

    maybe_add(construction_database, result_seam_a);
    maybe_add(construction_database, result_seam_b);
}

void World_Processor::do_rewrite_rules(World_Block *root,
                                       World_Block *block_a,
                                       World_Block *block_b,
                                       Chopped_Result *result_a,
                                       Chopped_Result *result_b) {
    Auto_Array <Mesh_Seam *> seams;
    construction_database->find_seams_containing_at_least_this_block(root, &seams);

    Mesh_Seam *seam;
    Array_Foreach(&seams, seam) {
        do_single_rewrite(root, seam, block_a, block_b, result_a, result_b);
    } Endeach;
}

Plane3 get_plane_from_mesh(Triangle_List_Mesh *mesh) {
    assert(mesh->num_vertices > 0);

    Vector3 mean(0, 0, 0);
    Covariance3 cov;
    cov.reset();

    // XXXXXXXXXXXXXXXXX do barycenter here, not mesh->vertex
    int i;
    for (i = 0; i < mesh->num_vertices; i++) {
        mean += mesh->vertices[i];
        cov.accumulate(mesh->vertices[i]);
    }

    float factor = (1.0f / (float)mesh->num_vertices);
    mean *= factor;
    cov.scale(factor);

    Covariance3 local;
    cov.move_to_local_coordinates(&local, mean);
    
    float eigenvalues[3];
    Vector3 eigenvectors[3];
    local.find_eigenvectors(eigenvalues, eigenvectors);

//    mean = Vector3(0, 0, 0);
//    eigenvectors[0] = Vector3(1, 0, 0);

    Vector3 normal = eigenvectors[0];
/*
    if ((fabs(normal.x) > fabs(normal.y)) && (fabs(normal.x) > fabs(normal.z))) {
        normal.set(1, 0, 0);
    } else if ((fabs(normal.y) > fabs(normal.x)) && (fabs(normal.y) > fabs(normal.z))) {
        normal.set(0, 1, 0);
    } else {
        normal.set(0, 0, 1);
    }
*/
    return Plane3(mean, normal);
}

void World_Processor::chop_leaves(World_Block *root) {
    Triangle_List_Mesh *mesh = root->mesh;
    if (!mesh) return;  // Shouldn't happen??

    if (mesh->num_faces <= TRIANGLE_MAXIMUM) return;


    printf("Split %d (%d)\n", root->leaf_distance, mesh->num_faces);

    // Split mesh...


    Mesh_Chopper chopper;
    Chopped_Result result_a;
    Chopped_Result result_b;

    
    Plane3 plane = get_plane_from_mesh(mesh);

    int plane_id = 0;
    Mesh_Seam *seam_a_to_b;
    chopper.chop_mesh(mesh, &plane, plane_id,
                      &result_a, &result_b, &seam_a_to_b);

    World_Block *block_a = new World_Block();
    block_init_for_subdivide_step(block_a, result_a.result_mesh);

    World_Block *block_b = new World_Block();
    block_init_for_subdivide_step(block_b, result_b.result_mesh);

    seam_a_to_b->block_membership[0] = block_a;
    seam_a_to_b->block_membership[1] = block_b;

    block_a->leaf_distance = root->leaf_distance - 1;
    block_b->leaf_distance = root->leaf_distance - 1;
    if (seam_a_to_b->num_faces) construction_database->add(seam_a_to_b);

    root->children[0] = block_a;
    root->children[1] = block_b;
    root->num_children = 2;

    do_rewrite_rules(root, block_a, block_b, &result_a, &result_b);
    delete result_a.vertex_hash_table;
    delete result_b.vertex_hash_table;


    // Get rid of it!

    delete mesh;
    root->mesh = NULL;

    if (root->num_children) {
        int i;
        for (i = 0; i < root->num_children; i++) {
            chop_leaves(root->children[i]);
        }
    }
}

World_Processor::World_Processor() {
    next_block_id = 1;  // 0 is reserved!
    construction_database = new Seam_Database();
    root = NULL;
}

World_Processor::~World_Processor() {
    delete construction_database;
}

World_Block *World_Processor::chop_mesh(Triangle_List_Mesh *mesh,
                                        Plane3 *planes, int num_planes) {
    World_Block *block = new World_Block();
    block_init_for_subdivide_step(block, mesh);
    block->leaf_distance = 500;

    int i;
    for (i = 0; i < num_planes; i++) {
        chop_leaves(block);
    }

    root = block;
    return block;
}

void main(int argc, char **argv) {
    Elevation_Map *map;
    char *filename = NULL;

    if (argc > 1) {
        filename = argv[1];
    }

/*
    if (filename == NULL) {
        fprintf(stderr, "Please specify a file to load!\n");
        exit(1);
    }

    if (map == NULL) {
        assert(filename);
        fprintf(stderr, "Unable to open map file '%s'!\n", filename);
        exit(1);
    }

*/

    Triangle_List_Mesh *mesh = load_quake();

    char *output_filename = "output.world_lod";
    FILE *f = fopen(output_filename, "wb");
    if (f == NULL) {
        fprintf(stderr, "Unable to open output file '%s' for writing!\n",
                output_filename);
        exit(1);
    }

    // Make some splitting planes
    
    const int MAX_PLANES = 20;
    Plane3 planes[MAX_PLANES];
    int num_planes = 0;
    const float k = 1.0f;

    planes[num_planes++] = Plane3(Vector3(0, 0, 0), Vector3(1, 0, 0));
    planes[num_planes++] = Plane3(Vector3(0, 0, 3), Vector3(0, 0, 1));

    Vector3 weird1(1, 0, 1);
    weird1.normalize();
    Vector3 weird2(.11, -.4, 1);
    weird2.normalize();
    planes[num_planes++] = Plane3(Vector3(0.5, 0, 3), weird1);
    planes[num_planes++] = Plane3(Vector3(0, 0, 2.6), weird2);

    World_Processor processor;
    processor.chop_mesh(mesh, planes, num_planes);
    processor.finish_subdivide_phase();

    processor.do_merges();

    printf("Leaf distances.\n");
    processor.recompute_leaf_distances(processor.root);

    save_world(processor.root, processor.construction_database, f);
    fclose(f);
    printf("Saved result as '%s'.\n", output_filename);

    exit(0);
}

⌨️ 快捷键说明

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