source: other-projects/playing-in-the-street/summer-2013/trunk/Playing-in-the-Street-WPF/Content/Web/mrdoob-three.js-4862f5f/utils/converters/utf8/src/objcompress.cc@ 28897

Last change on this file since 28897 was 28897, checked in by davidb, 10 years ago

GUI front-end to server base plus web page content

File size: 6.2 KB
Line 
1#if 0 // A cute trick to making this .cc self-building from shell.
2g++ $0 -O2 -Wall -Werror -o `basename $0 .cc`;
3exit;
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
25int main(int argc, const char* argv[]) {
26 if (argc != 3) {
27 fprintf(stderr, "Usage: %s in.obj out.utf8\n\n"
28 "\tCompress in.obj to out.utf8 and writes JS to STDOUT.\n\n",
29 argv[0]);
30 return -1;
31 }
32 FILE* fp = fopen(argv[1], "r");
33 WavefrontObjFile obj(fp);
34 fclose(fp);
35
36 printf("MODELS[\'%s\'] = {\n", StripLeadingDir(argv[1]));
37 puts(" materials: {");
38 const MaterialList& materials = obj.materials();
39 for (size_t i = 0; i < materials.size(); ++i) {
40 materials[i].DumpJson();
41 }
42 puts(" },");
43
44 const MaterialBatches& batches = obj.material_batches();
45
46 // Pass 1: compute bounds.
47 webgl_loader::Bounds bounds;
48 bounds.Clear();
49 for (MaterialBatches::const_iterator iter = batches.begin();
50 iter != batches.end(); ++iter) {
51 const DrawBatch& draw_batch = iter->second;
52 bounds.Enclose(draw_batch.draw_mesh().attribs);
53 }
54 webgl_loader::BoundsParams bounds_params =
55 webgl_loader::BoundsParams::FromBounds(bounds);
56 printf(" decodeParams: ");
57 bounds_params.DumpJson();
58
59 puts(" urls: {");
60 std::vector<char> utf8;
61 webgl_loader::VectorSink sink(&utf8);
62 // Pass 2: quantize, optimize, compress, report.
63 for (MaterialBatches::const_iterator iter = batches.begin();
64 iter != batches.end(); ++iter) {
65 size_t offset = 0;
66 utf8.clear();
67 const DrawMesh& draw_mesh = iter->second.draw_mesh();
68 if (draw_mesh.indices.empty()) continue;
69
70 QuantizedAttribList quantized_attribs;
71 webgl_loader::AttribsToQuantizedAttribs(draw_mesh.attribs, bounds_params,
72 &quantized_attribs);
73 VertexOptimizer vertex_optimizer(quantized_attribs);
74 const std::vector<GroupStart>& group_starts = iter->second.group_starts();
75 WebGLMeshList webgl_meshes;
76 std::vector<size_t> group_lengths;
77 for (size_t i = 1; i < group_starts.size(); ++i) {
78 const size_t here = group_starts[i-1].offset;
79 const size_t length = group_starts[i].offset - here;
80 group_lengths.push_back(length);
81 vertex_optimizer.AddTriangles(&draw_mesh.indices[here], length,
82 &webgl_meshes);
83 }
84 const size_t here = group_starts.back().offset;
85 const size_t length = draw_mesh.indices.size() - here;
86 const bool divisible_by_3 = length % 3 == 0;
87 CHECK(divisible_by_3);
88 group_lengths.push_back(length);
89 vertex_optimizer.AddTriangles(&draw_mesh.indices[here], length,
90 &webgl_meshes);
91
92 std::vector<std::string> material;
93 std::vector<size_t> attrib_start, attrib_length, index_start, index_length;
94 for (size_t i = 0; i < webgl_meshes.size(); ++i) {
95 const size_t num_attribs = webgl_meshes[i].attribs.size();
96 const size_t num_indices = webgl_meshes[i].indices.size();
97 const bool kBadSizes = num_attribs % 8 || num_indices % 3;
98 CHECK(!kBadSizes);
99 webgl_loader::CompressQuantizedAttribsToUtf8(webgl_meshes[i].attribs,
100 &sink);
101 webgl_loader::CompressIndicesToUtf8(webgl_meshes[i].indices, &sink);
102 material.push_back(iter->first);
103 attrib_start.push_back(offset);
104 attrib_length.push_back(num_attribs / 8);
105 index_start.push_back(offset + num_attribs);
106 index_length.push_back(num_indices / 3);
107 offset += num_attribs + num_indices;
108 }
109 const uint32 hash = SimpleHash(&utf8[0], utf8.size());
110 char buf[9] = { '\0' };
111 ToHex(hash, buf);
112 // TODO: this needs to handle paths.
113 std::string out_fn = std::string(buf) + "." + argv[2];
114 FILE* out_fp = fopen(out_fn.c_str(), "wb");
115 printf(" \'%s\': [\n", out_fn.c_str());
116 size_t group_index = 0;
117 for (size_t i = 0; i < webgl_meshes.size(); ++i) {
118 printf(" { material: \'%s\',\n"
119 " attribRange: [" PRIuS ", " PRIuS "],\n"
120 " indexRange: [" PRIuS ", " PRIuS "],\n"
121 " bboxes: " PRIuS ",\n"
122 " names: [",
123 material[i].c_str(),
124 attrib_start[i], attrib_length[i],
125 index_start[i], index_length[i],
126 offset);
127 std::vector<size_t> buffered_lengths;
128 size_t group_start = 0;
129 while (group_index < group_lengths.size()) {
130 printf("\'%s\', ",
131 obj.LineToGroup(group_starts[group_index].group_line).c_str());
132 const size_t group_length = group_lengths[group_index];
133 const size_t next_start = group_start + group_length;
134 const size_t webgl_index_length = webgl_meshes[i].indices.size();
135 // TODO: bbox info is better placed at the head of the file,
136 // perhaps transposed. Also, when a group gets split between
137 // batches, the bbox gets stored twice.
138 webgl_loader::CompressAABBToUtf8(group_starts[group_index].bounds,
139 bounds_params, &sink);
140 offset += 6;
141 if (next_start < webgl_index_length) {
142 buffered_lengths.push_back(group_length);
143 group_start = next_start;
144 ++group_index;
145 } else {
146 const size_t fits = webgl_index_length - group_start;
147 buffered_lengths.push_back(fits);
148 group_start = 0;
149 group_lengths[group_index] -= fits;
150 break;
151 }
152 }
153 printf("],\n lengths: [");
154 for (size_t k = 0; k < buffered_lengths.size(); ++k) {
155 printf(PRIuS ", ", buffered_lengths[k]);
156 }
157 puts("],\n },");
158 }
159 fwrite(&utf8[0], 1, utf8.size(), out_fp);
160 fclose(out_fp);
161 puts(" ],");
162 }
163 puts(" }\n};");
164 return 0;
165}
Note: See TracBrowser for help on using the repository browser.