S32 LLFace::renderElements(const U16 *index_array) const { S32 ret = 0; if (isState(GLOBAL)) { ret = pushVertices(index_array); } else { glPushMatrix(); glMultMatrixf((float*)getRenderMatrix().mMatrix); ret = pushVertices(index_array); glPopMatrix(); } return ret; }
void StretchableSprite2D::UpdateSourceBatches() { /* The general idea is to subdivide the image in the following 9 patches *---*---*---* 2 | | | | *---*---*---* 1 | | | | *---*---*---* 0 | | | | *---*---*---* 0 1 2 X scaling works as follow: as long as the scale determines that the total width is larger than the sum of the widths of columns 0 and 2, only column 1 is scaled. Otherwise, column 1 is removed and columns 0 and 2 are scaled, maintaining their relative size. The same principle applies for Y scaling (but with lines rather than columns). */ if (!sourceBatchesDirty_ || !sprite_ || (!useTextureRect_ && !sprite_->GetTextureRectangle(textureRect_, flipX_, flipY_))) return; Vector<Vertex2D>& vertices = sourceBatches_[0].vertices_; vertices.Clear(); auto effectiveBorder = calcEffectiveBorder(border_, drawRect_.Size()); float xs[4], ys[4], us[4], vs[4]; // prepare all coordinates const auto signedScale = node_->GetSignedWorldScale(); prepareXYCoords(xs, drawRect_.min_.x_, drawRect_.max_.x_, effectiveBorder.min_.x_, effectiveBorder.max_.x_, signedScale.x_); prepareXYCoords(ys, drawRect_.min_.y_, drawRect_.max_.y_, effectiveBorder.min_.y_, effectiveBorder.max_.y_, signedScale.y_); prepareUVCoords(us, textureRect_.min_.x_, textureRect_.max_.x_, effectiveBorder.min_.x_, effectiveBorder.max_.x_, drawRect_.max_.x_ - drawRect_.min_.x_); prepareUVCoords(vs, textureRect_.min_.y_, textureRect_.max_.y_, -effectiveBorder.min_.y_, -effectiveBorder.max_.y_ /* texture y direction inverted*/, drawRect_.max_.y_ - drawRect_.min_.y_); Vertex2D vtx[4][4]; // prepare all vertices prepareVertices(vtx, xs, ys, us, vs, color_.ToUInt(), node_->GetWorldPosition(), node_->GetWorldRotation()); pushVertices(vertices, vtx); // push the vertices that make up each patch sourceBatchesDirty_ = false; }
// tesselates the contours in preparation for a 3D output; // returns true if all was fine, false otherwise bool VRML_LAYER::Tesselate( VRML_LAYER* holes, bool aHolesOnly ) { if( !tess ) { error = "Tesselate(): GLU tesselator was not initialized"; return false; } pholes = holes; Fault = false; if( aHolesOnly ) gluTessProperty( tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NEGATIVE ); else gluTessProperty( tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE ); if( contours.size() < 1 || vertices.size() < 3 ) { error = "Tesselate(): not enough vertices"; return false; } // finish the winding calculation on all vertices prior to setting 'fix' if( !fix ) { for( unsigned int i = 0; i < contours.size(); ++i ) { if( contours[i]->size() < 3 ) continue; VERTEX_3D* vp0 = vertices[ contours[i]->back() ]; VERTEX_3D* vp1 = vertices[ contours[i]->front() ]; areas[i] += ( vp1->x - vp0->x ) * ( vp1->y + vp0->y ); } } // prevent the addition of any further contours and contour vertices fix = true; // clear temporary internals which may have been used in a previous run clearTmp(); // request an outline gluTessProperty( tess, GLU_TESS_BOUNDARY_ONLY, GL_TRUE ); // adjust internal indices for extra points and holes if( holes ) hidx = holes->GetSize(); else hidx = 0; eidx = idx + hidx; if( aHolesOnly && ( checkNContours( true ) == 0 ) ) { error = "tesselate(): no hole contours"; return false; } else if( !aHolesOnly && ( checkNContours( false ) == 0 ) ) { error = "tesselate(): no solid contours"; return false; } // open the polygon gluTessBeginPolygon( tess, this ); if( aHolesOnly ) { pholes = NULL; // do not accept foreign holes hidx = 0; eidx = idx; // add holes pushVertices( true ); gluTessEndPolygon( tess ); if( Fault ) return false; return true; } // add solid outlines pushVertices( false ); // close the polygon gluTessEndPolygon( tess ); if( Fault ) return false; // if there are no outlines we cannot proceed if( outline.empty() ) { error = "tesselate(): no points in result"; return false; } // at this point we have a solid outline; add it to the tesselator gluTessBeginPolygon( tess, this ); if( !pushOutline( NULL ) ) return false; // add the holes contained by this object pushVertices( true ); // import external holes (if any) if( hidx && ( holes->Import( idx, tess ) < 0 ) ) { std::ostringstream ostr; ostr << "Tesselate():FAILED: " << holes->GetError(); error = ostr.str(); return false; } if( Fault ) return false; // erase the previous outline data and vertex order // but preserve the extra vertices while( !outline.empty() ) { delete outline.back(); outline.pop_back(); } ordmap.clear(); ord = 0; // go through the vertex lists and reset ephemeral parameters for( unsigned int i = 0; i < vertices.size(); ++i ) { vertices[i]->o = -1; } for( unsigned int i = 0; i < extra_verts.size(); ++i ) { extra_verts[i]->o = -1; } // close the polygon; this creates the outline points // and the point ordering list 'ordmap' solid.clear(); gluTessEndPolygon( tess ); // repeat the last operation but request a tesselated surface // rather than an outline; this creates the triangles list. gluTessProperty( tess, GLU_TESS_BOUNDARY_ONLY, GL_FALSE ); gluTessBeginPolygon( tess, this ); if( !pushOutline( holes ) ) return false; gluTessEndPolygon( tess ); if( Fault ) return false; return true; }
// tesselates the contours in preparation for a 3D output; // returns true if all was fine, false otherwise bool VRML_LAYER::Tesselate( VRML_LAYER* holes ) { if( !tess ) { error = "Tesselate(): GLU tesselator was not initialized"; return false; } pholes = holes; Fault = false; if( contours.size() < 1 || vertices.size() < 3 ) { error = "Tesselate(): not enough vertices"; return false; } // finish the winding calculation on all vertices prior to setting 'fix' if( !fix ) { for( unsigned int i = 0; i < contours.size(); ++i ) { if( contours[i]->size() < 3 ) continue; VERTEX_3D* vp0 = vertices[ contours[i]->back() ]; VERTEX_3D* vp1 = vertices[ contours[i]->front() ]; areas[i] += ( vp1->x - vp0->x ) * ( vp1->y + vp0->y ); } } // prevent the addition of any further contours and contour vertices fix = true; // clear temporary internals which may have been used in a previous run clearTmp(); // request an outline gluTessProperty( tess, GLU_TESS_BOUNDARY_ONLY, GL_TRUE ); // adjust internal indices for extra points and holes if( holes ) hidx = holes->GetSize(); else hidx = 0; eidx = idx + hidx; // open the polygon gluTessBeginPolygon( tess, this ); pushVertices( false ); // close the polygon gluTessEndPolygon( tess ); if( Fault ) return false; // push the (solid) outline to the tesselator if( !pushOutline( holes ) ) return false; // add the holes contained by this object pushVertices( true ); // import external holes (if any) if( hidx && ( holes->Import( idx, tess ) < 0 ) ) { std::ostringstream ostr; ostr << "Tesselate():FAILED: " << holes->GetError(); error = ostr.str(); return NULL; } if( Fault ) return false; // erase the previous outline data and vertex order // but preserve the extra vertices for( int i = outline.size(); i > 0; --i ) { delete outline.back(); outline.pop_back(); } for( unsigned int i = ordmap.size(); i > 0; --i ) ordmap.pop_back(); // go through the vertex lists and reset ephemeral parameters for( unsigned int i = 0; i < vertices.size(); ++i ) { vertices[i]->o = -1; } for( unsigned int i = 0; i < extra_verts.size(); ++i ) { extra_verts[i]->o = -1; } ord = 0; // close the polygon; we now have all the data necessary for the tesselation gluTessEndPolygon( tess ); // request a tesselated surface gluTessProperty( tess, GLU_TESS_BOUNDARY_ONLY, GL_FALSE ); if( !pushOutline( holes ) ) return false; gluTessEndPolygon( tess ); if( Fault ) return false; return true; }