このスクリプトは以下を示します
GeometryAccess
クラスと createLineTexCoords
メソッドを参照してください。findLineGeos
、findGeos
、および findGeosRecursive
メソッドを参照してください。 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