static void set_margin(t_atoms *atoms, rvec *x, real *r) { int i,d,start; box_margin=0; start=0; for(i=0; i < atoms->nr; i++) { if ( (i+1 == atoms->nr) || (atoms->atom[i+1].resnr != atoms->atom[i].resnr) ) { d=max_dist(x,r,start,i+1); if (debug && d>box_margin) fprintf(debug,"getting margin from %s: %g\n", *(atoms->resname[atoms->atom[i].resnr]),box_margin); box_margin=max(box_margin,d); start=i+1; } } fprintf(stderr,"box_margin = %g\n",box_margin); }
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; }
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; }
void OpenSGNavGrab::initScene() { vprDEBUG_OutputGuard(vprDBG_ALL, vprDBG_CRITICAL_LVL, "OpenSGNavGrab::initScene() called.\n", "OpenSGNavGrab::initScene() exiting.\n"); // Set up the node highlighting state. initHighlight(); mModelRoot = OSG::Node::create(); mModelGroup = OSG::Group::create(); #if OSG_MAJOR_VERSION < 2 CPEdit(mModelRoot, OSG::Node::CoreFieldMask); #endif mModelRoot->setCore(mModelGroup); // Load the model to use. if ( mFilesToLoad.empty() ) { vprDEBUG(vprDBG_ALL, vprDBG_CRITICAL_LVL) << "[OpenSGNavGrab::initScene()] No model specified; creating box." << std::endl << vprDEBUG_FLUSH; // Box geometry: 2.5x2.5x2.5 (units are in feet) // Center point: (0,0,0) OSG::NodeRefPtr geom_node(OSG::makeBox(2.5f, 2.5f, 2.5f, 1, 1, 1)); // Move it so that it would butt up against a wall five feet in front // of the user and another wall five feet to the left of the user. // If the application units were meters, this placement would be very // different. OSG::Matrix init_geom_pos; init_geom_pos.setTransform(OSG::Vec3f(-3.75f, 1.25f, -3.75f)); mObjects.push_back(makeGrabbable(geom_node, init_geom_pos)); } else { OSG::Vec3f distance_vec; OSG::Pnt3f::RealReturnType max_dist(0.0f); std::vector<OSG::NodeRefPtr> nodes; // Load all the models that the user told us to load. typedef std::vector<std::string>::iterator iter_type; for ( iter_type i = mFilesToLoad.begin(); i != mFilesToLoad.end(); ++i ) { vprDEBUG(vprDBG_ALL, vprDBG_CRITICAL_LVL) << "[OpenSGNavGrab::initScene()] Loading '" << *i << "' ..." << std::endl << vprDEBUG_FLUSH; const OSG::Char8* file = (*i).c_str(); OSG::NodeRefPtr geom_node( #if OSG_MAJOR_VERSION < 2 OSG::SceneFileHandler::the().read(file) #else OSG::SceneFileHandler::the()->read(file) #endif ); nodes.push_back(geom_node); // Needed to get the volume set up after creating the geometry. geom_node->updateVolume(); OSG::DynamicVolume volume = geom_node->getVolume(); OSG::Pnt3f min, max; volume.getBounds(min, max); // Calculate the distance between min and max. The largest distance // will be used for spacing out the objects. OSG::Pnt3f::RealReturnType dist(max.dist(min)); // Keep track of the maximum-sized bounding volume. if ( dist > max_dist ) { max_dist = dist; distance_vec = max - min; } } std::cout << "distance_vec: " << distance_vec << std::endl; // If we have loaded any models, we will position them along the X-axis. // The extents of the line of models is based on the bounding volume of // the largest model and the number of models. The line of models is // centered on the origin. Hence, half the models will be have a // negative X translation value, and half will have a positive X // translation value. if ( ! nodes.empty() ) { const std::vector<OSG::NodeRefPtr>::size_type num_objs(nodes.size()); const OSG::Real32 interval_dist(distance_vec[0]); // Set the left extreme of the line of models. The full extent of // the model range is interval_dist * num_objs. To center things // on the origin, we divide that value by 2. Since x_offset will // be used for the new center point of the model (see below), we // shift the starting point (interval_dist / 2) units so that some // model will end up centered on the origin. OSG::Real32 x_offset = -(interval_dist * OSG::Real32(num_objs) - interval_dist) / 2.0f; typedef std::vector<OSG::NodeRefPtr>::iterator iter_type; for ( iter_type i = nodes.begin(); i != nodes.end(); ++i, x_offset += interval_dist ) { // Get the center point of the current node and change its X // component to be the current x_offset value. const OSG::DynamicVolume& volume = (*i)->getVolume(); OSG::Pnt3f center; volume.getCenter(center); center[0] = x_offset; // The transformation matrix xform_mat will be the "home" position // for the model. OSG::Matrix xform_mat; xform_mat.setTranslate(center); mObjects.push_back(makeGrabbable(*i, xform_mat)); } } } // --- Light setup --- // // - Add directional light for scene // - Create a beacon for it and connect to that beacon mLightNode = OSG::Node::create(); mLightBeacon = OSG::Node::create(); OSG::DirectionalLightPtr light_core = OSG::DirectionalLight::create(); OSG::TransformPtr light_beacon_core = OSG::Transform::create(); // Set up light beacon OSG::Matrix light_pos; light_pos.setTransform(OSG::Vec3f(2.0f, 5.0f, 4.0f)); #if OSG_MAJOR_VERSION < 2 CPEdit(light_beacon_core, OSG::Transform::MatrixFieldMask); CPEdit(mLightBeacon, OSG::Node::CoreFieldMask); CPEdit(mLightNode, OSG::Node::CoreFieldMask | OSG::Node::ChildrenFieldMask); CPEditAll(light_core); #endif light_beacon_core->setMatrix(light_pos); mLightBeacon->setCore(light_beacon_core); // Set up light node mLightNode->setCore(light_core); mLightNode->addChild(mLightBeacon); light_core->setAmbient(0.9, 0.8, 0.8, 1); light_core->setDiffuse(0.6, 0.6, 0.6, 1); light_core->setSpecular(1, 1, 1, 1); light_core->setDirection(0, 0, 1); light_core->setBeacon(mLightNode); // --- Set up scene -- // // add the loaded scene to the light node, so that it is lit by the light mLightNode->addChild(mModelRoot); // create the root part of the scene mSceneRoot = OSG::Node::create(); mSceneTransform = OSG::Transform::create(); #if OSG_MAJOR_VERSION < 2 CPEdit(mSceneRoot, OSG::Node::CoreFieldMask | OSG::Node::ChildrenFieldMask); #endif // Set up the root node mSceneRoot->setCore(mSceneTransform); mSceneRoot->addChild(mLightNode); }