113 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			113 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright 2009-2021 Intel Corporation
 | |
| // SPDX-License-Identifier: Apache-2.0
 | |
| 
 | |
| #include "subdivpatch1base.h"
 | |
| 
 | |
| namespace embree
 | |
| {
 | |
|   SubdivPatch1Base::SubdivPatch1Base (const unsigned int gID,
 | |
|                                       const unsigned int pID,
 | |
|                                       const unsigned int subPatch,
 | |
|                                       const SubdivMesh *const mesh,
 | |
|                                       const size_t time,
 | |
|                                       const Vec2f uv[4],
 | |
|                                       const float edge_level[4],
 | |
|                                       const int subdiv[4],
 | |
|                                       const int simd_width)
 | |
|   : flags(0), type(INVALID_PATCH), geom(gID), prim(pID), time_(unsigned(time))
 | |
|   {
 | |
|     static_assert(sizeof(SubdivPatch1Base) == 5 * 64, "SubdivPatch1Base has wrong size");
 | |
| 
 | |
|     const HalfEdge* edge = mesh->getHalfEdge(0,pID);
 | |
| 
 | |
|     if (edge->patch_type == HalfEdge::BILINEAR_PATCH)
 | |
|     {
 | |
|       type = BILINEAR_PATCH;
 | |
|       new (patch_v) BilinearPatch3fa(edge,mesh->getVertexBuffer(time));
 | |
|     }
 | |
|     else if (edge->patch_type == HalfEdge::REGULAR_QUAD_PATCH) 
 | |
|     {
 | |
| #if PATCH_USE_BEZIER_PATCH 
 | |
|       type = BEZIER_PATCH;
 | |
|       new (patch_v) BezierPatch3fa(BSplinePatch3fa(CatmullClarkPatch3fa(edge,mesh->getVertexBuffer(time))));
 | |
| #else
 | |
|       type = BSPLINE_PATCH;
 | |
|       new (patch_v) BSplinePatch3fa(CatmullClarkPatch3fa(edge,mesh->getVertexBuffer(time))); // FIXME: init BSpline directly from half edge structure
 | |
| #endif      
 | |
|     }
 | |
| #if PATCH_USE_GREGORY == 2
 | |
|     else if (edge->patch_type == HalfEdge::IRREGULAR_QUAD_PATCH) 
 | |
|     {
 | |
|       type = GREGORY_PATCH;
 | |
|       new (patch_v) DenseGregoryPatch3fa(GregoryPatch3fa(CatmullClarkPatch3fa(edge,mesh->getVertexBuffer(time))));
 | |
|     }
 | |
| #endif
 | |
|     else
 | |
|     {
 | |
|       type = EVAL_PATCH;
 | |
|       set_edge(mesh->getHalfEdge(0,pID));
 | |
|       set_subPatch(subPatch);
 | |
|     }
 | |
| 
 | |
|     for (size_t i=0; i<4; i++) {
 | |
|       u[i] = (unsigned short)clamp(uv[i].x * (0x10000/8.0f), 0.0f, float(0xFFFF));
 | |
|       v[i] = (unsigned short)clamp(uv[i].y * (0x10000/8.0f), 0.0f, float(0xFFFF));
 | |
|     }
 | |
| 
 | |
|     updateEdgeLevels(edge_level,subdiv,mesh,simd_width);
 | |
|   }
 | |
| 
 | |
|   void SubdivPatch1Base::computeEdgeLevels(const float edge_level[4], const int subdiv[4], float level[4])
 | |
|   {
 | |
|     /* init discrete edge tessellation levels and grid resolution */
 | |
|     assert( edge_level[0] >= 0.0f );
 | |
|     assert( edge_level[1] >= 0.0f );
 | |
|     assert( edge_level[2] >= 0.0f );
 | |
|     assert( edge_level[3] >= 0.0f );
 | |
| 
 | |
|     level[0] = max(ceilf(adjustTessellationLevel(edge_level[0],subdiv[0])),1.0f);
 | |
|     level[1] = max(ceilf(adjustTessellationLevel(edge_level[1],subdiv[1])),1.0f);
 | |
|     level[2] = max(ceilf(adjustTessellationLevel(edge_level[2],subdiv[2])),1.0f);
 | |
|     level[3] = max(ceilf(adjustTessellationLevel(edge_level[3],subdiv[3])),1.0f);
 | |
|   }
 | |
| 
 | |
|   Vec2i SubdivPatch1Base::computeGridSize(const float level[4])
 | |
|   {
 | |
|     return Vec2i((int)max(level[0],level[2])+1,
 | |
|                  (int)max(level[1],level[3])+1);
 | |
|   }
 | |
|   
 | |
|   bool SubdivPatch1Base::updateEdgeLevels(const float edge_level[4], const int subdiv[4], const SubdivMesh *const mesh, const int simd_width)
 | |
|   {
 | |
|     /* calculate edge levels */
 | |
|     float new_level[4];
 | |
|     computeEdgeLevels(edge_level,subdiv,new_level);
 | |
| 
 | |
|     /* calculate if tessellation pattern changed */
 | |
|     bool grid_changed = false;
 | |
|     for (size_t i=0; i<4; i++) {
 | |
|       grid_changed |= (int)new_level[i] != (int)level[i]; 
 | |
|       level[i] = new_level[i];
 | |
|     }
 | |
| 
 | |
|     /* compute grid resolution */
 | |
|     Vec2i res = computeGridSize(level);
 | |
|     grid_u_res = res.x; grid_v_res = res.y;
 | |
|     grid_size_simd_blocks = ((grid_u_res*grid_v_res+simd_width-1)&(-simd_width)) / simd_width;
 | |
| 
 | |
|     /* need stiching? */
 | |
|     flags &= ~TRANSITION_PATCH;
 | |
|     const int int_edge_points0 = (int)level[0] + 1;
 | |
|     const int int_edge_points1 = (int)level[1] + 1;
 | |
|     const int int_edge_points2 = (int)level[2] + 1;
 | |
|     const int int_edge_points3 = (int)level[3] + 1;
 | |
|     if (int_edge_points0 < (int)grid_u_res ||
 | |
| 	int_edge_points2 < (int)grid_u_res ||
 | |
| 	int_edge_points1 < (int)grid_v_res ||
 | |
| 	int_edge_points3 < (int)grid_v_res) {
 | |
|       flags |= TRANSITION_PATCH;
 | |
|     }
 | |
| 
 | |
|     return grid_changed;
 | |
|   }
 | |
| }
 |