void App::slotHelpAbout() { AboutBox ab(this); ab.exec(); }
ftype pointLineDist(const Point& p, const Point& a, const Point& b) { Vec ab(a, b), ap(a, p); return abs(ab.cross(ap)) / sqrt(ab.norm_sq()); }
int main() {for (long long a,b,c,d,r;~scanf("%lld%lld%lld%lld%lld",&a,&b,&c,&d,&r);puts((ab(c-a)+ab(d-b) >r ? "alive" : "die"))) ;}
void I (int j) { int m,g,e; if( d == 288) { ad(); ad(); m= U (); ad(); I (j); if( d == 312) { ad(); g=B(0); A(m); I (j); A(g); } else { A(m); } } else if( d == 352|d == 504) { e=d; ad(); ad(); if( e == 352) { g=q; m= U (); } else { if( d!= 59)w (); ad(); g=q; m= 0; if( d!= 59)m= U (); ad(); if( d!= 41) { e=B(0); w (); B(g-q-5); A(e); g=e +4; } } ad(); I(&m); B(g-q-5); A(m); } else if( d == 123) { ad(); ab(1); while( d!= 125)I (j); ad(); } else { if( d == 448) { ad(); if( d!= 59)w (); K=B(K); } else if( d == 400) { ad(); *(int*) j=B(*(int*) j); } else if( d!= 59)w (); ad(); } }
void ImageSysData::Paint(SystemDraw& w, int x, int y, const Rect& src, Color c) { GuiLock __; x += w.GetOffset().x; y += w.GetOffset().y; Size sz = img.GetSize(); int len = sz.cx * sz.cy; Rect sr = src & sz; Size ssz = sr.Size(); if(sr.IsEmpty()) return; int kind = img.GetKind(); if(kind == IMAGE_EMPTY) return; if(kind == IMAGE_OPAQUE && !IsNull(c)) { w.DrawRect(x, y, sz.cx, sz.cy, c); return; } if(kind == IMAGE_OPAQUE && paintcount == 0 && sr == Rect(sz)) { SetSurface(w, x, y, sz.cx, sz.cy, ~img); paintcount++; return; } if(IsNull(c)) { if(!picture) { bool opaque = kind == IMAGE_OPAQUE; Pixmap pixmap = XCreatePixmap(Xdisplay, Xroot, sz.cx, sz.cy, opaque ? 24 : 32); picture = XRenderCreatePicture( Xdisplay, pixmap, XRenderFindStandardFormat(Xdisplay, opaque ? PictStandardRGB24 : PictStandardARGB32), 0, 0 ); XImage ximg; sInitXImage(ximg, sz); ximg.bitmap_pad = 32; ximg.bytes_per_line = 4 * sz.cx; ximg.bits_per_pixel = 32; ximg.blue_mask = 0x00ff0000; ximg.green_mask = 0x0000ff00; ximg.red_mask = 0x000000ff; ximg.bitmap_unit = 32; ximg.data = (char *)~img; ximg.depth = opaque ? 24 : 32; XInitImage(&ximg); GC gc = XCreateGC(Xdisplay, pixmap, 0, 0); XPutImage(Xdisplay, pixmap, gc, &ximg, 0, 0, 0, 0, sz.cx, sz.cy); XFreeGC(Xdisplay, gc); XFreePixmap(Xdisplay, pixmap); SysImageRealized(img); } XRenderComposite(Xdisplay, PictOpOver, picture, 0, XftDrawPicture(w.GetXftDraw()), sr.left, sr.top, 0, 0, x, y, ssz.cx, ssz.cy); } else { if(!picture8) { Pixmap pixmap = XCreatePixmap(Xdisplay, Xroot, sz.cx, sz.cy, 8); picture8 = XRenderCreatePicture(Xdisplay, pixmap, XRenderFindStandardFormat(Xdisplay, PictStandardA8), 0, 0); Buffer<byte> ab(len); byte *t = ab; const RGBA *s = ~img; const RGBA *e = s + len; while(s < e) *t++ = (s++)->a; XImage ximg; sInitXImage(ximg, sz); ximg.data = (char *)~ab; ximg.bitmap_unit = 8; ximg.bitmap_pad = 8; ximg.depth = 8; ximg.bytes_per_line = sz.cx; ximg.bits_per_pixel = 8; XInitImage(&ximg); GC gc = XCreateGC(Xdisplay, pixmap, 0, 0); XPutImage(Xdisplay, pixmap, gc, &ximg, 0, 0, 0, 0, sz.cx, sz.cy); XFreeGC(Xdisplay, gc); XFreePixmap(Xdisplay, pixmap); } XRenderComposite(Xdisplay, PictOpOver, sGetSolidFill(c), picture8, XftDrawPicture(w.GetXftDraw()), sr.left, sr.top, 0, 0, x, y, ssz.cx, ssz.cy); } }
bool Edge3D::intercept(const Point3D &p1, const Point3D &p2) const { double min, max, pmin, pmax; //if the bounding boxes of the two edges do not intercept, then // the two edges do not intercept Point3D *tp1 = (Point3D *)this->getP1(); Point3D *tp2 = (Point3D *)this->getP2(); if (tp1->getX() > tp2->getX()) { min = tp2->getX(); max = tp1->getX(); } else { min = tp1->getX(); max = tp2->getX(); } if (p1.getX() > p2.getX()) { pmin = p2.getX(); pmax = p1.getX(); } else { pmin = p1.getX(); pmax = p2.getX(); } if ((min > pmax) || (max < pmin)) { return false; } if (tp1->getY() > tp2->getY()) { min = tp2->getY(); max = tp1->getY(); } else { min = tp1->getY(); max = tp2->getY(); } if (p1.getY() > p2.getY()) { pmin = p2.getY(); pmax = p1.getY(); } else { pmin = p1.getY(); pmax = p2.getY(); } if ((min > pmax) || (max < pmin)) { return false; } Vector3D ab(this->vector()); Vector3D ac(*tp1, p1); Vector3D ad(*tp1, p2); Vector3D cd(p1, p2); Vector3D ca(p1, *tp1); Vector3D cb(p1, *tp2); return ( (ab.cross(ac).getX() * ab.cross(ad).getX() + ab.cross(ac).getY() * ab.cross(ad).getY() + ab.cross(ac).getZ() * ab.cross(ad).getZ() < 0.0) && (cd.cross(ca).getX() * cd.cross(cb).getX() + cd.cross(ca).getY() * cd.cross(cb).getY() + cd.cross(ca).getZ() * cd.cross(cb).getZ() < 0.0) ); }
void HalfedgeMesh::build(const vector<vector<Index> >& polygons, const vector<Vector3D>& vertexPositions) // This method initializes the halfedge data structure from a raw list of // polygons, where each input polygon is specified as a list of vertex indices. // The input must describe a manifold, oriented surface, where the orientation // of a polygon is determined by the order of vertices in the list. Polygons // must have at least three vertices. Note that there are no special conditions // on the vertex indices, i.e., they do not have to start at 0 or 1, nor does // the collection of indices have to be contiguous. Overall, this initializer // is designed to be robust but perhaps not incredibly fast (though of course // this does not affect the performance of the resulting data structure). One // could also implement faster initializers that handle important special cases // (e.g., all triangles, or data that is known to be manifold). Since there are // no strong conditions on the indices of polygons, we assume that the list of // vertex positions is given in lexicographic order (i.e., that the lowest index // appearing in any polygon corresponds to the first entry of the list of // positions and so on). { // define some types, to improve readability typedef vector<Index> IndexList; typedef IndexList::const_iterator IndexListCIter; typedef vector<IndexList> PolygonList; typedef PolygonList::const_iterator PolygonListCIter; typedef pair<Index, Index> IndexPair; // ordered pair of vertex indices, // corresponding to an edge of an // oriented polygon // Clear any existing elements. halfedges.clear(); vertices.clear(); edges.clear(); faces.clear(); boundaries.clear(); // Since the vertices in our halfedge mesh are stored in a linked list, // we will temporarily need to keep track of the correspondence between // indices of vertices in our input and pointers to vertices in the new // mesh (which otherwise can't be accessed by index). Note that since // we're using a general-purpose map (rather than, say, a vector), we can // be a bit more flexible about the indexing scheme: input vertex indices // aren't required to be 0-based or 1-based; in fact, the set of indices // doesn't even have to be contiguous. Taking advantage of this fact makes // our conversion a bit more robust to different types of input, including // data that comes from a subset of a full mesh. // maps a vertex index to the corresponding vertex map<Index, VertexIter> indexToVertex; // Also store the vertex degree, i.e., the number of polygons that use each // vertex; this information will be used to check that the mesh is manifold. map<VertexIter, Size> vertexDegree; // First, we do some basic sanity checks on the input. for (PolygonListCIter p = polygons.begin(); p != polygons.end(); p++) { if (p->size() < 3) { // Refuse to build the mesh if any of the polygons have fewer than three // vertices.(Note that if we omit this check the code will still // constructsomething fairlymeaningful for 1- and 2-point polygons, but // enforcing this stricterrequirementon the input will help simplify code // further downstream, since it canbe certainit doesn't have to check for // these rather degenerate cases.) cerr << "Error converting polygons to halfedge mesh: each polygon must " "have at least three vertices." << endl; exit(1); } // We want to count the number of distinct vertex indices in this // polygon, to make sure it's the same as the number of vertices // in the polygon---if they disagree, then the polygon is not valid // (or at least, for simplicity we don't handle polygons of this type!). set<Index> polygonIndices; // loop over polygon vertices for (IndexListCIter i = p->begin(); i != p->end(); i++) { polygonIndices.insert(*i); // allocate one vertex for each new index we encounter if (indexToVertex.find(*i) == indexToVertex.end()) { VertexIter v = newVertex(); v->halfedge() = halfedges.end(); // this vertex doesn't yet point to any halfedge indexToVertex[*i] = v; vertexDegree[v] = 1; // we've now seen this vertex only once } else { // keep track of the number of times we've seen this vertex vertexDegree[indexToVertex[*i]]++; } } // end loop over polygon vertices // check that all vertices of the current polygon are distinct Size degree = p->size(); // number of vertices in this polygon if (polygonIndices.size() < degree) { cerr << "Error converting polygons to halfedge mesh: one of the input " "polygons does not have distinct vertices!" << endl; cerr << "(vertex indices:"; for (IndexListCIter i = p->begin(); i != p->end(); i++) { cerr << " " << *i; } cerr << ")" << endl; exit(1); } // end check that polygon vertices are distinct } // end basic sanity checks on input // The number of vertices in the mesh is the // number of unique indices seen in the input. Size nVertices = indexToVertex.size(); // The number of faces is just the number of polygons in the input. Size nFaces = polygons.size(); faces.resize(nFaces); // allocate storage for faces in our new mesh // We will store a map from ordered pairs of vertex indices to // the corresponding halfedge object in our new (halfedge) mesh; // this map gets constructed during the next loop over polygons. map<IndexPair, HalfedgeIter> pairToHalfedge; // Next, we actually build the halfedge connectivity by again looping over // polygons PolygonListCIter p; FaceIter f; for (p = polygons.begin(), f = faces.begin(); p != polygons.end(); p++, f++) { vector<HalfedgeIter> faceHalfedges; // cyclically ordered list of the half // edges of this face Size degree = p->size(); // number of vertices in this polygon // loop over the halfedges of this face (equivalently, the ordered pairs of // consecutive vertices) for (Index i = 0; i < degree; i++) { Index a = (*p)[i]; // current index Index b = (*p)[(i + 1) % degree]; // next index, in cyclic order IndexPair ab(a, b); HalfedgeIter hab; // check if this halfedge already exists; if so, we have a problem! if (pairToHalfedge.find(ab) != pairToHalfedge.end()) { cerr << "Error converting polygons to halfedge mesh: found multiple " "oriented edges with indices (" << a << ", " << b << ")." << endl; cerr << "This means that either (i) more than two faces contain this " "edge (hence the surface is nonmanifold), or" << endl; cerr << "(ii) there are exactly two faces containing this edge, but " "they have the same orientation (hence the surface is" << endl; cerr << "not consistently oriented." << endl; exit(1); } else // otherwise, the halfedge hasn't been allocated yet { // so, we point this vertex pair to a new halfedge hab = newHalfedge(); pairToHalfedge[ab] = hab; // link the new halfedge to its face hab->face() = f; hab->face()->halfedge() = hab; // also link it to its starting vertex hab->vertex() = indexToVertex[a]; hab->vertex()->halfedge() = hab; // keep a list of halfedges in this face, so that we can later // link them together in a loop (via their "next" pointers) faceHalfedges.push_back(hab); } // Also, check if the twin of this halfedge has already been constructed // (during construction of a different face). If so, link the twins // together and allocate their shared halfedge. By the end of this pass // over polygons, the only halfedges that will not have a twin will hence // be those that sit along the domain boundary. IndexPair ba(b, a); map<IndexPair, HalfedgeIter>::iterator iba = pairToHalfedge.find(ba); if (iba != pairToHalfedge.end()) { HalfedgeIter hba = iba->second; // link the twins hab->twin() = hba; hba->twin() = hab; // allocate and link their edge EdgeIter e = newEdge(); hab->edge() = e; hba->edge() = e; e->halfedge() = hab; } else { // If we didn't find a twin... // ...mark this halfedge as being twinless by pointing // it to the end of the list of halfedges. If it remains // twinless by the end of the current loop over polygons, // it will be linked to a boundary face in the next pass. hab->twin() = halfedges.end(); } } // end loop over the current polygon's halfedges // Now that all the halfedges of this face have been allocated, // we can link them together via their "next" pointers. for (Index i = 0; i < degree; i++) { Index j = (i + 1) % degree; // index of the next halfedge, in cyclic order faceHalfedges[i]->next() = faceHalfedges[j]; } } // done building basic halfedge connectivity // For each vertex on the boundary, advance its halfedge pointer to one that // is also on the boundary. for (VertexIter v = verticesBegin(); v != verticesEnd(); v++) { // loop over halfedges around vertex HalfedgeIter h = v->halfedge(); do { if (h->twin() == halfedges.end()) { v->halfedge() = h; break; } h = h->twin()->next(); } while (h != v->halfedge()); // end loop over halfedges around vertex } // done advancing halfedge pointers for boundary vertices // Next we construct new faces for each boundary component. for (HalfedgeIter h = halfedgesBegin(); h != halfedgesEnd(); h++) // loop over all halfedges { // Any halfedge that does not yet have a twin is on the boundary of the // domain. If we follow the boundary around long enough we will of course // eventually make a closed loop; we can represent this boundary loop by a // new face. To make clear the distinction between faces and boundary loops, // the boundary face will (i) have a flag indicating that it is a boundary // loop, and (ii) be stored in a list of boundaries, rather than the usual // list of faces. The reason we need the both the flag *and* the separate // list is that faces are often accessed in two fundamentally different // ways: either by (i) local traversal of the neighborhood of some mesh // element using the halfedge structure, or (ii) global traversal of all // faces (or boundary loops). if (h->twin() == halfedges.end()) { FaceIter b = newBoundary(); vector<HalfedgeIter> boundaryHalfedges; // keep a list of halfedges along // the boundary, so we can link // them together // We now need to walk around the boundary, creating new // halfedges and edges along the boundary loop as we go. HalfedgeIter i = h; do { // create a twin, which becomes a halfedge of the boundary loop HalfedgeIter t = newHalfedge(); boundaryHalfedges.push_back( t); // keep a list of all boundary halfedges, in cyclic order i->twin() = t; t->twin() = i; t->face() = b; t->vertex() = i->next()->vertex(); // create the shared edge EdgeIter e = newEdge(); e->halfedge() = i; i->edge() = e; t->edge() = e; // Advance i to the next halfedge along the current boundary loop // by walking around its target vertex and stopping as soon as we // find a halfedge that does not yet have a twin defined. i = i->next(); while (i != h && // we're done if we end up back at the beginning of // the loop i->twin() != halfedges.end()) // otherwise, we're looking for // the next twinless halfedge // along the loop { i = i->twin(); i = i->next(); } } while (i != h); // The only pointers that still need to be set are the "next" pointers of // the twins; these we can set from the list of boundary halfedges, but we // must use the opposite order from the order in the list, since the // orientation of the boundary loop is opposite the orientation of the // halfedges "inside" the domain boundary. Size degree = boundaryHalfedges.size(); for (Index p = 0; p < degree; p++) { Index q = (p - 1 + degree) % degree; boundaryHalfedges[p]->next() = boundaryHalfedges[q]; } } // end construction of one of the boundary loops // Note that even though we are looping over all halfedges, we will still // construct the appropriate number of boundary loops (and not, say, one // loop per boundary halfedge). The reason is that as we continue to // iterate through halfedges, we check whether their twin has been assigned, // and since new twins may have been assigned earlier in this loop, we will // end up skipping many subsequent halfedges. } // done adding "virtual" faces corresponding to boundary loops // To make later traversal of the mesh easier, we will now advance the // halfedge // associated with each vertex such that it refers to the *first* non-boundary // halfedge, rather than the last one. for (VertexIter v = verticesBegin(); v != verticesEnd(); v++) { v->halfedge() = v->halfedge()->twin()->next(); } // Finally, we check that all vertices are manifold. for (VertexIter v = vertices.begin(); v != vertices.end(); v++) { // First check that this vertex is not a "floating" vertex; // if it is then we do not have a valid 2-manifold surface. if (v->halfedge() == halfedges.end()) { cerr << "Error converting polygons to halfedge mesh: some vertices are " "not referenced by any polygon." << endl; exit(1); } // Next, check that the number of halfedges emanating from this vertex in // our half edge data structure equals the number of polygons containing // this vertex, which we counted during our first pass over the mesh. If // not, then our vertex is not a "fan" of polygons, but instead has some // other (nonmanifold) structure. Size count = 0; HalfedgeIter h = v->halfedge(); do { if (!h->face()->isBoundary()) { count++; } h = h->twin()->next(); } while (h != v->halfedge()); if (count != vertexDegree[v]) { cerr << "Error converting polygons to halfedge mesh: at least one of the " "vertices is nonmanifold." << endl; exit(1); } } // end loop over vertices // Now that we have the connectivity, we copy the list of vertex // positions into member variables of the individual vertices. if (vertexPositions.size() != vertices.size()) { cerr << "Error converting polygons to halfedge mesh: number of vertex " "positions is different from the number of distinct vertices!" << endl; cerr << "(number of positions in input: " << vertexPositions.size() << ")" << endl; cerr << "( number of vertices in mesh: " << vertices.size() << ")" << endl; exit(1); } // Since an STL map internally sorts its keys, we can iterate over the map // from vertex indices to vertex iterators to visit our (input) vertices in // lexicographic order int i = 0; for (map<Index, VertexIter>::const_iterator e = indexToVertex.begin(); e != indexToVertex.end(); e++) { // grab a pointer to the vertex associated with the current key (i.e., the // current index) VertexIter v = e->second; // set the att of this vertex to the corresponding // position in the input v->position = vertexPositions[i]; i++; } // compute initial normals for (VertexIter v = verticesBegin(); v != verticesEnd(); v++) { v->computeNormal(); } } // end HalfedgeMesh::build()
bool CurveWarp::accelerated_cairorender(Context context, cairo_t *cr, int quality, const RendDesc &renddesc_, ProgressCallback *cb)const { Point start_point=param_start_point.get(Point()); Point end_point=param_end_point.get(Point()); SuperCallback stageone(cb,0,9000,10000); SuperCallback stagetwo(cb,9000,10000,10000); RendDesc renddesc(renddesc_); // Untransform the render desc if(!cairo_renddesc_untransform(cr, renddesc)) return false; int x,y; const Real pw(renddesc.get_pw()),ph(renddesc.get_ph()); Point tl(renddesc.get_tl()); Point br(renddesc.get_br()); const int w(renddesc.get_w()); const int h(renddesc.get_h()); // find a bounding rectangle for the context we need to render // todo: find a better way of doing this - this way doesn't work Rect src_rect(transform(tl)); Point pos1, pos2; Real dist, along; Real min_dist(999999), max_dist(-999999), min_along(999999), max_along(-999999); #define UPDATE_DIST \ if (dist < min_dist) min_dist = dist; \ if (dist > max_dist) max_dist = dist; \ if (along < min_along) min_along = along; \ if (along > max_along) max_along = along // look along the top and bottom edges pos1[0] = pos2[0] = tl[0]; pos1[1] = tl[1]; pos2[1] = br[1]; for (x = 0; x < w; x++, pos1[0] += pw, pos2[0] += pw) { src_rect.expand(transform(pos1, &dist, &along)); UPDATE_DIST; src_rect.expand(transform(pos2, &dist, &along)); UPDATE_DIST; } // look along the left and right edges pos1[0] = tl[0]; pos2[0] = br[0]; pos1[1] = pos2[1] = tl[1]; for (y = 0; y < h; y++, pos1[1] += ph, pos2[1] += ph) { src_rect.expand(transform(pos1, &dist, &along)); UPDATE_DIST; src_rect.expand(transform(pos2, &dist, &along)); UPDATE_DIST; } // look along the diagonals const int max_wh(std::max(w,h)); const Real inc_x((br[0]-tl[0])/max_wh),inc_y((br[1]-tl[1])/max_wh); pos1[0] = pos2[0] = tl[0]; pos1[1] = tl[1]; pos2[1] = br[1]; for (x = 0; x < max_wh; x++, pos1[0] += inc_x, pos2[0] = pos1[0], pos1[1]+=inc_y, pos2[1]-=inc_y) { src_rect.expand(transform(pos1, &dist, &along)); UPDATE_DIST; src_rect.expand(transform(pos2, &dist, &along)); UPDATE_DIST; } #if 0 // look at each blinepoint std::vector<synfig::BLinePoint>::const_iterator iter; for (iter=bline.begin(); iter!=bline.end(); iter++) src_rect.expand(transform(iter->get_vertex()+origin, &dist, &along)); UPDATE_DIST; #endif Point src_tl(src_rect.get_min()); Point src_br(src_rect.get_max()); Vector ab((end_point - start_point).norm()); Angle::tan ab_angle(ab[1], ab[0]); Real used_length = max_along - min_along; Real render_width = max_dist - min_dist; int src_w = (abs(used_length*Angle::cos(ab_angle).get()) + abs(render_width*Angle::sin(ab_angle).get())) / abs(pw); int src_h = (abs(used_length*Angle::sin(ab_angle).get()) + abs(render_width*Angle::cos(ab_angle).get())) / abs(ph); Real src_pw((src_br[0] - src_tl[0]) / src_w); Real src_ph((src_br[1] - src_tl[1]) / src_h); if (src_pw > abs(pw)) { src_w = int((src_br[0] - src_tl[0]) / abs(pw)); src_pw = (src_br[0] - src_tl[0]) / src_w; } if (src_ph > abs(ph)) { src_h = int((src_br[1] - src_tl[1]) / abs(ph)); src_ph = (src_br[1] - src_tl[1]) / src_h; } #define MAXPIX 10000 if (src_w > MAXPIX) src_w = MAXPIX; if (src_h > MAXPIX) src_h = MAXPIX; // this is an attempt to remove artifacts around tile edges - the // cubic interpolation uses at most 2 pixels either side of the // target pixel, so add an extra 2 pixels around the tile on all // sides src_tl -= (Point(src_pw,src_ph)*2); src_br += (Point(src_pw,src_ph)*2); src_w += 4; src_h += 4; src_pw = (src_br[0] - src_tl[0]) / src_w; src_ph = (src_br[1] - src_tl[1]) / src_h; // set up a renddesc for the context to render RendDesc src_desc(renddesc); //src_desc.clear_flags(); src_desc.set_tl(src_tl); src_desc.set_br(src_br); src_desc.set_wh(src_w, src_h); // New expanded renddesc values const double wpw=src_desc.get_pw(); const double wph=src_desc.get_ph(); const double wtlx=src_desc.get_tl()[0]; const double wtly=src_desc.get_tl()[1]; // render the context onto a new surface cairo_surface_t* csource, *cresult; csource=cairo_surface_create_similar(cairo_get_target(cr),CAIRO_CONTENT_COLOR_ALPHA, src_w, src_h); cresult=cairo_surface_create_similar(cairo_get_target(cr),CAIRO_CONTENT_COLOR_ALPHA, w, h); cairo_t *subcr=cairo_create(csource); cairo_scale(subcr, 1/wpw, 1/wph); cairo_translate(subcr, -wtlx, -wtly); if(!context.accelerated_cairorender(subcr,quality,src_desc,&stageone)) return false; // don't needed anymore cairo_destroy(subcr); //access to pixels CairoSurface source(csource); source.map_cairo_image(); CairoSurface result(cresult); result.map_cairo_image(); float u,v; Point pos, tmp; if(quality<=4) // CUBIC for(y=0,pos[1]=tl[1];y<h;y++,pos[1]+=ph) { for(x=0,pos[0]=tl[0];x<w;x++,pos[0]+=pw) { tmp=transform(pos); u=(tmp[0]-src_tl[0])/src_pw; v=(tmp[1]-src_tl[1])/src_ph; if(u<0 || v<0 || u>=src_w || v>=src_h || isnan(u) || isnan(v)) result[y][x]=CairoColor(context.get_color(tmp)).premult_alpha(); else result[y][x]=source.cubic_sample_cooked(u,v); } if((y&31)==0 && cb && !stagetwo.amount_complete(y,h)) return false; } else if (quality<=6) // INTERPOLATION_LINEAR for(y=0,pos[1]=tl[1];y<h;y++,pos[1]+=ph) { for(x=0,pos[0]=tl[0];x<w;x++,pos[0]+=pw) { tmp=transform(pos); u=(tmp[0]-src_tl[0])/src_pw; v=(tmp[1]-src_tl[1])/src_ph; if(u<0 || v<0 || u>=src_w || v>=src_h || isnan(u) || isnan(v)) result[y][x]=CairoColor(context.get_color(tmp)).premult_alpha(); else result[y][x]=source.linear_sample_cooked(u,v); } if((y&31)==0 && cb && !stagetwo.amount_complete(y,h)) return false; } else // NEAREST_NEIGHBOR for(y=0,pos[1]=tl[1];y<h;y++,pos[1]+=ph) { for(x=0,pos[0]=tl[0];x<w;x++,pos[0]+=pw) { tmp=transform(pos); u=(tmp[0]-src_tl[0])/src_pw; v=(tmp[1]-src_tl[1])/src_ph; if(u<0 || v<0 || u>=src_w || v>=src_h || isnan(u) || isnan(v)) result[y][x]=CairoColor(context.get_color(tmp)).premult_alpha(); else result[y][x]=source[floor_to_int(v)][floor_to_int(u)]; } if((y&31)==0 && cb && !stagetwo.amount_complete(y,h)) return false; } result.unmap_cairo_image(); source.unmap_cairo_image(); cairo_surface_destroy(csource); // Now paint it on the context cairo_save(cr); cairo_translate(cr, tl[0], tl[1]); cairo_scale(cr, pw, ph); cairo_set_source_surface(cr, cresult, 0, 0); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_paint(cr); cairo_restore(cr); cairo_surface_destroy(cresult); // Mark our progress as finished if(cb && !cb->amount_complete(10000,10000)) return false; return true; }
int main() { Mercator::Terrain terrain; terrain.setBasePoint(0, 0, 2.8); terrain.setBasePoint(1, 0, 7.1); terrain.setBasePoint(0, 1, 0.2); terrain.setBasePoint(1, 1, 14.7); Mercator::Segment * segment = terrain.getSegment(0, 0); if (segment == 0) { std::cerr << "Segment not created by addition of required basepoints" << std::endl << std::flush; return 1; } segment->populate(); //test box definitely outside terrain WFMath::AxisBox<3> highab(WFMath::Point<3> (10.0, 10.0, segment->getMax() + 3.0), WFMath::Point<3> (20.0, 20.0, segment->getMax() + 6.1)); if (Mercator::Intersect(terrain, highab)) { std::cerr << "axisbox intersects with terrain even though it should be above it" << std::endl; return 1; } //test box definitely inside terrain WFMath::AxisBox<3> lowab(WFMath::Point<3> (10.0, 10.0, segment->getMin() - 6.1), WFMath::Point<3> (20.0, 20.0, segment->getMax() - 3.0)); if (!Mercator::Intersect(terrain, lowab)) { std::cerr << "axisbox does not intersect with terrain even though it should be below it" << std::endl; return 1; } //test axis box moved from above terrain to below it. bool inter=false; float dz = highab.highCorner()[2] - highab.lowCorner()[2] - 0.1; while (highab.highCorner()[2] > segment->getMin()) { highab.shift(WFMath::Vector<3>(0.0, 0.0, -dz)); if (Mercator::Intersect(terrain, highab)) { inter=true; break; } } if (!inter) { std::cerr << "axisbox passed through terrain with no intersection" << std::endl; return 1; } //test axisbox that spans two segments terrain.setBasePoint(0, 2, 4.8); terrain.setBasePoint(1, 2, 3.7); Mercator::Segment *segment2 = terrain.getSegment(0, 1); segment2->populate(); float segmax=std::max(segment->getMax(), segment2->getMax()); float segmin=std::min(segment->getMin(), segment2->getMin()); WFMath::AxisBox<3> ab(WFMath::Point<3> (50.0, 10.0, segmax + 3.0), WFMath::Point<3> (70.0, 20.0, segmax + 6.1)); if (Mercator::Intersect(terrain, ab)) { std::cerr << "axisbox2 intersects with terrain even though it should be above it" << std::endl; return 1; } WFMath::AxisBox<3> ab2(WFMath::Point<3> (50.0, 10.0, segmin - 6.1), WFMath::Point<3> (70.0, 20.0, segmin + 3.0)); if (!Mercator::Intersect(terrain, ab2)) { std::cerr << "axisbox2 does not intersect with terrain even though it should be below it" << std::endl; return 1; } WFMath::Point<3> intPoint; WFMath::Vector<3> intNorm; float par; //test vertical ray if (Mercator::Intersect(terrain, WFMath::Point<3>(20.1, 20.2, segmax + 3), WFMath::Vector<3>(0.0,0.0,50.0), intPoint, intNorm, par)) { std::cerr << "vertical ray intersected when it shouldnt" << std::endl; return 1; } if (!Mercator::Intersect(terrain, WFMath::Point<3>(20.1, 20.2, segmax + 3), WFMath::Vector<3>(0.0,0.0,-50.0), intPoint, intNorm, par)) { std::cerr << "vertical ray didnt intersect when it should" << std::endl; return 1; } //test each quadrant if (!Mercator::Intersect(terrain, WFMath::Point<3>(20.1, 20.2, segmax + 3), WFMath::Vector<3>(10.0,10.0,-100.0), intPoint, intNorm, par)) { std::cerr << "quad1 ray didnt intersect when it should" << std::endl; return 1; } if (!Mercator::Intersect(terrain, WFMath::Point<3>(20.1, 20.2, segmax + 3), WFMath::Vector<3>(10.0,-15.0,-50.0), intPoint, intNorm, par)) { std::cerr << "quad2 ray didnt intersect when it should" << std::endl; return 1; } if (!Mercator::Intersect(terrain, WFMath::Point<3>(20.1, 20.2, segmax + 3), WFMath::Vector<3>(-10.0,-10.0,-50.0), intPoint, intNorm, par)) { std::cerr << "quad3 ray didnt intersect when it should" << std::endl; return 1; } if (!Mercator::Intersect(terrain, WFMath::Point<3>(20.1, 20.2, segmax + 3), WFMath::Vector<3>(-10.0,10.0,-50.0), intPoint, intNorm, par)) { std::cerr << "quad4 ray didnt intersect when it should" << std::endl; return 1; } //test dx==0 and dy==0 if (!Mercator::Intersect(terrain, WFMath::Point<3>(20.1, 20.2, segmax + 3), WFMath::Vector<3>(0.0,10.0,-50.0), intPoint, intNorm, par)) { std::cerr << "y+ ray didnt intersect when it should" << std::endl; return 1; } if (!Mercator::Intersect(terrain, WFMath::Point<3>(20.1, 20.2, segmax + 3), WFMath::Vector<3>(0.0,-10.0,-50.0), intPoint, intNorm, par)) { std::cerr << "y- ray didnt intersect when it should" << std::endl; return 1; } if (!Mercator::Intersect(terrain, WFMath::Point<3>(20.1, 20.2, segmax + 3), WFMath::Vector<3>(-10.0,0.0,-50.0), intPoint, intNorm, par)) { std::cerr << "x- ray didnt intersect when it should" << std::endl; return 1; } if (!Mercator::Intersect(terrain, WFMath::Point<3>(20.1, 20.2, segmax + 3), WFMath::Vector<3>(10.0,0.0,-50.0), intPoint, intNorm, par)) { std::cerr << "x+ ray didnt intersect when it should" << std::endl; return 1; } //test a longer ray if (!Mercator::Intersect(terrain, WFMath::Point<3>(-10.08, -20.37, segmax + 3), WFMath::Vector<3>(100.0,183.0,-50.0), intPoint, intNorm, par)) { std::cerr << "long ray didnt intersect when it should" << std::endl; return 1; } //check the height value float h; WFMath::Vector<3> n; terrain.getHeightAndNormal(intPoint[0], intPoint[1], h, n); n.normalize(); if (n != intNorm) { std::cerr << "calculated normal is different from getHeightAndNormal" << std::endl; std::cerr << intPoint << std::endl; std::cerr << intNorm << "!=" << n << std::endl; // return 1; } // We can't check for equality here is it just doesn't work with // floats. Look it up in any programming book if you don't believe me. // - 20040721 <*****@*****.**> if (fabs(h - intPoint[2]) > 0.00001) { std::cerr << "calculated height is different from getHeightAndNormal" << std::endl; std::cerr << h << "!=" << intPoint[2] << std::endl; return 1; } return 0; }
void ContainerNode::setAttributeEventListener(const AtomicString& eventType, const QualifiedName& attributeName, const AtomicString& attributeValue) { Attribute ab(attributeName,attributeValue); setAttributeEventListener(eventType, createAttributeEventListener(this, &ab));//CMP_ERROR , use v8 instead of jsc }
bool CurveWarp::accelerated_render(Context context,Surface *surface,int quality, const RendDesc &renddesc, ProgressCallback *cb)const { Point start_point=param_start_point.get(Point()); Point end_point=param_end_point.get(Point()); SuperCallback stageone(cb,0,9000,10000); SuperCallback stagetwo(cb,9000,10000,10000); int x,y; const Real pw(renddesc.get_pw()),ph(renddesc.get_ph()); Point tl(renddesc.get_tl()); Point br(renddesc.get_br()); const int w(renddesc.get_w()); const int h(renddesc.get_h()); // find a bounding rectangle for the context we need to render // todo: find a better way of doing this - this way doesn't work Rect src_rect(transform(tl)); Point pos1, pos2; Real dist, along; Real min_dist(999999), max_dist(-999999), min_along(999999), max_along(-999999); #define UPDATE_DIST \ if (dist < min_dist) min_dist = dist; \ if (dist > max_dist) max_dist = dist; \ if (along < min_along) min_along = along; \ if (along > max_along) max_along = along // look along the top and bottom edges pos1[0] = pos2[0] = tl[0]; pos1[1] = tl[1]; pos2[1] = br[1]; for (x = 0; x < w; x++, pos1[0] += pw, pos2[0] += pw) { src_rect.expand(transform(pos1, &dist, &along)); UPDATE_DIST; src_rect.expand(transform(pos2, &dist, &along)); UPDATE_DIST; } // look along the left and right edges pos1[0] = tl[0]; pos2[0] = br[0]; pos1[1] = pos2[1] = tl[1]; for (y = 0; y < h; y++, pos1[1] += ph, pos2[1] += ph) { src_rect.expand(transform(pos1, &dist, &along)); UPDATE_DIST; src_rect.expand(transform(pos2, &dist, &along)); UPDATE_DIST; } // look along the diagonals const int max_wh(std::max(w,h)); const Real inc_x((br[0]-tl[0])/max_wh),inc_y((br[1]-tl[1])/max_wh); pos1[0] = pos2[0] = tl[0]; pos1[1] = tl[1]; pos2[1] = br[1]; for (x = 0; x < max_wh; x++, pos1[0] += inc_x, pos2[0] = pos1[0], pos1[1]+=inc_y, pos2[1]-=inc_y) { src_rect.expand(transform(pos1, &dist, &along)); UPDATE_DIST; src_rect.expand(transform(pos2, &dist, &along)); UPDATE_DIST; } #if 0 // look at each blinepoint std::vector<synfig::BLinePoint>::const_iterator iter; for (iter=bline.begin(); iter!=bline.end(); iter++) src_rect.expand(transform(iter->get_vertex()+origin, &dist, &along)); UPDATE_DIST; #endif Point src_tl(src_rect.get_min()); Point src_br(src_rect.get_max()); Vector ab((end_point - start_point).norm()); Angle::tan ab_angle(ab[1], ab[0]); Real used_length = max_along - min_along; Real render_width = max_dist - min_dist; int src_w = (abs(used_length*Angle::cos(ab_angle).get()) + abs(render_width*Angle::sin(ab_angle).get())) / abs(pw); int src_h = (abs(used_length*Angle::sin(ab_angle).get()) + abs(render_width*Angle::cos(ab_angle).get())) / abs(ph); Real src_pw((src_br[0] - src_tl[0]) / src_w); Real src_ph((src_br[1] - src_tl[1]) / src_h); if (src_pw > abs(pw)) { src_w = int((src_br[0] - src_tl[0]) / abs(pw)); src_pw = (src_br[0] - src_tl[0]) / src_w; } if (src_ph > abs(ph)) { src_h = int((src_br[1] - src_tl[1]) / abs(ph)); src_ph = (src_br[1] - src_tl[1]) / src_h; } #define MAXPIX 10000 if (src_w > MAXPIX) src_w = MAXPIX; if (src_h > MAXPIX) src_h = MAXPIX; // this is an attempt to remove artifacts around tile edges - the // cubic interpolation uses at most 2 pixels either side of the // target pixel, so add an extra 2 pixels around the tile on all // sides src_tl -= (Point(src_pw,src_ph)*2); src_br += (Point(src_pw,src_ph)*2); src_w += 4; src_h += 4; src_pw = (src_br[0] - src_tl[0]) / src_w; src_ph = (src_br[1] - src_tl[1]) / src_h; // set up a renddesc for the context to render RendDesc src_desc(renddesc); src_desc.clear_flags(); src_desc.set_tl(src_tl); src_desc.set_br(src_br); src_desc.set_wh(src_w, src_h); // render the context onto a new surface Surface source; source.set_wh(src_w,src_h); if(!context.accelerated_render(&source,quality,src_desc,&stageone)) return false; float u,v; Point pos, tmp; surface->set_wh(w,h); surface->clear(); if(quality<=4) // CUBIC for(y=0,pos[1]=tl[1];y<h;y++,pos[1]+=ph) { for(x=0,pos[0]=tl[0];x<w;x++,pos[0]+=pw) { tmp=transform(pos); u=(tmp[0]-src_tl[0])/src_pw; v=(tmp[1]-src_tl[1])/src_ph; if(u<0 || v<0 || u>=src_w || v>=src_h || isnan(u) || isnan(v)) (*surface)[y][x]=context.get_color(tmp); else (*surface)[y][x]=source.cubic_sample(u,v); } if((y&31)==0 && cb && !stagetwo.amount_complete(y,h)) return false; } else if (quality<=6) // INTERPOLATION_LINEAR for(y=0,pos[1]=tl[1];y<h;y++,pos[1]+=ph) { for(x=0,pos[0]=tl[0];x<w;x++,pos[0]+=pw) { tmp=transform(pos); u=(tmp[0]-src_tl[0])/src_pw; v=(tmp[1]-src_tl[1])/src_ph; if(u<0 || v<0 || u>=src_w || v>=src_h || isnan(u) || isnan(v)) (*surface)[y][x]=context.get_color(tmp); else (*surface)[y][x]=source.linear_sample(u,v); } if((y&31)==0 && cb && !stagetwo.amount_complete(y,h)) return false; } else // NEAREST_NEIGHBOR for(y=0,pos[1]=tl[1];y<h;y++,pos[1]+=ph) { for(x=0,pos[0]=tl[0];x<w;x++,pos[0]+=pw) { tmp=transform(pos); u=(tmp[0]-src_tl[0])/src_pw; v=(tmp[1]-src_tl[1])/src_ph; if(u<0 || v<0 || u>=src_w || v>=src_h || isnan(u) || isnan(v)) (*surface)[y][x]=context.get_color(tmp); else (*surface)[y][x]=source[floor_to_int(v)][floor_to_int(u)]; } if((y&31)==0 && cb && !stagetwo.amount_complete(y,h)) return false; } // Mark our progress as finished if(cb && !cb->amount_complete(10000,10000)) return false; return true; }
/** * メッシュ情報を読み込む * * @param mesh メッシュ情報 */ void FbxFileLoader::load_mesh( FbxMesh* mesh ) { if ( ! mesh ) { return; } if ( ! get_model()->get_mesh() ) { get_model()->set_mesh( create_mesh() ); } VertexIndexMap vertex_index_map; VertexList vertex_list; Mesh::PositionList position_list; Mesh::VertexWeightList vertex_weight_list; // load_mesh_vertex() for ( int n = 0; n < mesh->GetControlPointsCount(); n++ ) { FbxVector4 v = mesh->GetControlPointAt( n ); position_list.push_back( Mesh::Position( static_cast< float >( v[ 0 ] ), static_cast< float >( v[ 1 ] ), static_cast< float >( v[ 2 ] ) ) ); } // load_mesh_vertex_weight() { int skin_count = mesh->GetDeformerCount( FbxDeformer::eSkin ); if ( skin_count > 0 ) { assert( skin_count == 1 ); vertex_weight_list.resize( position_list.size() ); FbxSkin* skin = FbxCast< FbxSkin >( mesh->GetDeformer( 0, FbxDeformer::eSkin ) ); load_mesh_vertex_weight( skin, vertex_weight_list ); } } FbxLayerElementSmoothing* smoothing = 0; // load_mesh_smoothing_info() { FbxLayer* layer = mesh->GetLayer( 0 ); smoothing = layer->GetSmoothing(); } if ( ! smoothing ) { COMMON_THROW_EXCEPTION_MESSAGE( "this FBX format is not supported. ( no smoothing info )" ); } // load_mesh_plygon() FbxLayerElementArrayTemplate< int >* material_indices; mesh->GetMaterialIndices( & material_indices ); for ( int n = 0; n < mesh->GetPolygonCount(); n++ ) { Mesh::VertexGroup* vertex_group = get_model()->get_mesh()->get_vertex_group_at( material_indices->GetAt( n ) ); bool is_smooth = smoothing->GetDirectArray().GetAt( n ) != 0; FbxVector4 polygon_normal( 0.f, 0.f, 0.f ); if ( ! is_smooth ) { // ポリゴンの法線を計算する Mesh::Position p1( position_list.at( mesh->GetPolygonVertex( n, 0 ) ) ); Mesh::Position p2( position_list.at( mesh->GetPolygonVertex( n, 1 ) ) ); Mesh::Position p3( position_list.at( mesh->GetPolygonVertex( n, 2 ) ) ); FbxVector4 a = FbxVector4( p1.x(), p1.y(), p1.z() ); FbxVector4 b = FbxVector4( p2.x(), p2.y(), p2.z() ); FbxVector4 c = FbxVector4( p3.x(), p3.y(), p3.z() ); FbxVector4 ab( b - a ); FbxVector4 bc( c - b ); polygon_normal = ab.CrossProduct( bc ); polygon_normal.Normalize(); } for ( int m = 0; m < mesh->GetPolygonSize( n ); m++ ) { int position_index = mesh->GetPolygonVertex( n, m ); Mesh::Vertex v; v.Position = Mesh::Position( position_list.at( position_index ) ); FbxVector2 uv_vector; bool unmapped; if ( mesh->GetPolygonVertexUV( n, m, "UVMap", uv_vector, unmapped) ) { v.TexCoord = Mesh::TexCoord( static_cast< float >( uv_vector[ 0 ] ), 1.f - static_cast< float >( uv_vector[ 1 ] ) ); } if ( is_smooth ) { FbxVector4 normal_vector; // 頂点の法線 if ( mesh->GetPolygonVertexNormal( n, m, normal_vector ) ) { v.Normal = Mesh::Normal( static_cast< float >( normal_vector[ 0 ] ), static_cast< float >( normal_vector[ 1 ] ), static_cast< float >( normal_vector[ 2 ] ) ); } } else { // ポリゴンの法線 v.Normal = Mesh::Normal( static_cast< float >( polygon_normal[ 0 ] ), static_cast< float >( polygon_normal[ 1 ] ), static_cast< float >( polygon_normal[ 2 ] ) ); } // 頂点の一覧に追加 { VertexIndexMap::iterator i = vertex_index_map.find( v ); if ( i != vertex_index_map.end() ) { vertex_group->add_index( i->second ); } else { Mesh::Index vertex_index = static_cast< Mesh::Index >( get_model()->get_mesh()->get_vertex_count() ); get_model()->get_mesh()->add_vertex( v ); if ( ! vertex_weight_list.empty() ) { get_model()->get_mesh()->add_vertex_weight( vertex_weight_list.at( position_index ) ); } vertex_group->add_index( vertex_index ); vertex_index_map[ v ] = vertex_index; } } } } }
int dist(point a,point b) { return ab(a.x-b.x)+ab(a.y-b.y); }
bool in_triangle(point a, point* triangle) { vec ab(triangle[0], triangle[1]), bc(triangle[1], triangle[2]), ac(triangle[0], triangle[2]); return ((ab.cross(vec(triangle[0], a)) * vec(triangle[0], a).cross(ac) > 0 and bc.cross(vec(triangle[1], a)) * vec(triangle[1], a).cross(vec(triangle[1], triangle[0])) > 0)) or a == triangle[0] or a == triangle[1] or a == triangle[2]; return true; }
void DebugAABB2D() { #pragma region TestShapes AABB2D ab(Vector2{ 10 , 10 }, Vector2{ 20 , 20 }); AABB2D bb(Vector2{ 15 , 15 }, Vector2{ 25 , 25 }); AABB2D cb(Vector2{ 25 , 25 }, Vector2{ 35 , 35 }); Circle ac{ Vector2{10 , 15 }, 5 }; Circle bc{ Vector2{0 , 0 }, 1 }; Circle cc{ Vector2{25 , 25 }, 5 }; Plane2D ap{ Vector2{15 ,15 } , Vector2{0 ,1 } }; Plane2D bp{ Vector2{15 ,15 } , Vector2{1 ,0 } }; Plane2D cp{ Vector2{0 ,0 } , Vector2{0 ,1 } }; Ray2D ar{ Vector2{0,0 }, normal(Vector2{0.5,0.5}), 50 }; Ray2D br{ Vector2{14.9f,1}, Vector2{0,1}, 50 }; Ray2D cr{ Vector2{1,13}, Vector2{1,0}, 50 }; ConvexHull2D chull; chull.size = 4; chull.verts[0] = Vector2{ 20,22 }; chull.verts[1] = Vector2{ 23,18 }; chull.verts[2] = Vector2{ 26,22 }; chull.verts[3] = Vector2{ 23,28 }; #pragma endregion //AABB2D VS AABB2D assert( iTest(ab, bb)); assert(!iTest(ab, cb)); assert( iTest(bb, cb)); //AABB2D VS CIRCLE assert( iTest(ab, ac)); assert(!iTest(ab, bc)); assert(!iTest(ab, cc)); assert( iTest(bb, ac)); assert(!iTest(bb, bc)); assert( iTest(bb, cc)); assert(!iTest(cb, ac)); assert(!iTest(cb, bc)); assert( iTest(cb, cc)); //AABB2D VS PLANE assert( iTest(ab, ap)); assert( iTest(ab, bp)); assert(!iTest(ab, cp)); assert( iTest(bb, ap)); assert( iTest(bb, bp)); assert(!iTest(bb, cp)); assert(!iTest(cb, ap)); assert(!iTest(cb, bp)); assert(!iTest(cb, cp)); //AABB2D VS RAY2D assert( iTest(ab, ar)); assert( iTest(ab, br)); assert( iTest(ab, cr)); assert( iTest(bb, ar)); assert(!iTest(bb, br)); assert(!iTest(bb, cr)); assert( iTest(cb, ar)); assert(!iTest(cb, br)); assert(!iTest(cb, cr)); //AABB VS CONVEX2D assert(iTest_data(chull, ab).penDepth <= 0); assert(iTest_data(chull, bb).penDepth > 0); assert(iTest_data(chull, cb).penDepth <= 0); }
osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model, obj::Model::ElementList& elementList, ObjOptionsStruct& localOptions) const { unsigned int numVertexIndices = 0; unsigned int numNormalIndices = 0; unsigned int numTexCoordIndices = 0; unsigned int numPointElements = 0; unsigned int numPolylineElements = 0; unsigned int numPolygonElements = 0; obj::Model::ElementList::iterator itr; if (localOptions.generateFacetNormals == true) { for(itr=elementList.begin(); itr!=elementList.end(); ++itr) { obj::Element& element = *(*itr); if (element.dataType==obj::Element::POINTS || element.dataType==obj::Element::POLYLINE) continue; if (element.normalIndices.size() == 0) { // fill in the normals int a = element.vertexIndices[0]; int b = element.vertexIndices[1]; int c = element.vertexIndices[2]; osg::Vec3f ab(model.vertices[b]); osg::Vec3f ac(model.vertices[c]); ab -= model.vertices[a]; ac -= model.vertices[a]; osg::Vec3f Norm( ab ^ ac ); Norm.normalize(); int normal_idx = model.normals.size(); model.normals.push_back(Norm); for (unsigned i=0 ; i < element.vertexIndices.size() ; i++) element.normalIndices.push_back(normal_idx); } } } for(itr=elementList.begin(); itr!=elementList.end(); ++itr) { obj::Element& element = *(*itr); numVertexIndices += element.vertexIndices.size(); numNormalIndices += element.normalIndices.size(); numTexCoordIndices += element.texCoordIndices.size(); numPointElements += (element.dataType==obj::Element::POINTS) ? 1 : 0; numPolylineElements += (element.dataType==obj::Element::POLYLINE) ? 1 : 0; numPolygonElements += (element.dataType==obj::Element::POLYGON) ? 1 : 0; } if (numVertexIndices==0) return 0; if (numNormalIndices!=0 && numNormalIndices!=numVertexIndices) { OSG_NOTICE<<"Incorrect number of normals, ignore them"<<std::endl; numNormalIndices = 0; } if (numTexCoordIndices!=0 && numTexCoordIndices!=numVertexIndices) { OSG_NOTICE<<"Incorrect number of normals, ignore them"<<std::endl; numTexCoordIndices = 0; } osg::Vec3Array* vertices = numVertexIndices ? new osg::Vec3Array : 0; osg::Vec3Array* normals = numNormalIndices ? new osg::Vec3Array : 0; osg::Vec2Array* texcoords = numTexCoordIndices ? new osg::Vec2Array : 0; osg::Vec4Array* colors = (!model.colors.empty()) ? new osg::Vec4Array : 0; if (vertices) vertices->reserve(numVertexIndices); if (normals) normals->reserve(numNormalIndices); if (texcoords) texcoords->reserve(numTexCoordIndices); if (colors) colors->reserve(numVertexIndices); osg::Geometry* geometry = new osg::Geometry; if (vertices) geometry->setVertexArray(vertices); if (normals) { geometry->setNormalArray(normals, osg::Array::BIND_PER_VERTEX); } if (texcoords) { geometry->setTexCoordArray(0,texcoords); } if (colors) { geometry->setColorArray(colors, osg::Array::BIND_PER_VERTEX); } if (numPointElements>0) { unsigned int startPos = vertices->size(); unsigned int numPoints = 0; for(itr=elementList.begin(); itr!=elementList.end(); ++itr) { obj::Element& element = *(*itr); if (element.dataType==obj::Element::POINTS) { for(obj::Element::IndexList::iterator index_itr = element.vertexIndices.begin(); index_itr != element.vertexIndices.end(); ++index_itr) { // if use color extension ( not standard but used by meshlab) if (colors) { colors->push_back(model.colors[*index_itr]); } vertices->push_back(transformVertex(model.vertices[*index_itr],localOptions.rotate)); ++numPoints; } if (numNormalIndices) { for(obj::Element::IndexList::iterator index_itr = element.normalIndices.begin(); index_itr != element.normalIndices.end(); ++index_itr) { normals->push_back(transformNormal(model.normals[*index_itr],localOptions.rotate)); } } if (numTexCoordIndices) { for(obj::Element::IndexList::iterator index_itr = element.texCoordIndices.begin(); index_itr != element.texCoordIndices.end(); ++index_itr) { texcoords->push_back(model.texcoords[*index_itr]); } } } } osg::DrawArrays* drawArrays = new osg::DrawArrays(GL_POINTS,startPos,numPoints); geometry->addPrimitiveSet(drawArrays); } if (numPolylineElements>0) { unsigned int startPos = vertices->size(); osg::DrawArrayLengths* drawArrayLengths = new osg::DrawArrayLengths(GL_LINES,startPos); for(itr=elementList.begin(); itr!=elementList.end(); ++itr) { obj::Element& element = *(*itr); if (element.dataType==obj::Element::POLYLINE) { drawArrayLengths->push_back(element.vertexIndices.size()); for(obj::Element::IndexList::iterator index_itr = element.vertexIndices.begin(); index_itr != element.vertexIndices.end(); ++index_itr) { // if use color extension ( not standard but used by meshlab) if (colors) { colors->push_back(model.colors[*index_itr]); } vertices->push_back(transformVertex(model.vertices[*index_itr],localOptions.rotate)); } if (numNormalIndices) { for(obj::Element::IndexList::iterator index_itr = element.normalIndices.begin(); index_itr != element.normalIndices.end(); ++index_itr) { normals->push_back(transformNormal(model.normals[*index_itr],localOptions.rotate)); } } if (numTexCoordIndices) { for(obj::Element::IndexList::iterator index_itr = element.texCoordIndices.begin(); index_itr != element.texCoordIndices.end(); ++index_itr) { texcoords->push_back(model.texcoords[*index_itr]); } } } } geometry->addPrimitiveSet(drawArrayLengths); } // #define USE_DRAWARRAYLENGTHS bool hasReversedFaces = false ; if (numPolygonElements>0) { unsigned int startPos = vertices->size(); #ifdef USE_DRAWARRAYLENGTHS osg::DrawArrayLengths* drawArrayLengths = new osg::DrawArrayLengths(GL_POLYGON,startPos); geometry->addPrimitiveSet(drawArrayLengths); #endif for(itr=elementList.begin(); itr!=elementList.end(); ++itr) { obj::Element& element = *(*itr); if (element.dataType==obj::Element::POLYGON) { #ifdef USE_DRAWARRAYLENGTHS drawArrayLengths->push_back(element.vertexIndices.size()); #else if (element.vertexIndices.size()>4) { osg::DrawArrays* drawArrays = new osg::DrawArrays(GL_POLYGON,startPos,element.vertexIndices.size()); startPos += element.vertexIndices.size(); geometry->addPrimitiveSet(drawArrays); } else { osg::DrawArrays* drawArrays = new osg::DrawArrays(GL_TRIANGLE_FAN,startPos,element.vertexIndices.size()); startPos += element.vertexIndices.size(); geometry->addPrimitiveSet(drawArrays); } #endif if (model.needReverse(element) && !localOptions.noReverseFaces) { hasReversedFaces = true; // need to reverse so add to OSG arrays in same order as in OBJ, as OSG assume anticlockwise ordering. for(obj::Element::IndexList::reverse_iterator index_itr = element.vertexIndices.rbegin(); index_itr != element.vertexIndices.rend(); ++index_itr) { // if use color extension ( not standard but used by meshlab) if (colors) { colors->push_back(model.colors[*index_itr]); } vertices->push_back(transformVertex(model.vertices[*index_itr],localOptions.rotate)); } if (numNormalIndices) { for(obj::Element::IndexList::reverse_iterator index_itr = element.normalIndices.rbegin(); index_itr != element.normalIndices.rend(); ++index_itr) { normals->push_back(transformNormal(model.normals[*index_itr],localOptions.rotate)); } } if (numTexCoordIndices) { for(obj::Element::IndexList::reverse_iterator index_itr = element.texCoordIndices.rbegin(); index_itr != element.texCoordIndices.rend(); ++index_itr) { texcoords->push_back(model.texcoords[*index_itr]); } } } else { // no need to reverse so add to OSG arrays in same order as in OBJ. for(obj::Element::IndexList::iterator index_itr = element.vertexIndices.begin(); index_itr != element.vertexIndices.end(); ++index_itr) { // if use color extension ( not standard but used by meshlab) if (colors) { colors->push_back(model.colors[*index_itr]); } vertices->push_back(transformVertex(model.vertices[*index_itr],localOptions.rotate)); } if (numNormalIndices) { for(obj::Element::IndexList::iterator index_itr = element.normalIndices.begin(); index_itr != element.normalIndices.end(); ++index_itr) { normals->push_back(transformNormal(model.normals[*index_itr],localOptions.rotate)); } } if (numTexCoordIndices) { for(obj::Element::IndexList::iterator index_itr = element.texCoordIndices.begin(); index_itr != element.texCoordIndices.end(); ++index_itr) { texcoords->push_back(model.texcoords[*index_itr]); } } } } } } if(hasReversedFaces) { OSG_WARN << "Warning: [ReaderWriterOBJ::convertElementListToGeometry] Some faces from geometry '" << geometry->getName() << "' were reversed by the plugin" << std::endl; } return geometry; }