Create texture coordinates for line geometries¶
This script shows
- how to use
vrdGeometryNode
for low level access to geometry data. SeeGeometryAccess
class andcreateLineTexCoords
method below. - how to find
vrdGeometryNode
nodes in the Scenegraph based on a filter predicate, in this case to find only line geometries. See methodfindLineGeos
.
lineGeometry-texCoords.py¶
1# © 2024 Autodesk, Inc. All rights reserved.
2
3""" This script creates UV coordinates for line geometries
4 in the scene, so that a stipple pattern can be created
5 with a transparency texture.
6 For demonstration purposes an example line geometry is
7 loaded.
8"""
9
10newScene()
11
12class GeometryAccess(object):
13 """ Helps accessing primitives and vertex data of a vrdGeometryNode.
14
15 Args:
16 geo (vrdGeometryNode): The geometry node.
17 """
18 def __init__(self, geo):
19 if geo.isValid():
20 self.__positions = geo.getPositions()
21 self.__indices = geo.getIndices()
22 self.__primType = geo.getPrimitiveType()
23 else:
24 self.__positions = []
25 self.__indices = []
26 self.__primType = None
27
28 def isLineGeometry(self):
29 """
30 Returns:
31 Whether the geometry is a line geometry.
32 """
33 return GeometryAccess.isLine(self.__primType)
34
35 def isLine(primType):
36 """
37 Returns:
38 Whether the type is a line primitive type.
39 """
40 return primType in (vrGeometryTypes.Lines, vrGeometryTypes.LineStrip)
41
42
43 def getPosition(self, vertexIndex):
44 """
45 Args:
46 vertexIndex (int): The vertex index in range from 0 to N-1
47 where N is the vertex count.
48 Returns:
49 3d vertex position.
50 """
51 return QVector3D(self.__positions[3*vertexIndex],
52 self.__positions[3*vertexIndex+1],
53 self.__positions[3*vertexIndex+2])
54
55
56 def getPrimitiveVertexIndices(self, primId):
57 """
58 Args:
59 primId (int): The primitive index in range from 0 to N-1
60 where N is the primitive count.
61 Returns:
62 A list of vertex indices of a primitive: 3 indices for a
63 triangle, 2 for a line primitives, 1 for a point primitive.
64 """
65 if self.__primType == vrGeometryTypes.Points:
66 v0 = primId
67 return [self.__indices[v0]]
68 elif self.__primType == vrGeometryTypes.Lines:
69 v0 = primId * 2
70 v1 = primId * 2 + 1
71 return [self.__indices[v0], self.__indices[v1]]
72 elif self.__primType == vrGeometryTypes.LineStrip:
73 v0 = primId
74 v1 = primId + 1
75 return [self.__indices[v0], self.__indices[v1]]
76 elif self.__primType == vrGeometryTypes.Triangles:
77 v0 = primId * 3
78 v1 = primId * 3 + 1
79 v2 = primId * 3 + 2
80 return [self.__indices[v0], self.__indices[v1], self.__indices[v2]]
81 else:
82 return []
83
84
85def findLineGeos(root):
86 """ Find line geometries in the scene tree. """
87 predicate = lambda node : node.isType(vrdGeometryNode) and GeometryAccess.isLine(node.getPrimitiveType())
88 lines = vrNodeService.findNodes(predicate, vrdFindOptions(), root)
89 return lines
90
91
92def createLineTexCoords(node):
93 """Assigns texture coordinates (u, 0) to a given line geometry, with u
94 going from 0.0 (begin of line sequence) to "length" (end of line sequence).
95 The coordinates along the line are calculated from the lengths of the
96 3D lines, and scaled such that the texture width corresponds to 100 mm
97 in the scene (world-scale texture coordinates)
98
99 Args:
100 node (vrdNode): A line geometry node.
101 It is assumed that the geometry stores the lines
102 in the same order as they are concatenated in 3D.
103 """
104
105 geo = vrdGeometryNode(node)
106 geoAccess = GeometryAccess(geo)
107 if not geoAccess.isLineGeometry():
108 return
109
110 # Calculate lengths of all line segments, from start vertex
111 # to each vertex along the line geometry.
112 #
113 # v0----v1----v2----v3
114 # |
115 # -------|
116 # ------------|
117 # -------------------|
118
119 vertexCount = geo.getVertexCount()
120 segmentLengths = [0.0] * vertexCount
121 totalLength = 0.0
122
123 # The world scale factor of the geometry is needed to
124 # calculate the actual world length of the lines.
125 sx, sy, sz = toNode(geo.getObjectId()).getWorldScale()
126 scale = QVector3D(sx, sy, sz)
127
128 lineCount = geo.getPrimitiveCount()
129 for lineId in range(0, lineCount):
130 v0, v1 = geoAccess.getPrimitiveVertexIndices(lineId)
131 p0 = geoAccess.getPosition(v0)
132 p1 = geoAccess.getPosition(v1)
133 lineLength = ((p1 - p0) * scale).length()
134 segmentLengths[v0] = totalLength
135 segmentLengths[v1] = totalLength + lineLength
136 totalLength += lineLength
137
138 # Create world-scale texture coordinates from list of lengths:
139
140 # 1 in UV space corresponds to 100mm in scene units
141 mmToUVUnit = 1.0 / 100.0
142 # Pre-allocate flat list of 2d-coordinates for each vertex
143 texCoords2f = [0.0] * (vertexCount * 2)
144
145 for i in range(0, vertexCount):
146 u = segmentLengths[i] * mmToUVUnit
147 texCoords2f[i * 2] = u
148 # v-coordinate stays 0.0
149
150 geo.setTexCoords(texCoords2f)
151
152
153###########################################################
154
155# Load example line geometry
156loadGeometry("$VRED_EXAMPLES/geo/curve.osb")
157
158# Find all line geometries in scenegraph
159root = getRootNode()
160lines = findLineGeos(root)
161print ("Found line geometries:", len(lines))
162
163# Create the texture coordinates
164for line in lines:
165 createLineTexCoords(line)
166