[28897] | 1 | #if 0 // A cute trick to making this .cc self-building from shell.
|
---|
| 2 | g++ $0 -O2 -Wall -Werror -o `basename $0 .cc`;
|
---|
| 3 | exit;
|
---|
| 4 | #endif
|
---|
| 5 | // Copyright 2011 Google Inc. All Rights Reserved.
|
---|
| 6 | //
|
---|
| 7 | // Licensed under the Apache License, Version 2.0 (the "License"); you
|
---|
| 8 | // may not use this file except in compliance with the License. You
|
---|
| 9 | // may obtain a copy of the License at
|
---|
| 10 | //
|
---|
| 11 | // http://www.apache.org/licenses/LICENSE-2.0
|
---|
| 12 | //
|
---|
| 13 | // Unless required by applicable law or agreed to in writing, software
|
---|
| 14 | // distributed under the License is distributed on an "AS IS" BASIS,
|
---|
| 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
---|
| 16 | // implied. See the License for the specific language governing
|
---|
| 17 | // permissions and limitations under the License.
|
---|
| 18 |
|
---|
| 19 | #include "bounds.h"
|
---|
| 20 | #include "compress.h"
|
---|
| 21 | #include "mesh.h"
|
---|
| 22 | #include "optimize.h"
|
---|
| 23 | #include "stream.h"
|
---|
| 24 |
|
---|
| 25 | int main(int argc, const char* argv[]) {
|
---|
| 26 | FILE* json_out = stdout;
|
---|
| 27 | if (argc != 3 && argc != 4) {
|
---|
| 28 | fprintf(stderr, "Usage: %s in.obj out.utf8\n\n"
|
---|
| 29 | "\tCompress in.obj to out.utf8 and writes JS to STDOUT.\n\n",
|
---|
| 30 | argv[0]);
|
---|
| 31 | return -1;
|
---|
| 32 | } else if (argc == 4) {
|
---|
| 33 | json_out = fopen(argv[3], "w");
|
---|
| 34 | CHECK(json_out != NULL);
|
---|
| 35 | }
|
---|
| 36 |
|
---|
| 37 | FILE* fp = fopen(argv[1], "r");
|
---|
| 38 | WavefrontObjFile obj(fp);
|
---|
| 39 | fclose(fp);
|
---|
| 40 |
|
---|
| 41 | fputs("{\n \"materials\": {\n", json_out);
|
---|
| 42 | const MaterialList& materials = obj.materials();
|
---|
| 43 | for (size_t i = 0; i < materials.size(); ++i) {
|
---|
| 44 | materials[i].DumpJson(json_out);
|
---|
| 45 | const bool last = i == materials.size() - 1;
|
---|
| 46 | fputs(",\n" + last, json_out);
|
---|
| 47 | }
|
---|
| 48 | fputs(" },\n", json_out);
|
---|
| 49 |
|
---|
| 50 | const MaterialBatches& batches = obj.material_batches();
|
---|
| 51 |
|
---|
| 52 | // Pass 1: compute bounds.
|
---|
| 53 | webgl_loader::Bounds bounds;
|
---|
| 54 | bounds.Clear();
|
---|
| 55 | for (MaterialBatches::const_iterator iter = batches.begin();
|
---|
| 56 | iter != batches.end(); ++iter) {
|
---|
| 57 | const DrawBatch& draw_batch = iter->second;
|
---|
| 58 | bounds.Enclose(draw_batch.draw_mesh().attribs);
|
---|
| 59 | }
|
---|
| 60 | webgl_loader::BoundsParams bounds_params =
|
---|
| 61 | webgl_loader::BoundsParams::FromBounds(bounds);
|
---|
| 62 | fputs(" \"decodeParams\": ", json_out);
|
---|
| 63 | bounds_params.DumpJson(json_out);
|
---|
| 64 | fputs(",\n \"urls\": {\n", json_out);
|
---|
| 65 | // Pass 2: quantize, optimize, compress, report.
|
---|
| 66 | FILE* utf8_out_fp = fopen(argv[2], "wb");
|
---|
| 67 | CHECK(utf8_out_fp != NULL);
|
---|
| 68 | fprintf(json_out, " \"%s\": [\n", argv[2]);
|
---|
| 69 | webgl_loader::FileSink utf8_sink(utf8_out_fp);
|
---|
| 70 | size_t offset = 0;
|
---|
| 71 | MaterialBatches::const_iterator iter = batches.begin();
|
---|
| 72 | while (iter != batches.end()) {
|
---|
| 73 | const DrawMesh& draw_mesh = iter->second.draw_mesh();
|
---|
| 74 | if (draw_mesh.indices.empty()) {
|
---|
| 75 | ++iter;
|
---|
| 76 | continue;
|
---|
| 77 | }
|
---|
| 78 | QuantizedAttribList quantized_attribs;
|
---|
| 79 | webgl_loader::AttribsToQuantizedAttribs(draw_mesh.attribs, bounds_params,
|
---|
| 80 | &quantized_attribs);
|
---|
| 81 | VertexOptimizer vertex_optimizer(quantized_attribs);
|
---|
| 82 | const std::vector<GroupStart>& group_starts = iter->second.group_starts();
|
---|
| 83 | WebGLMeshList webgl_meshes;
|
---|
| 84 | std::vector<size_t> group_lengths;
|
---|
| 85 | for (size_t i = 1; i < group_starts.size(); ++i) {
|
---|
| 86 | const size_t here = group_starts[i-1].offset;
|
---|
| 87 | const size_t length = group_starts[i].offset - here;
|
---|
| 88 | group_lengths.push_back(length);
|
---|
| 89 | vertex_optimizer.AddTriangles(&draw_mesh.indices[here], length,
|
---|
| 90 | &webgl_meshes);
|
---|
| 91 | }
|
---|
| 92 | const size_t here = group_starts.back().offset;
|
---|
| 93 | const size_t length = draw_mesh.indices.size() - here;
|
---|
| 94 | CHECK(length % 3 == 0);
|
---|
| 95 | group_lengths.push_back(length);
|
---|
| 96 | vertex_optimizer.AddTriangles(&draw_mesh.indices[here], length,
|
---|
| 97 | &webgl_meshes);
|
---|
| 98 |
|
---|
| 99 | std::vector<std::string> material;
|
---|
| 100 | // TODO: is this buffering still necessary?
|
---|
| 101 | std::vector<size_t> attrib_start, attrib_length,
|
---|
| 102 | code_start, code_length, num_tris;
|
---|
| 103 | for (size_t i = 0; i < webgl_meshes.size(); ++i) {
|
---|
| 104 | const size_t num_attribs = webgl_meshes[i].attribs.size();
|
---|
| 105 | const size_t num_indices = webgl_meshes[i].indices.size();
|
---|
| 106 | CHECK(num_attribs % 8 == 0);
|
---|
| 107 | CHECK(num_indices % 3 == 0);
|
---|
| 108 | webgl_loader::EdgeCachingCompressor compressor(webgl_meshes[i].attribs,
|
---|
| 109 | webgl_meshes[i].indices);
|
---|
| 110 | compressor.Compress(&utf8_sink);
|
---|
| 111 | material.push_back(iter->first);
|
---|
| 112 | attrib_start.push_back(offset);
|
---|
| 113 | attrib_length.push_back(num_attribs / 8);
|
---|
| 114 | code_start.push_back(offset + num_attribs);
|
---|
| 115 | code_length.push_back(compressor.codes().size());
|
---|
| 116 | num_tris.push_back(num_indices / 3);
|
---|
| 117 | offset += num_attribs + compressor.codes().size();
|
---|
| 118 | }
|
---|
| 119 | for (size_t i = 0; i < webgl_meshes.size(); ++i) {
|
---|
| 120 | fprintf(json_out,
|
---|
| 121 | " { \"material\": \"%s\",\n"
|
---|
| 122 | " \"attribRange\": [" PRIuS ", " PRIuS "],\n"
|
---|
| 123 | " \"codeRange\": [" PRIuS ", " PRIuS ", " PRIuS "]\n"
|
---|
| 124 | " }",
|
---|
| 125 | material[i].c_str(),
|
---|
| 126 | attrib_start[i], attrib_length[i],
|
---|
| 127 | code_start[i], code_length[i], num_tris[i]);
|
---|
| 128 | if (i != webgl_meshes.size() - 1) {
|
---|
| 129 | fputs(",\n", json_out);
|
---|
| 130 | }
|
---|
| 131 | }
|
---|
| 132 | const bool last = (++iter == batches.end());
|
---|
| 133 | fputs(",\n" + last, json_out);
|
---|
| 134 | }
|
---|
| 135 | fputs(" ]\n", json_out);
|
---|
| 136 | fputs(" }\n}", json_out);
|
---|
| 137 | return 0;
|
---|
| 138 | }
|
---|