ライン ジオメトリのテクスチャ座標を作成する

このスクリプトは以下を示します

lineGeometry-texCoords.py

  1 """ このスクリプトは、シーン内にライン ジオメトリの UV 座標を作成し、
  2     点線のパターンを
  3     透明度テクスチャで作成できます。
 4     デモ用に、ライン ジオメトリの例が
  5     ロードされます。
 6 """
  7 
  8 newScene()
  9 
 10 class GeometryAccess(object):
 11     """ vrdGeometryNode のプリミティブと頂点データへのアクセスをサポートします。
12 
 13         Args:
 14             geo (vrdGeometryNode): ジオメトリ ノード。
 15     """
 16     def __init__(self, geo):      
 17         if geo.isValid():
 18             self.__positions = geo.getPositions()
 19             self.__indices = geo.getIndices()
 20             self.__primType = geo.getPrimitiveType()
 21         else:
 22             self.__positions = []
 23             self.__indices = []
 24             self.__primType = None
 25                
 26     def isLineGeometry(self):
 27         """
 28             戻り値: 
 29                 ジオメトリがライン ジオメトリであるかどうか。
30         """
 31         return GeometryAccess.isLineType(self.__primType)
 32        
 33     def isLineType(primType):
 34         """
 35             戻り値: 
 36                 タイプがライン プリミティブ タイプであるかどうか。
37         """
 38         return primType in (vrGeometryTypes.Lines, vrGeometryTypes.LineStrip)
 39        
 40        
 41     def getPosition(self, vertexIndex):
 42         """
 43             Args:
 44                 vertexIndex (int): 0 ~ N-1 の範囲内の頂点インデックス
 45                                    N は頂点数です。
46             戻り値: 
 47                 3D 頂点の位置。
48         """   
 49         return QVector3D(self.__positions[3*vertexIndex],
 50                          self.__positions[3*vertexIndex+1],
 51                          self.__positions[3*vertexIndex+2])
 52 
 53 
 54     def getPrimitiveVertexIndices(self, primId):
 55         """
 56             Args:
 57                 primId (int): 0 から N-1 までの範囲のプリミティブ インデックス
 58                               N はプリミティブの数です。
59             戻り値: 
 60                プリミティブの頂点インデックスのリスト: 
 61                 三角形の場合は 3 つのインデックス、ライン プリミティブの場合 は 2 つ、ポイント プリミティブの場合は 1 つ。
62         """
 63         if self.__primType == vrGeometryTypes.Points:
 64             v0 = primId
 65             return [self.__indices[v0]]
 66         elif self.__primType == vrGeometryTypes.Lines:
 67             v0 = primId * 2
 68             v1 = primId * 2 + 1
 69             return [self.__indices[v0], self.__indices[v1]]
 70         elif self.__primType == vrGeometryTypes.LineStrip:
 71             v0 = primId
 72             v1 = primId + 1
 73             return [self.__indices[v0], self.__indices[v1]]
 74         elif self.__primType == vrGeometryTypes.Triangles:
 75             v0 = primId * 3
 76             v1 = primId * 3 + 1
 77             v2 = primId * 3 + 2
 78             return [self.__indices[v0], self.__indices[v1], self.__indices[v2]]
 79         else:
 80             return []
 81 
 82 
 83 # シーン ツリー内のライン ジオメトリを検索するヘルパー メソッド。
84 
 85 def findGeosRecursive(node, geos, predicate):
 86     """ ノードから開始してシーングラフを再帰的にトラバース、
 87         述語を使用してフィルタできるジオメトリ ノードを
 88         収集します。
89         Args:
 90             node (vrdNode): 現在トラバースされているノード
 91             geos (vrdGeometryNode のリスト): 収集されたジオメトリ ノードのリスト
 92             predicate (function): None または predicate(vrdGeometryNode)->bool
 93     """
 94     geo = vrdGeometryNode(node)
 95     if geo.isValid():
 96         if predicate is None または predicate(geo):
 97             geos.append(geo)
 98         # ツリーのトラバースを停止します
 99     else:
100         # traverse the children
101         for child in node.getChildren():
102             findGeosRecursive(child, geos, predicate)
103 
104 def findGeos(root, predicate=None):
105     """ findGeosRecursive をラップして、ジオメトリ ノードのリストを返します。
106     """
107     geos = []
108     findGeosRecursive(vrdNode(root), geos, predicate)
109     return geos
110 
111 
112 def findLineGeos(root):
113     predicate = lambda geo : GeometryAccess.isLineType(geo.getPrimitiveType())
114     lines = findGeos(root, predicate)
115     return lines
116 
117 
118 def createLineTexCoords(node):
119     """指定されたライン ジオメトリにテクスチャ座標 (u, 0) を割り当てます。u は 
120        0.0 (ライン シーケンスの開始) から「length」(ライン シーケンスの終了) の範囲です。
121        線分に沿った座標は、3D 線分の長さから計算され、
122        テクスチャの幅がシーンの 100 mm に対応するように
123        スケーリングされます(ワールドスケールのテクスチャ座標)
124 
125     Args:
126         node (vrdNode): ライン ジオメトリ ノード。
127                         ジオメトリは、3D で連結されるのと同じ順序で
128                         線分を格納するものと想定されます。
129     """
130 
131     geo = vrdGeometryNode(node)
132     geoAccess = GeometryAccess(geo)
133     if not geoAccess.isLineGeometry():
134         return
135                    
136     # 開始頂点からライン ジオメトリに沿った各頂点まで、
137     # すべての線分セグメントの長さを計算します。
138     #
139     # v0----v1----v2----v3
140     # |
141     # -------|
142     # ------------|
143     # -------------------|
144    
145     vertexCount = geo.getVertexCount()
146     segmentLengths = [0.0] * vertexCount
147     totalLength = 0.0
148 
149     # 線分の実際のワールド長さを計算するには、
150     # ジオメトリのワールド スケール係数が必要です。
151     sx, sy, sz = toNode(geo.getObjectId()).getWorldScale()
152     scale = QVector3D(sx, sy, sz)
153 
154     lineCount = geo.getPrimitiveCount()
155     for lineId in range(0, lineCount):
156         v0, v1 = geoAccess.getPrimitiveVertexIndices(lineId)
157         p0 = geoAccess.getPosition(v0)
158         p1 = geoAccess.getPosition(v1)
159         lineLength = ((p1 - p0) * scale).length()
160         segmentLengths[v0] = totalLength
161         segmentLengths[v1] = totalLength + lineLength
162         totalLength += lineLength
163 
164     # 長さのリストからワールドスケールのテクスチャ座標を作成する:
165 
166# UV 空間の 1 は、シーン単位の 100 mm に相当します
167     mmToUVUnit = 1.0 / 100.0
168     # 各頂点の 2D 座標のフラット リストを事前に割り当てます
169     texCoords2f = [0.0] * (vertexCount * 2)    
170    
171     for i in range(0, vertexCount):
172         u = segmentLengths[i] * mmToUVUnit
173         texCoords2f[i * 2] = u
174         # v 座標は 0.0 のままです
175        
176     geo.setTexCoords(texCoords2f)
177 
178 
179 ###########################################################
180 
181 # サンプルのライン ジオメトリをロードします
182 loadGeometry("$VRED_EXAMPLES/geo/curve.osb")
183 
184 # シーングラフのすべてのライン ジオメトリを検索します
185 root = getRootNode()
186 lines = findLineGeos(root)
187 print ("Found line geometries:", len(lines))
188 
189 # テクスチャ座標を作成する
190 for line in lines:
191     createLineTexCoords(line)
192