void PatchInspector::emitTesselation()
{
	UndoableCommand setFixedTessCmd("patchSetFixedTesselation");

	wxSpinCtrl* fixedSubdivX = findNamedObject<wxSpinCtrl>(this, "PatchInspectorSubdivisionsX");
	wxSpinCtrl* fixedSubdivY = findNamedObject<wxSpinCtrl>(this, "PatchInspectorSubdivisionsY");

	Subdivisions tess(
		fixedSubdivX->GetValue(),
		fixedSubdivY->GetValue()
	);

	bool fixed = findNamedObject<wxCheckBox>(this, "PatchInspectorFixedSubdivisions")->GetValue();

	// Save the setting into the selected patch(es)
	GlobalSelectionSystem().foreachPatch([&] (Patch& patch)
	{
		patch.setFixedSubdivisions(fixed, tess);
	});

	fixedSubdivX->Enable(fixed);
	fixedSubdivY->Enable(fixed);
	findNamedObject<wxStaticText>(this, "PatchInspectorSubdivisionsXLabel")->Enable(fixed);
	findNamedObject<wxStaticText>(this, "PatchInspectorSubdivisionsYLabel")->Enable(fixed);

	GlobalMainFrame().updateAllWindows();
}
void
WRATHTessGLU::
end_polygon(void)
{
  WRATHassert(m_private_data!=NULL);
  wrath_GLUtesselator *tess(static_cast<wrath_GLUtesselator*>(m_private_data));
  wrath_gluTessEndPolygon(tess);
}
void
WRATHTessGLU::
begin_contour(void)
{
  WRATHassert(m_private_data!=NULL);
  wrath_GLUtesselator *tess(static_cast<wrath_GLUtesselator*>(m_private_data));
  
  WRATHassert(!m_polygons.empty());
  wrath_gluTessBeginContour(tess);
}
void
WRATHTessGLU::
begin_polygon(void *polygon_data)
{
  WRATHassert(m_private_data!=NULL);
  wrath_GLUtesselator *tess(static_cast<wrath_GLUtesselator*>(m_private_data));

  /*
    create and save a polygon object.
   */
  m_polygons.push_back( WRATHTessGLUPrivate::polygon_element(this, polygon_data));

  wrath_gluTessBeginPolygon(tess, &m_polygons.back());
}
void
WRATHTessGLU::
add_vertex(vec2 position, void *vertex_data)
{
  WRATHassert(m_private_data!=NULL);

  double values[3];
  wrath_GLUtesselator *tess(static_cast<wrath_GLUtesselator*>(m_private_data));

  values[0]=position.x();
  values[1]=position.y();
  values[2]=0.0;

  wrath_gluTessVertex(tess, values, vertex_data);
}
WRATHTessGLU::
WRATHTessGLU(enum tessellation_type ptype)
{
  m_private_data=wrath_gluNewTess();

  /*
    register call backs:
   */
  wrath_GLUtesselator *tess(static_cast<wrath_GLUtesselator*>(m_private_data));

  wrath_gluTessCallbackBegin(tess, &begin_callBack); //WRATH_GLU_TESS_BEGIN_DATA
  wrath_gluTessCallbackVertex(tess, &vertex_callBack); //WRATH_GLU_TESS_VERTEX_DATA
  wrath_gluTessCallbackEnd(tess, &end_callBack); //WRATH_GLU_TESS_END_DATA
  wrath_gluTessCallbackError(tess, &error_callBack); //WRATH_GLU_TESS_ERROR_DATA
  wrath_gluTessCallbackCombine(tess, &combine_callBack); //WRATH_GLU_TESS_COMBINE_DATA
  wrath_gluTessCallbackFillRule(tess, &winding_callBack); //WRATH_GLU_TESS_COMBINE_DATA

 
  switch(ptype)
    {
    default:
      WRATHwarning("\nBad tessellation_type: " << static_cast<unsigned int>(ptype)
                   << " reevaluated as tessellate_triangles_only\n");

    case tessellate_triangles_only:
      wrath_gluTessCallbackEdgeFlag(tess, &edgeflag_callBack); //WRATH_GLU_TESS_EDGE_FLAG_DATA
      wrath_gluTessPropertyBoundaryOnly(tess, WRATH_GLU_FALSE);
      break;

    case tessellate_any_triangles_type:
      {
        wrath_glu_tess_function_edge_data no_edge_function(NULL);
        wrath_gluTessCallbackEdgeFlag(tess, no_edge_function);
        wrath_gluTessPropertyBoundaryOnly(tess, WRATH_GLU_FALSE);
      }
      break;

    case tessellate_boundary_only:
      wrath_gluTessCallbackEdgeFlag(tess, &edgeflag_callBack); //WRATH_GLU_TESS_EDGE_FLAG_DATA
      wrath_gluTessPropertyBoundaryOnly(tess, WRATH_GLU_TRUE);
      break;
    }
}
int window_maker(const sf::Vector2f& windims, const std::string& program_name)
{
	const sf::Color black{sf::Color(0, 0, 0)};
	const sf::Color light_red{sf::Color(191, 63, 63)};
	
	const sf::Vector2f left_start_rel{0.2f, 0.9f};
	
	square tess(windims, left_start_rel, light_red);
	
	sf::RenderWindow window(sf::VideoMode(windims.x, windims.y), program_name, sf::Style::Default);
		
	while (window.isOpen())
	{
		sf::Event event;
		
		window.clear(black);
		
		tess.show_square(window);
		
		window.display();
		
		if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
		{
			window.close();
			return 0;
		}
		
		while (window.pollEvent(event))
		{			
			if (event.type == sf::Event::Closed)
			{
				window.close();
				return 0;
			}		
		}		
	}
	
	return 1;	
}
Example #8
0
void LightSampler::collect_emitting_triangles(
    const Assembly&         assembly,
    const AssemblyInstance& assembly_instance)
{
    // Loop over the object instances of the assembly.
    const size_t object_instance_count = assembly.object_instances().size();
    for (size_t object_instance_index = 0; object_instance_index < object_instance_count; ++object_instance_index)
    {
        // Retrieve the object instance.
        const ObjectInstance* object_instance = assembly.object_instances().get_by_index(object_instance_index);

        // Retrieve the materials of the object instance.
        const MaterialArray& front_materials = object_instance->get_front_materials();
        const MaterialArray& back_materials = object_instance->get_back_materials();

        // Skip object instances without light-emitting materials.
        if (!has_emitting_materials(front_materials) && !has_emitting_materials(back_materials))
            continue;

        // Compute the object space to world space transformation.
        // todo: add support for moving light-emitters.
        const Transformd& object_instance_transform = object_instance->get_transform();
        const Transformd assembly_instance_transform =
            assembly_instance.transform_sequence().empty()
                ? Transformd::identity()
                : assembly_instance.transform_sequence().earliest_transform();
        const Transformd global_transform = assembly_instance_transform * object_instance_transform;

        // Retrieve the object.
        Object& object = object_instance->get_object();

        // Retrieve the region kit of the object.
        Access<RegionKit> region_kit(&object.get_region_kit());

        // Loop over the regions of the object.
        const size_t region_count = region_kit->size();
        for (size_t region_index = 0; region_index < region_count; ++region_index)
        {
            // Retrieve the region.
            const IRegion* region = (*region_kit)[region_index];

            // Retrieve the tessellation of the region.
            Access<StaticTriangleTess> tess(&region->get_static_triangle_tess());

            // Loop over the triangles of the region.
            const size_t triangle_count = tess->m_primitives.size();
            for (size_t triangle_index = 0; triangle_index < triangle_count; ++triangle_index)
            {
                // Fetch the triangle.
                const Triangle& triangle = tess->m_primitives[triangle_index];

                // Skip triangles without a material.
                if (triangle.m_pa == Triangle::None)
                    continue;

                // Fetch the materials assigned to this triangle.
                const size_t pa_index = static_cast<size_t>(triangle.m_pa);
                const Material* front_material =
                    pa_index < front_materials.size() ? front_materials[pa_index] : 0;
                const Material* back_material =
                    pa_index < back_materials.size() ? back_materials[pa_index] : 0;

                // Skip triangles that don't emit light.
                if ((front_material == 0 || front_material->get_uncached_edf() == 0) &&
                    (back_material == 0 || back_material->get_uncached_edf() == 0))
                    continue;

                // Retrieve object instance space vertices of the triangle.
                const GVector3& v0_os = tess->m_vertices[triangle.m_v0];
                const GVector3& v1_os = tess->m_vertices[triangle.m_v1];
                const GVector3& v2_os = tess->m_vertices[triangle.m_v2];

                // Transform triangle vertices to assembly space.
                const GVector3 v0_as = object_instance_transform.point_to_parent(v0_os);
                const GVector3 v1_as = object_instance_transform.point_to_parent(v1_os);
                const GVector3 v2_as = object_instance_transform.point_to_parent(v2_os);

                // Compute the support plane of the hit triangle in assembly space.
                const GTriangleType triangle_geometry(v0_as, v1_as, v2_as);
                TriangleSupportPlaneType triangle_support_plane;
                triangle_support_plane.initialize(TriangleType(triangle_geometry));

                // Transform triangle vertices to world space.
                const Vector3d v0(assembly_instance_transform.point_to_parent(v0_as));
                const Vector3d v1(assembly_instance_transform.point_to_parent(v1_as));
                const Vector3d v2(assembly_instance_transform.point_to_parent(v2_as));

                // Compute the geometric normal to the triangle and the area of the triangle.
                Vector3d geometric_normal = cross(v1 - v0, v2 - v0);
                const double geometric_normal_norm = norm(geometric_normal);
                if (geometric_normal_norm == 0.0)
                    continue;
                const double rcp_geometric_normal_norm = 1.0 / geometric_normal_norm;
                const double rcp_area = 2.0 * rcp_geometric_normal_norm;
                const double area = 0.5 * geometric_normal_norm;
                geometric_normal *= rcp_geometric_normal_norm;
                assert(is_normalized(geometric_normal));

                // Retrieve object instance space vertex normals.
                const GVector3& n0_os = tess->m_vertex_normals[triangle.m_n0];
                const GVector3& n1_os = tess->m_vertex_normals[triangle.m_n1];
                const GVector3& n2_os = tess->m_vertex_normals[triangle.m_n2];

                // Transform vertex normals to world space.
                const Vector3d n0(normalize(global_transform.normal_to_parent(n0_os)));
                const Vector3d n1(normalize(global_transform.normal_to_parent(n1_os)));
                const Vector3d n2(normalize(global_transform.normal_to_parent(n2_os)));

                for (size_t side = 0; side < 2; ++side)
                {
                    const Material* material = side == 0 ? front_material : back_material;
                    const Vector3d side_geometric_normal = side == 0 ? geometric_normal : -geometric_normal;
                    const Vector3d side_n0 = side == 0 ? n0 : -n0;
                    const Vector3d side_n1 = side == 0 ? n1 : -n1;
                    const Vector3d side_n2 = side == 0 ? n2 : -n2;

                    // Skip sides without a material.
                    if (material == 0)
                        continue;

                    const EDF* edf = material->get_uncached_edf();

                    // Skip sides without a light-emitting material.
                    if (edf == 0)
                        continue;

                    // Create a light-emitting triangle.
                    EmittingTriangle emitting_triangle;
                    emitting_triangle.m_assembly_instance = &assembly_instance;
                    emitting_triangle.m_object_instance_index = object_instance_index;
                    emitting_triangle.m_region_index = region_index;
                    emitting_triangle.m_triangle_index = triangle_index;
                    emitting_triangle.m_v0 = v0;
                    emitting_triangle.m_v1 = v1;
                    emitting_triangle.m_v2 = v2;
                    emitting_triangle.m_n0 = side_n0;
                    emitting_triangle.m_n1 = side_n1;
                    emitting_triangle.m_n2 = side_n2;
                    emitting_triangle.m_geometric_normal = side_geometric_normal;
                    emitting_triangle.m_triangle_support_plane = triangle_support_plane;
                    emitting_triangle.m_rcp_area = rcp_area;
                    emitting_triangle.m_edf = edf;

                    // Store the light-emitting triangle.
                    const size_t emitting_triangle_index = m_emitting_triangles.size();
                    m_emitting_triangles.push_back(emitting_triangle);

                    // Insert the light-emitting triangle into the CDFs.
                    m_emitter_cdf.insert(emitting_triangle_index + m_lights.size(), area);
                    m_emitting_triangle_cdf.insert(emitting_triangle_index, area);

                    // Keep track of the total area of the light-emitting triangles.
                    m_total_emissive_area += area;
                }
            }
        }
    }
}
Example #9
0
/*!
  Generates the convexified data. FIXME: doc
*/
void
SoConvexDataCache::generate(const SoCoordinateElement * const coords,
                            const SbMatrix & matrix,
                            const int32_t *vind,
                            const int numv,
                            const int32_t *mind, const int32_t *nind,
                            const int32_t *tind,
                            const Binding matbind, const Binding normbind,
                            const Binding texbind)
{
#if COIN_DEBUG && 0
  SoDebugError::postInfo("SoConvexDataCache::generate",
                         "generating convex data");
#endif

  SbBool identity = matrix == SbMatrix::identity();

  // remove old data
  PRIVATE(this)->coordIndices.truncate(0);
  PRIVATE(this)->materialIndices.truncate(0);
  PRIVATE(this)->normalIndices.truncate(0);
  PRIVATE(this)->texIndices.truncate(0);

  int matnr = 0;
  int texnr = 0;
  int normnr = 0;

  // initialize the struct with data needed during tessellation
  tTessData tessdata;
  tessdata.matbind = matbind;
  tessdata.normbind = normbind;
  tessdata.texbind = texbind;
  tessdata.numvertexind = 0;
  tessdata.nummatind = 0;
  tessdata.numnormind = 0;
  tessdata.numtexind = 0;
  // FIXME: stupid to have a separate struct for each coordIndex
  // should only allocate enough to hold the largest polygon
  tessdata.vertexInfo = new tVertexInfo[numv];
  tessdata.vertexIndex = NULL;
  tessdata.matIndex = NULL;
  tessdata.normIndex = NULL;
  tessdata.texIndex = NULL;
  tessdata.firstvertex = TRUE;

  // create tessellator
  SbGLUTessellator glutess(do_triangle, &tessdata);
  SbTesselator tess(do_triangle, &tessdata);
  const SbBool gt = SbGLUTessellator::preferred();

  // if PER_FACE binding, the binding must change to PER_FACE_INDEXED
  // if convexify data is used.
  tessdata.vertexIndex = &PRIVATE(this)->coordIndices;
  if (matbind != NONE)
    tessdata.matIndex = &PRIVATE(this)->materialIndices;
  if (normbind != NONE)
    tessdata.normIndex = &PRIVATE(this)->normalIndices;
  if (texbind != NONE)
    tessdata.texIndex = &PRIVATE(this)->texIndices;

  if (gt) { glutess.beginPolygon(); }
  else { tess.beginPolygon(); }
  for (int i = 0; i < numv; i++) {
    if (vind[i] < 0) {
      if (gt) { glutess.endPolygon(); }
      else { tess.endPolygon(); }
      if (matbind == PER_VERTEX_INDEXED || 
          matbind == PER_FACE ||
          matbind == PER_FACE_INDEXED) matnr++;
      if (normbind == PER_VERTEX_INDEXED ||
          normbind == PER_FACE ||
          normbind == PER_FACE_INDEXED) normnr++;
      if (texbind == PER_VERTEX_INDEXED) texnr++;
      if (i < numv - 1) { // if not last polygon
        if (gt) { glutess.beginPolygon(); }
        else { tess.beginPolygon(); }
      }
    }
    else {
      tessdata.vertexInfo[i].vertexnr = vind[i];
      if (mind)
        tessdata.vertexInfo[i].matnr = mind[matnr];
      else tessdata.vertexInfo[i].matnr = matnr;
      if (matbind >= PER_VERTEX) {
        matnr++;
      }
      if (nind)
        tessdata.vertexInfo[i].normnr = nind[normnr];
      else tessdata.vertexInfo[i].normnr = normnr;
      if (normbind >= PER_VERTEX)
        normnr++;
      if (tind)
        tessdata.vertexInfo[i].texnr = tind[texnr++];
      else
        tessdata.vertexInfo[i].texnr = texnr++;

      SbVec3f v = coords->get3(vind[i]);
      if (!identity) matrix.multVecMatrix(v,v);
      if (gt) { glutess.addVertex(v, static_cast<void *>(&tessdata.vertexInfo[i])); }
      else { tess.addVertex(v, static_cast<void *>(&tessdata.vertexInfo[i])); }
    }
  }
  
  // if last coordIndex != -1, terminate polygon
  if (numv > 0 && vind[numv-1] != -1) {
    if (gt) { glutess.endPolygon(); }
    else { tess.endPolygon(); }
  }

  delete [] tessdata.vertexInfo;

  PRIVATE(this)->coordIndices.fit();
  if (tessdata.matIndex) PRIVATE(this)->materialIndices.fit();
  if (tessdata.normIndex) PRIVATE(this)->normalIndices.fit();
  if (tessdata.texIndex) PRIVATE(this)->texIndices.fit();
}
    void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override {
        bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage();

        SkMatrix invert;
        if (this->usesLocalCoords() && !this->viewMatrix().invert(&invert)) {
            SkDebugf("Could not invert viewmatrix\n");
            return;
        }

        // Setup GrGeometryProcessor
        SkAutoTUnref<const GrGeometryProcessor> gp(
                                                create_fill_gp(canTweakAlphaForCoverage, invert,
                                                               this->usesLocalCoords(),
                                                               this->coverageIgnored()));

        batchTarget->initDraw(gp, pipeline);

        size_t vertexStride = gp->getVertexStride();

        SkASSERT(canTweakAlphaForCoverage ?
                 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr) :
                 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr));

        int instanceCount = fGeoData.count();

        int vertexCount = 0;
        int indexCount = 0;
        int maxVertices = DEFAULT_BUFFER_SIZE;
        int maxIndices = DEFAULT_BUFFER_SIZE;
        uint8_t* vertices = (uint8_t*) malloc(maxVertices * vertexStride);
        uint16_t* indices = (uint16_t*) malloc(maxIndices * sizeof(uint16_t));
        for (int i = 0; i < instanceCount; i++) {
            Geometry& args = fGeoData[i];
            GrAAConvexTessellator tess(args.fStrokeWidth, args.fJoin, args.fMiterLimit);

            if (!tess.tessellate(args.fViewMatrix, args.fPath)) {
                continue;
            }

            int currentIndices = tess.numIndices();
            SkASSERT(currentIndices <= UINT16_MAX);
            if (indexCount + currentIndices > UINT16_MAX) {
                // if we added the current instance, we would overflow the indices we can store in a 
                // uint16_t. Draw what we've got so far and reset.
                draw(batchTarget, pipeline, vertexCount, vertexStride, vertices, indexCount, 
                        indices);
                vertexCount = 0;
                indexCount = 0;
            }
            int currentVertices = tess.numPts();
            if (vertexCount + currentVertices > maxVertices) {
                maxVertices = SkTMax(vertexCount + currentVertices, maxVertices * 2);
                vertices = (uint8_t*) realloc(vertices, maxVertices * vertexStride);
            }
            if (indexCount + currentIndices > maxIndices) {
                maxIndices = SkTMax(indexCount + currentIndices, maxIndices * 2);
                indices = (uint16_t*) realloc(indices, maxIndices * sizeof(uint16_t));
            }

            extract_verts(tess, vertices + vertexStride * vertexCount, vertexStride, args.fColor, 
                    vertexCount, indices + indexCount, canTweakAlphaForCoverage);
            vertexCount += currentVertices;
            indexCount += currentIndices;
        }
        draw(batchTarget, pipeline, vertexCount, vertexStride, vertices, indexCount, indices);
        free(vertices);
        free(indices);
    }
Example #11
0
tileList tiledCanvas::getTesselation(int w, int h, int x1, int y1, bool flipY)
{
    tileList tessPoints;
    // Produce an integer version of mOffset that is centered in the w x h screen
    agg::trans_affine tess(mWidth, floor(mOffset.shy + 0.5), floor(mOffset.shx + 0.5),
        flipY ? -mHeight : mHeight, x1, y1);
    agg::rect_i screen(0, 0, w - 1, h - 1);
    if (mFrieze == CFDG::frieze_x)
        tess.sy = 0.0;
    if (mFrieze == CFDG::frieze_y)
        tess.sx = 0.0;
    
    tessPoints.push_back(agg::point_i(x1, y1));   // always include the center tile
    
    if (mFrieze) {
        for (int offset = 1; ; ++offset) {
            bool hit = false;
            for (int side: {-1, 1}) {
                double dx = offset * side;
                double dy = dx;
                tess.transform(&dx, &dy);
                int px = static_cast<int>(floor(dx + 0.5));
                int py = static_cast<int>(floor(dy + 0.5));
                
                // If the tile is visible then record it
                agg::rect_i tile(px, py, px + mWidth - 1, py + mHeight - 1);
                if (tile.overlaps(screen)) {
                    hit = true;
                    tessPoints.emplace_back(px, py);
                }
            }
            if (!hit) return tessPoints;
        }
    }
    
    // examine rings of tile units around the center unit until you encounter a
    // ring that doesn't have any tile units that intersect the screen. Then stop.
    for (int ring = 1; ; ring++) {
        bool hit = false;
        for (int pos = -ring; pos < ring; pos++) {
            std::array<std::pair<int, int>, 4> points = {{
                {pos, -ring},
                {ring, pos},
                {-pos, ring},
                {-ring, -pos}
            }};
            for (auto&& point: points) {
                // Find where this tile is on the screen
                double dx = point.first;
                double dy = point.second;
                tess.transform(&dx, &dy);
                int px = static_cast<int>(floor(dx + 0.5));
                int py = static_cast<int>(floor(dy + 0.5));
                
                // If the tile is visible then record it
                agg::rect_i tile(px, py, px + mWidth - 1, py + mHeight - 1);
                if (tile.overlaps(screen)) {
                    hit = true;
                    tessPoints.emplace_back(px, py);
                }
            }
        }
        
        if (!hit) break;
    }
    return tessPoints;
}
Example #12
0
int main(int argc, char *argv[])
{
  int tot_blocks;                           // total number of blocks in the domain
  int mem_blocks;                           // max blocks in memory
  int dsize[3];                             // domain grid size
  float jitter;                             // max amount to randomly displace particles
  float minvol, maxvol;                     // volume range, -1.0 = unused
  double times[TESS_MAX_TIMES];             // timing
  int wrap;                                 // wraparound neighbors flag
  int walls;                                // apply walls to simulation (wrap must be off)
  char outfile[256];                        // output file name
  int num_threads = 1;                      // threads diy can use

  // init MPI
  MPI_Comm comm = MPI_COMM_WORLD;
  MPI_Init(&argc, &argv);

  GetArgs(argc, argv, tot_blocks, mem_blocks, dsize, &jitter, &minvol, &maxvol, &wrap, &walls,
          outfile);

  // data extents
  typedef     diy::ContinuousBounds         Bounds;
  Bounds domain { 3 };
  for(int i = 0; i < 3; i++)
  {
    domain.min[i] = 0;
    domain.max[i] = dsize[i] - 1.0;
  }

  // init diy
  diy::mpi::communicator    world(comm);
  diy::FileStorage          storage("./DIY.XXXXXX");
  diy::Master               master(world,
				   num_threads,
                                   mem_blocks,
                                   &create_block,
                                   &destroy_block,
                                   &storage,
                                   &save_block,
                                   &load_block);
  diy::RoundRobinAssigner   assigner(world.size(), tot_blocks);
  AddAndGenerate            create(master, jitter);

  // decompose
  std::vector<int> my_gids;
  assigner.local_gids(world.rank(), my_gids);
  diy::RegularDecomposer<Bounds>::BoolVector          wraps;
  diy::RegularDecomposer<Bounds>::BoolVector          share_face;
  diy::RegularDecomposer<Bounds>::CoordinateVector    ghosts;
  if (wrap)
    wraps.assign(3, true);
  diy::decompose(3, world.rank(), domain, assigner, create, share_face, wraps, ghosts);

  // tessellate
  quants_t quants;
  timing(times, -1, -1, world);
  timing(times, TOT_TIME, -1, world);
  tess(master, quants, times);

  // output
  tess_save(master, outfile, times);
  timing(times, -1, TOT_TIME, world);
  tess_stats(master, quants, times);

  MPI_Finalize();

  return 0;
}
Example #13
0
void PatchInspector::rescanSelection()
{
	// Check if there is one distinct patch selected
	bool sensitive = (_selectionInfo.patchCount == 1);

	findNamedObject<wxPanel>(this, "PatchInspectorVertexPanel")->Enable(sensitive);
	findNamedObject<wxPanel>(this, "PatchInspectorCoordPanel")->Enable(sensitive);

	// Tesselation is always sensitive when one or more patches are selected
	findNamedObject<wxPanel>(this, "PatchInspectorTessPanel")->Enable(_selectionInfo.patchCount > 0);

	// Clear the patch reference
	setPatch(PatchNodePtr());

	if (_selectionInfo.patchCount > 0)
	{
		// Get the list of selected patches
		PatchPtrVector list = selection::algorithm::getSelectedPatches();

		Subdivisions tess(UINT_MAX, UINT_MAX);
		bool tessIsFixed = false;

		// Try to find a pair of same tesselation values
		for (PatchPtrVector::const_iterator i = list.begin(); i != list.end(); ++i)
        {
			IPatch& p = (*i)->getPatch();

			if (tess.x() == UINT_MAX)
            {
				// Not initialised yet, take these values for starters
				tessIsFixed = p.subdivionsFixed();
				tess = p.getSubdivisions();
			}
			else
			{
				// We already have a pair of divisions, compare
				Subdivisions otherTess = p.getSubdivisions();

				if (tessIsFixed != p.subdivionsFixed() || otherTess != tess)
				{
					// Our journey ends here, we cannot find a pair of tesselations
					// for all selected patches or the same fixed/variable status
					tessIsFixed = false;
					break;
				}
			}
		}

		_updateActive = true;

		// Load the "fixed tesselation" value
		findNamedObject<wxCheckBox>(this, "PatchInspectorFixedSubdivisions")->SetValue(tessIsFixed);

		wxSpinCtrl* fixedSubdivX = findNamedObject<wxSpinCtrl>(this, "PatchInspectorSubdivisionsX");
		wxSpinCtrl* fixedSubdivY = findNamedObject<wxSpinCtrl>(this, "PatchInspectorSubdivisionsY");

		fixedSubdivX->SetValue(tess[0]);
		fixedSubdivY->SetValue(tess[1]);

		fixedSubdivX->Enable(tessIsFixed);
		fixedSubdivY->Enable(tessIsFixed);

		findNamedObject<wxStaticText>(this, "PatchInspectorSubdivisionsXLabel")->Enable(tessIsFixed);
		findNamedObject<wxStaticText>(this, "PatchInspectorSubdivisionsYLabel")->Enable(tessIsFixed);

		if (_selectionInfo.patchCount == 1)
		{
			setPatch(list[0]);
		}

		_updateActive = false;
	}

	update();
}
Example #14
0
void AOVoxelTree::build(
    const Scene&    scene,
    BuilderType&    builder)
{
    // The voxel tree is built using the scene geometry at the middle of the shutter interval.
    const double time = scene.get_camera()->get_shutter_middle_time();

    // Loop over the assembly instances of the scene.
    for (const_each<AssemblyInstanceContainer> i = scene.assembly_instances(); i; ++i)
    {
        // Retrieve the assembly instance.
        const AssemblyInstance& assembly_instance = *i;

        // Retrieve the assembly.
        const Assembly& assembly = assembly_instance.get_assembly();

        // Loop over the object instances of the assembly.
        for (const_each<ObjectInstanceContainer> j = assembly.object_instances(); j; ++j)
        {
            // Retrieve the object instance.
            const ObjectInstance& object_instance = *j;

            // Compute the object space to world space transformation.
            const Transformd transform =
                  assembly_instance.transform_sequence().evaluate(time)
                * object_instance.get_transform();

            // Retrieve the object.
            Object& object = object_instance.get_object();

            // Retrieve the region kit of the object.
            Access<RegionKit> region_kit(&object.get_region_kit());

            // Loop over the regions of the object.
            const size_t region_count = region_kit->size();
            for (size_t region_index = 0; region_index < region_count; ++region_index)
            {
                // Retrieve the region.
                const IRegion* region = (*region_kit)[region_index];

                // Retrieve the tessellation of the region.
                Access<StaticTriangleTess> tess(&region->get_static_triangle_tess());

                // Push all triangles of the region into the tree.
                const size_t triangle_count = tess->m_primitives.size();
                for (size_t triangle_index = 0; triangle_index < triangle_count; ++triangle_index)
                {
                    // Fetch the triangle.
                    const Triangle& triangle = tess->m_primitives[triangle_index];

                    // Retrieve object instance space vertices of the triangle.
                    const GVector3& v0_os = tess->m_vertices[triangle.m_v0];
                    const GVector3& v1_os = tess->m_vertices[triangle.m_v1];
                    const GVector3& v2_os = tess->m_vertices[triangle.m_v2];

                    // Transform triangle vertices to world space.
                    const GVector3 v0(transform.point_to_parent(v0_os));
                    const GVector3 v1(transform.point_to_parent(v1_os));
                    const GVector3 v2(transform.point_to_parent(v2_os));

                    // Push the triangle into the tree.
                    TriangleIntersector intersector(v0, v1, v2);
                    builder.push(intersector);
                }
            }
        }
    }
}
Example #15
0
void LightSampler::collect_emitting_triangles(
    const Assembly&                     assembly,
    const AssemblyInstance&             assembly_instance,
    const TransformSequence&            transform_sequence)
{
    // Loop over the object instances of the assembly.
    const size_t object_instance_count = assembly.object_instances().size();
    for (size_t object_instance_index = 0; object_instance_index < object_instance_count; ++object_instance_index)
    {
        // Retrieve the object instance.
        const ObjectInstance* object_instance = assembly.object_instances().get_by_index(object_instance_index);

        // Retrieve the materials of the object instance.
        const MaterialArray& front_materials = object_instance->get_front_materials();
        const MaterialArray& back_materials = object_instance->get_back_materials();

        // Skip object instances without light-emitting materials.
        if (!has_emitting_materials(front_materials) && !has_emitting_materials(back_materials))
            continue;

        double object_area = 0.0;

        // Compute the object space to world space transformation.
        // todo: add support for moving light-emitters.
        const Transformd& object_instance_transform = object_instance->get_transform();
        const Transformd& assembly_instance_transform = transform_sequence.get_earliest_transform();
        const Transformd global_transform = assembly_instance_transform * object_instance_transform;

        // Retrieve the object.
        Object& object = object_instance->get_object();

        // Retrieve the region kit of the object.
        Access<RegionKit> region_kit(&object.get_region_kit());

        // Loop over the regions of the object.
        const size_t region_count = region_kit->size();
        for (size_t region_index = 0; region_index < region_count; ++region_index)
        {
            // Retrieve the region.
            const IRegion* region = (*region_kit)[region_index];

            // Retrieve the tessellation of the region.
            Access<StaticTriangleTess> tess(&region->get_static_triangle_tess());

            // Loop over the triangles of the region.
            const size_t triangle_count = tess->m_primitives.size();
            for (size_t triangle_index = 0; triangle_index < triangle_count; ++triangle_index)
            {
                // Fetch the triangle.
                const Triangle& triangle = tess->m_primitives[triangle_index];

                // Skip triangles without a material.
                if (triangle.m_pa == Triangle::None)
                    continue;

                // Fetch the materials assigned to this triangle.
                const size_t pa_index = static_cast<size_t>(triangle.m_pa);
                const Material* front_material =
                    pa_index < front_materials.size() ? front_materials[pa_index] : 0;
                const Material* back_material =
                    pa_index < back_materials.size() ? back_materials[pa_index] : 0;

                // Skip triangles that don't emit light.
                if ((front_material == 0 || front_material->has_emission() == false) &&
                    (back_material == 0 || back_material->has_emission() == false))
                    continue;

                // Retrieve object instance space vertices of the triangle.
                const GVector3& v0_os = tess->m_vertices[triangle.m_v0];
                const GVector3& v1_os = tess->m_vertices[triangle.m_v1];
                const GVector3& v2_os = tess->m_vertices[triangle.m_v2];

                // Transform triangle vertices to assembly space.
                const GVector3 v0_as = object_instance_transform.point_to_parent(v0_os);
                const GVector3 v1_as = object_instance_transform.point_to_parent(v1_os);
                const GVector3 v2_as = object_instance_transform.point_to_parent(v2_os);

                // Compute the support plane of the hit triangle in assembly space.
                const GTriangleType triangle_geometry(v0_as, v1_as, v2_as);
                TriangleSupportPlaneType triangle_support_plane;
                triangle_support_plane.initialize(TriangleType(triangle_geometry));

                // Transform triangle vertices to world space.
                const Vector3d v0(assembly_instance_transform.point_to_parent(v0_as));
                const Vector3d v1(assembly_instance_transform.point_to_parent(v1_as));
                const Vector3d v2(assembly_instance_transform.point_to_parent(v2_as));

                // Compute the geometric normal to the triangle and the area of the triangle.
                Vector3d geometric_normal = cross(v1 - v0, v2 - v0);
                const double geometric_normal_norm = norm(geometric_normal);
                if (geometric_normal_norm == 0.0)
                    continue;
                const double rcp_geometric_normal_norm = 1.0 / geometric_normal_norm;
                const double rcp_area = 2.0 * rcp_geometric_normal_norm;
                const double area = 0.5 * geometric_normal_norm;
                geometric_normal *= rcp_geometric_normal_norm;
                assert(is_normalized(geometric_normal));

                // Retrieve object instance space vertex normals.
                Vector3d n0_os, n1_os, n2_os;

                if (triangle.m_n0 != Triangle::None &&
                    triangle.m_n1 != Triangle::None &&
                    triangle.m_n2 != Triangle::None)
                {
                    n0_os = Vector3d(tess->m_vertex_normals[triangle.m_n0]);
                    n1_os = Vector3d(tess->m_vertex_normals[triangle.m_n1]);
                    n2_os = Vector3d(tess->m_vertex_normals[triangle.m_n2]);
                }
                else
                    n0_os = n1_os = n2_os = geometric_normal;

                // Transform vertex normals to world space.
                const Vector3d n0(normalize(global_transform.normal_to_parent(n0_os)));
                const Vector3d n1(normalize(global_transform.normal_to_parent(n1_os)));
                const Vector3d n2(normalize(global_transform.normal_to_parent(n2_os)));

                for (size_t side = 0; side < 2; ++side)
                {
                    // Retrieve the material; skip sides without a material or without emission.
                    const Material* material = side == 0 ? front_material : back_material;
                    if (material == 0 || material->has_emission() == false)
                        continue;

                    // Retrieve the EDF and get the importance multiplier.
                    double importance_multiplier = 1.0;
                    if (const EDF* edf = material->get_uncached_edf())
                        importance_multiplier = edf->get_uncached_importance_multiplier();

                    // Accumulate the object area for OSL shaders.
                    object_area += area;

                    // Compute the probability density of this triangle.
                    const double triangle_importance = m_params.m_importance_sampling ? area : 1.0;
                    const double triangle_prob = triangle_importance * importance_multiplier;

                    // Create a light-emitting triangle.
                    EmittingTriangle emitting_triangle;
                    emitting_triangle.m_assembly_instance = &assembly_instance;
                    emitting_triangle.m_object_instance_index = object_instance_index;
                    emitting_triangle.m_region_index = region_index;
                    emitting_triangle.m_triangle_index = triangle_index;
                    emitting_triangle.m_v0 = v0;
                    emitting_triangle.m_v1 = v1;
                    emitting_triangle.m_v2 = v2;
                    emitting_triangle.m_n0 = side == 0 ? n0 : -n0;
                    emitting_triangle.m_n1 = side == 0 ? n1 : -n1;
                    emitting_triangle.m_n2 = side == 0 ? n2 : -n2;
                    emitting_triangle.m_geometric_normal = side == 0 ? geometric_normal : -geometric_normal;
                    emitting_triangle.m_triangle_support_plane = triangle_support_plane;
                    emitting_triangle.m_rcp_area = rcp_area;
                    emitting_triangle.m_triangle_prob = 0.0;    // will be initialized once the emitting triangle CDF is built
                    emitting_triangle.m_material = material;

                    // Store the light-emitting triangle.
                    const size_t emitting_triangle_index = m_emitting_triangles.size();
                    m_emitting_triangles.push_back(emitting_triangle);

                    // Insert the light-emitting triangle into the CDF.
                    m_emitting_triangles_cdf.insert(emitting_triangle_index, triangle_prob);
                }
            }
        }

#ifdef APPLESEED_WITH_OSL
        store_object_area_in_shadergroups(
            &assembly_instance,
            object_instance,
            object_area,
            front_materials);

        store_object_area_in_shadergroups(
            &assembly_instance,
            object_instance,
            object_area,
            back_materials);
#endif
    }
}