一、實驗目標/要求: The goal of this assignment is to try your hand at various mesh processing tasks. A half-edge mesh adjacency data structure is provided, along with a very simple .obj mesh parser. As you modify the triangle mesh, it is critical that the manifold properties of the input surface are maintained, and that the adjacency data structure remains consistent. Throughout this assignment you are asked to consider the efficiency of various mesh operations: is it quadratic, linear, logarithmic, constant, etc? It’s ok if you don’t always implement the most efficient strategy (which may require additional data structures). (上面的的意思大概就是利用Loop Subdivision算法對簡單模型進行細分。)
二、實現效果: 第一組
第二組
第三組
三、實現方法/思路:
先更新原來的舊頂點,根據舊頂點信息計算出新頂點位置信息并將計算的新位置信息和原來的點組成pair并儲存在一個新的vector中(即下面算法中的update)。(另:此處要注意內部頂點和邊界點的更新方式,公式不要出錯) 分別根據內部邊和和邊界邊不同的處理方式算出插入的新點的位置信息,然后直接向原來的點vector(即vertices)中插入(用addVertex函數)新頂點。 利用步驟1)中的vector(即update)來更新舊頂點的位置信息(用一個for循環和setPos函數即可)。 新建一個臨時三角形面片的哈希表來存儲舊三角形面片信息(即下面算法中的tempTriangles),然后清除舊三角形面片信息(triangles.clear())和邊信息(edges.clear()),然后再利用臨時的三角形面片哈希表重構新的三角形面片信息和新的邊信息(邊信息是隨著三角形面片信息的更新而更新的,不用管)。 修復一下這邊信息,即為原來crease值不為零的邊及其“衍生”的邊重新附上crease值。 清空vertex_parents(這個玩意兒是通過一條邊的兩個端點去找邊上所產生的新點的,在插入新店的步驟(即步驟2)中進行準備,用在重構三角形面片信息的步驟(即步驟4中),為下一次細分做準備。
算法代碼如下: (只包含算法部分的代碼,不包含其余部分的代碼,太多了,懶得整,嘿嘿)
void Mesh
:: LoopSubdivision ( )
{ printf ( "Subdivide the mesh!\n" ) ; std
:: vector
< std
:: pair
< Vertex
* , Vec3f
>> update
; for ( edgeshashtype
:: iterator eIterator1
= edges
. begin ( ) ; eIterator1
!= edges
. end ( ) ; eIterator1
++ ) { Edge
* e
= eIterator1
- > second
; Edge
* temp
= e
- > getNext ( ) ; Vec3f
newPosition ( 0 , 0 , 0 ) ; std
:: vector
< Vertex
* > neighborVertices
; while ( temp
- > getOpposite ( ) != NULL && temp
- > getOpposite ( ) != e
) { neighborVertices
. push_back ( temp
- > getEndVertex ( ) ) ; temp
= temp
- > getOpposite ( ) - > getNext ( ) ; } if ( temp
- > getOpposite ( ) == NULL ) { neighborVertices
. clear ( ) ; Vertex
* v1
= temp
- > getEndVertex ( ) ; assert ( temp
- > getStartVertex ( ) == e
- > getEndVertex ( ) ) ; temp
= e
; while ( temp
- > getOpposite ( ) != NULL ) { temp
= temp
- > getOpposite ( ) - > getNext ( ) - > getNext ( ) ; } Vertex
* v2
= temp
- > getStartVertex ( ) ; assert ( temp
- > getEndVertex ( ) == e
- > getEndVertex ( ) ) ; newPosition
= newPosition
= 3.0 / 4.0 * e
- > getEndVertex ( ) - > getPos ( ) + 1.0 / 8.0 * ( v1
- > getPos ( ) + v2
- > getPos ( ) ) ; } else { int degree
= neighborVertices
. size ( ) ; float beta
= ( 5.0 / 8.0 - std
:: pow ( 3.0 / 8.0 + 1.0 / 4.0 * std
:: cos ( 2 * std
:: acos ( - 1 ) / degree
) , 2 ) ) / degree
; for ( int k
= 0 ; k
< degree
; k
++ ) newPosition
+ = beta
* neighborVertices
[ k
] - > getPos ( ) ; newPosition
+ = ( 1.0 - degree
* beta
) * e
- > getEndVertex ( ) - > getPos ( ) ; } update
. push_back ( std
:: make_pair ( e
- > getEndVertex ( ) , newPosition
) ) ; } for ( edgeshashtype
:: iterator eIterator2
= edges
. begin ( ) ; eIterator2
!= edges
. end ( ) ; eIterator2
++ ) { Edge
* e
= eIterator2
- > second
; Vec3f
newVertexPos ( 0 , 0 , 0 ) ; if ( e
- > getOpposite ( ) != NULL ) { if ( getChildVertex ( e
- > getStartVertex ( ) , e
- > getEndVertex ( ) ) != NULL ) continue ; newVertexPos
= 3.0 / 8.0 * ( e
- > getEndVertex ( ) - > getPos ( ) + e
- > getStartVertex ( ) - > getPos ( ) ) + 1.0 / 8.0 * ( e
- > getNext ( ) - > getEndVertex ( ) - > getPos ( ) + e
- > getOpposite ( ) - > getNext ( ) - > getEndVertex ( ) - > getPos ( ) ) ; } else newVertexPos
= 1.0 / 2.0 * ( e
- > getStartVertex ( ) - > getPos ( ) + e
- > getEndVertex ( ) - > getPos ( ) ) ; Vertex
* newVertex
= addVertex ( newVertexPos
) ; if ( newVertex
!= NULL ) setParentsChild ( e
- > getStartVertex ( ) , e
- > getEndVertex ( ) , newVertex
) ; } for ( int i
= 0 ; i
< update
. size ( ) ; i
++ ) update
[ i
] . first
- > setPos ( update
[ i
] . second
) ; triangleshashtype tempTriangles
= triangles
; triangles
. clear ( ) ; edges
. clear ( ) ; triangleshashtype
:: iterator tIterator
= tempTriangles
. begin ( ) ; for ( ; tIterator
!= tempTriangles
. end ( ) ; tIterator
++ ) { Triangle
* t
= tIterator
- > second
; Vertex
* v1
, * v2
, * v3
, * c12
, * c23
, * c13
; v1
= ( * t
) [ 0 ] ; v2
= ( * t
) [ 1 ] ; v3
= ( * t
) [ 2 ] ; c12
= getChildVertex ( v1
, v2
) ; c23
= getChildVertex ( v2
, v3
) ; c13
= getChildVertex ( v1
, v3
) ; if ( c12
== NULL || c23
== NULL || c13
== NULL ) break ; addTriangle ( c12
, c23
, c13
) ; addTriangle ( v1
, c12
, c13
) ; addTriangle ( v2
, c23
, c12
) ; addTriangle ( v3
, c13
, c23
) ; } for ( edgeshashtype
:: iterator eIterator3
= edges
. begin ( ) ; eIterator3
!= edges
. end ( ) ; eIterator3
++ ) { Edge
* e
= eIterator3
- > second
; std
:: pair
< Vertex
* , Vertex
* > ePair
= eIterator3
- > first
; if ( vertex_parents
. find ( ePair
) == vertex_parents
. end ( ) ) continue ; if ( e
- > getCrease ( ) ) { Vertex
* childVertex
= vertex_parents
. find ( ePair
) - > second
; assert ( edges
. find ( std
:: make_pair ( e
- > getStartVertex ( ) , childVertex
) ) != edges
. end ( ) ) ; edges
. find ( std
:: make_pair ( e
- > getStartVertex ( ) , childVertex
) ) - > second
- > setCrease ( e
- > getCrease ( ) ) ; assert ( edges
. find ( std
:: make_pair ( childVertex
, e
- > getEndVertex ( ) ) ) != edges
. end ( ) ) ; edges
. find ( std
:: make_pair ( childVertex
, e
- > getEndVertex ( ) ) ) - > second
- > setCrease ( e
- > getCrease ( ) ) ; } } vertex_parents
. clear ( ) ;
}
四、實驗感受與體會: 原來的模型干干巴巴的,麻麻賴賴的,一點兒都不圓潤,盤它!
總結
以上是生活随笔 為你收集整理的山东大学计算机图形学实验(Opengl实现):Loop Subdivision算法对模型进行细分 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。