?? gameswf_shape.cpp
字號:
m_last_strip_used = i; return; } } for (i = 0; i <= m_last_strip_used; i++) { array<point>& str = m_strips[i]; assert(str.size() >= 3); // should have at least one tri already. int last = str.size() - 1; if (str[last - 1].bitwise_equal(l0) && str[last].bitwise_equal(r0)) { // Can join these tris to this strip. str.push_back(l1); str.push_back(r1); m_last_strip_used = i; return; } } } // else this trapezoid is pointy on top, so // it's almost certainly the start of a new // strip. Don't bother searching current // strips. // Can't join with existing strip, so start a new strip. m_strips.resize(m_strips.size() + 1); m_strips.back().resize(4); m_strips.back()[0] = l0; m_strips.back()[1] = r0; m_strips.back()[2] = l1; m_strips.back()[3] = r1; } void flush(mesh_set* m, int style) const // Join sub-strips together, and push the whole thing into the given mesh_set, // under the given style. { if (m_strips.size()) { array<point> big_strip; big_strip = m_strips[0]; assert(big_strip.size() >= 3); for (int i = 1, n = m_strips.size(); i < n; i++) { // Append to the big strip. const array<point>& str = m_strips[i]; assert(str.size() >= 3); // should have at least one tri already. int last = big_strip.size() - 1; if (big_strip[last] == str[1] && big_strip[last - 1] == str[0]) { // Strips fit right together. Append. big_strip.append(&str[2], str.size() - 2); } else if (big_strip[last] == str[0] && big_strip[last - 1] == str[1]) { // Strips fit together with a half-twist. point to_dup = big_strip[last - 1]; big_strip.push_back(to_dup); big_strip.append(&str[2], str.size() - 2); } else { // Strips need a degenerate to link them together. point to_dup = big_strip[last]; big_strip.push_back(to_dup); big_strip.push_back(str[0]); big_strip.append(str); } } m->set_tri_strip(style, &big_strip[0], big_strip.size()); } } }; // // mesh_set // mesh_set::mesh_set() :// m_last_frame_rendered(-1), m_error_tolerance(0) // invalid -- don't use this constructor; it's only here for array (@@ fix array) { } mesh_set::mesh_set(const tesselate::tesselating_shape* sh, float error_tolerance) // Tesselate the shape's paths into a different mesh for each fill style. :// m_last_frame_rendered(0), m_error_tolerance(error_tolerance) { struct collect_traps : public tesselate::trapezoid_accepter { mesh_set* m; // the mesh_set that receives trapezoids. // strips-in-progress. hash<int, tri_stripper*> m_strips; collect_traps(mesh_set* set) : m(set) {} virtual ~collect_traps() {} // Overrides from trapezoid_accepter virtual void accept_trapezoid(int style, const tesselate::trapezoid& tr) { // Add trapezoid to appropriate stripper. tri_stripper* s = NULL; m_strips.get(style, &s); if (s == NULL) { s = new tri_stripper; m_strips.add(style, s); } s->add_trapezoid( point(tr.m_lx0, tr.m_y0), point(tr.m_rx0, tr.m_y0), point(tr.m_lx1, tr.m_y1), point(tr.m_rx1, tr.m_y1)); } virtual void accept_line_strip(int style, const point coords[], int coord_count) // Remember this line strip in our mesh set. { m->add_line_strip(style, coords, coord_count); } void flush() const // Push our strips into the mesh set. { for (hash<int, tri_stripper*>::const_iterator it = m_strips.begin(); it != m_strips.end(); ++it) { // Push strip into m. tri_stripper* s = it->second; s->flush(m, it->first); delete s; } } }; collect_traps accepter(this); sh->tesselate(error_tolerance, &accepter); accepter.flush(); // triangles should be collected now into the meshes for each fill style. }// int mesh_set::get_last_frame_rendered() const { return m_last_frame_rendered; }// void mesh_set::set_last_frame_rendered(int frame_counter) { m_last_frame_rendered = frame_counter; } void mesh_set::display( const matrix& mat, const cxform& cx, const array<fill_style>& fills, const array<line_style>& line_styles) const // Throw our meshes at the renderer. { assert(m_error_tolerance > 0); // Setup transforms. render::set_matrix(mat); render::set_cxform(cx); // Dump meshes into renderer, one mesh per style. for (int i = 0; i < m_meshes.size(); i++) { m_meshes[i].display(fills[i], 1.0); } // Dump line-strips into renderer. {for (int i = 0; i < m_line_strips.size(); i++) { int style = m_line_strips[i].get_style(); m_line_strips[i].display(line_styles[style], 1.0); }} } void mesh_set::display( const matrix& mat, const cxform& cx, const array<morph_fill_style>& fills, const array<morph_line_style>& line_styles, float ratio) const // Throw our meshes at the renderer. { assert(m_error_tolerance > 0); // Setup transforms. render::set_matrix(mat); render::set_cxform(cx); // Dump meshes into renderer, one mesh per style. for (int i = 0; i < m_meshes.size(); i++) { m_meshes[i].display(fills[i], ratio); } // Dump line-strips into renderer. {for (int i = 0; i < m_line_strips.size(); i++) { int style = m_line_strips[i].get_style(); m_line_strips[i].display(line_styles[style], ratio); }} } void mesh_set::set_tri_strip(int style, const point pts[], int count) // Set mesh associated with the given fill style to the // specified triangle strip. { assert(style >= 0); assert(style < 10000); // sanity check // Expand our mesh list if necessary. if (style >= m_meshes.size()) { m_meshes.resize(style + 1); } m_meshes[style].set_tri_strip(pts, count); } void mesh_set::add_line_strip(int style, const point coords[], int coord_count) // Add the specified line strip to our list of things to render. { assert(style >= 0); assert(style < 1000); // sanity check assert(coords != NULL); assert(coord_count > 1); m_line_strips.push_back(line_strip(style, coords, coord_count)); } void mesh_set::output_cached_data(tu_file* out) // Dump our data to the output stream. { out->write_float32(m_error_tolerance); int mesh_n = m_meshes.size(); out->write_le32(mesh_n); for (int i = 0; i < mesh_n; i++) { m_meshes[i].output_cached_data(out); } int lines_n = m_line_strips.size(); out->write_le32(lines_n); {for (int i = 0; i < lines_n; i++) { m_line_strips[i].output_cached_data(out); }} } void mesh_set::input_cached_data(tu_file* in) // Grab our data from the input stream. { m_error_tolerance = in->read_float32(); int mesh_n = in->read_le32(); m_meshes.resize(mesh_n); for (int i = 0; i < mesh_n; i++) { m_meshes[i].input_cached_data(in); } int lines_n = in->read_le32(); m_line_strips.resize(lines_n); {for (int i = 0; i < lines_n; i++) { m_line_strips[i].input_cached_data(in); }} } // // helper functions. // static void read_fill_styles(array<fill_style>* styles, stream* in, int tag_type, movie_definition_sub* m) // Read fill styles, and push them onto the given style array. { assert(styles); // Get the count. int fill_style_count = in->read_u8(); if (tag_type > 2) { if (fill_style_count == 0xFF) { fill_style_count = in->read_u16(); } } IF_VERBOSE_PARSE(log_msg(" read_fill_styles: count = %d\n", fill_style_count)); // Read the styles. for (int i = 0; i < fill_style_count; i++) { (*styles).resize((*styles).size() + 1); (*styles)[(*styles).size() - 1].read(in, tag_type, m); } } static void read_line_styles(array<line_style>* styles, stream* in, int tag_type) // Read line styles and push them onto the back of the given array. { // Get the count. int line_style_count = in->read_u8(); IF_VERBOSE_PARSE(log_msg(" read_line_styles: count = %d\n", line_style_count)); // @@ does the 0xFF flag apply to all tag types? // if (tag_type > 2) // { if (line_style_count == 0xFF) { line_style_count = in->read_u16(); IF_VERBOSE_PARSE(log_msg(" read_line_styles: count2 = %d\n", line_style_count)); } // } // Read the styles. for (int i = 0; i < line_style_count; i++) { (*styles).resize((*styles).size() + 1); (*styles)[(*styles).size() - 1].read(in, tag_type); } } // // shape_character_def // shape_character_def::shape_character_def() { } shape_character_def::~shape_character_def() { // Free our mesh_sets. for (int i = 0; i < m_cached_meshes.size(); i++) { delete m_cached_meshes[i]; } } void shape_character_def::read(stream* in, int tag_type, bool with_style, movie_definition_sub* m) { if (with_style) { m_bound.read(in); read_fill_styles(&m_fill_styles, in, tag_type, m); read_line_styles(&m_line_styles, in, tag_type); } // // SHAPE // int num_fill_bits = in->read_uint(4); int num_line_bits = in->read_uint(4); IF_VERBOSE_PARSE(log_msg(" shape_character read: nfillbits = %d, nlinebits = %d\n", num_fill_bits, num_line_bits)); // These are state variables that keep the // current position & style of the shape // outline, and vary as we read the edge data. // // At the moment we just store each edge with // the full necessary info to render it, which // is simple but not optimally efficient. int fill_base = 0; int line_base = 0; float x = 0, y = 0; path current_path;#define SHAPE_LOG 0 // SHAPERECORDS for (;;) { int type_flag = in->read_uint(1); if (type_flag == 0) { // Parse the record. int flags = in->read_uint(5); if (flags == 0) { // End of shape records. // Store the current path if any. if (! current_path.is_empty()) { m_paths.push_back(current_path); current_path.m_edges.resize(0); } break; } if (flags & 0x01) { // move_to = 1; // Store the current path if any, and prepare a fresh one. if (! current_path.is_empty()) { m_paths.push_back(current_path); current_path.m_edges.resize(0); } int num_move_bits = in->read_uint(5); int move_x = in->read_sint(num_move_bits); int move_y = in->read_sint(num_move_bits); x = (float) move_x; y = (float) move_y; // Set the beginning of the path. current_path.m_ax = x; current_path.m_ay = y; if (SHAPE_LOG) IF_VERBOSE_PARSE(log_msg(" shape_character read: moveto %4g %4g\n", x, y)); } if ((flags & 0x02) && num_fill_bits > 0) { // fill_style_0_change = 1; if (! current_path.is_empty()) { m_paths.push_back(current_path); current_path.m_edges.resize(0); current_path.m_ax = x; current_path.m_ay = y; } int style = in->read_uint(num_fill_bits); if (style > 0) { style += fill_base; } current_path.m_fill0 = style; if (SHAPE_LOG) IF_VERBOSE_PARSE(log_msg(" shape_character read: fill0 = %d\n", current_path.m_fill0)); } if ((flags & 0x04) && num_fill_bits > 0) { // fill_style_1_change = 1; if (! current_path.is_empty()) { m_paths.push_back(current_path); current_path.m_edges.resize(0); current_path.m_ax = x; current_path.m_ay = y; } int style = in->read_uint(num_fill_bits); if (style > 0) { style += fill_base; } current_path.m_fill1 = style; if (SHAPE_LOG) IF_VERBOSE_PARSE(log_msg(" shape_character read: fill1 = %d\n", current_path.m_fill1)); } if ((flags & 0x08) && num_line_bits > 0) { // line_style_change = 1; if (! current_path.is_empty()) { m_paths.push_back(current_path); current_path.m_edges.resize(0); current_path.m_ax = x;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -