Trying to texture a multipatch

2840
4
11-02-2011 02:01 PM
AllanMills
New Contributor III
I'm trying to make a fairly simple multipatch with an image textured onto it. The multipatch is basically made from a line with an upper and lower set of Z values.

Creating the multipatch isn't a problem, the problem comes when I try to texture it. I've read some example code:

http://edndoc.esri.com/arcobjects/9.2/NET/D773962D-2B32-4459-BB3F-376D2F6DE82F.htm
http://edndoc.esri.com/arcobjects/9.2/ComponentHelp/esri3DAnalyst/IGeneralMultiPatchCreator_Example....

Which gives me a general idea, but neither code sample or the documentation gives me a good enough idea on how the interfaces work. I need the image to stretch across the whole of the multipatch, but I can't quite work out what combination of values to feed in to make this happen. The SetTextureWKSPoint calls really don't make any sense to me, I'm not sure what the parameters actually mean.

Does anyone have a simple code sample or a better explanation on what the calls in the IGeneralMultiPatchCreator interface actually mean?

Thanks.
0 Kudos
4 Replies
xmxu
by
New Contributor
I'm trying to make a fairly simple multipatch with an image textured onto it. The multipatch is basically made from a line with an upper and lower set of Z values.

Creating the multipatch isn't a problem, the problem comes when I try to texture it. I've read some example code:

http://edndoc.esri.com/arcobjects/9.2/NET/D773962D-2B32-4459-BB3F-376D2F6DE82F.htm
http://edndoc.esri.com/arcobjects/9.2/ComponentHelp/esri3DAnalyst/IGeneralMultiPatchCreator_Example....

Which gives me a general idea, but neither code sample or the documentation gives me a good enough idea on how the interfaces work. I need the image to stretch across the whole of the multipatch, but I can't quite work out what combination of values to feed in to make this happen. The SetTextureWKSPoint calls really don't make any sense to me, I'm not sure what the parameters actually mean.

Does anyone have a simple code sample or a better explanation on what the calls in the IGeneralMultiPatchCreator interface actually mean?

Thanks.


I believe that is all you can get from Esri. The 3D modelling is moved to CityEngine and the 3D development of native ArcGIS seems over.
0 Kudos
nicogis
MVP Frequent Contributor
in this document http://downloads.esri.com/support/whitepapers/ao_/J9749_MultiPatch_Geometry_Type.pdf (from page 142) you can see details on texture for multipatch
JohnMcGlynn
Occasional Contributor

I read that document and like Allan I couldn't get it to work.

My successful effort was the sub below. I have used it to add images to the flags on the Sydney Harbour Bridge and the Anzac Bridge in Sydney. Sorry for the line nos, I forgot to strip them out.

    Private Sub tileComponentGeometry(ByVal sLayer As String, ByVal sOID As String, _

                                        ByVal sTextureFile As String, ByVal sGeomNo As String, _

                            ByRef sError As String, ByRef sMsg As String, ByVal sXfreq As String, _

                            ByVal sYfreq As String)

        ' Add an image to a component geometry. The image is tiled Xfreq x Yfreq across the geometry.

        ' sOID can only refer to one component. The image is in the texture file.

1:      Using pComReleaser As New ESRI.ArcGIS.ADF.ComReleaser

2:          Dim pColour As IRgbColor

3:          Dim iColourNo As Integer

4:          Dim pFeat As IFeature

5:          Dim pFC As IFeatureClass

6:          Dim pPtColl As IPointCollection4

7:          Dim iOID As Integer

8:          Dim pGeom As IGeometry

9:          Dim bGeomProgress As Boolean

10:         Dim pPt1 As ESRI.ArcGIS.Geometry.IPoint

11:         Dim pWKSPt As WKSPoint

12:         Dim pZAware As IZAware

13:         Dim pExGeomCol As IGeometryCollection

14:         Dim pExMultiPatch As IMultiPatch

15:         Dim pNewGeomPatchCreator As IGeneralMultiPatchCreator

16:         Dim pGenInfo As IGeneralMultiPatchInfo

17:         Dim pMat As IGeometryMaterial

18:         Dim pMatList As IGeometryMaterialList

19:         Dim i As Integer

20:         Dim iPatchType As ESRI.ArcGIS.Geometry.esriPatchType

21:         Dim j As Integer

22:         Dim k As Integer

23:         Dim n As Integer

24:         Dim iVertices As Integer

25:         Dim pNewMultiPatch As IMultiPatch

26:         Dim pSpatialRef As ISpatialReference

27:         Dim sFldOID As String

28:         Dim bWhere As Boolean = True

29:         Dim iGeomCount As Integer

30:         Dim iGeomNo As Integer

31:         Dim iPatchCount As Integer

32:         Dim iAction As m_eTextureAction = m_iTextureAction

33:         Dim iVertexCount As Integer

34:         Dim s As String = "s"

35:         Dim pColTextureFiles As New StringCollection

36:         Dim sTempTextureFile As String

37:         Dim iFileIndex As Short = 0

38:         Dim dTransparency As Double  ' 0 to 1

39:         Dim sFileDir As String = My.Application.Info.DirectoryPath

40:         Dim pExMultiPatchCopy As IMultiPatch

41:         Dim iNewTexture As Short

42:         Dim hPatchMatII As New Hashtable ' Patch index and it's material index

43:         Dim hTexturePts As New Hashtable ' Point index + texture pt

44:         Dim hExistingTexturesII As New Hashtable ' Material No + nothing

45:         Dim iPriority As Integer

46:         Dim iGeomMatIndex As Integer ' The material index of iGeomNo

47:         Dim bAssigned As Boolean = False ' Set to True if the texture is overwriting an existing texture

49:         Dim iXfreq As Short

50:         Dim iYfreq As Short

51:         Dim iX As Short

52:         Dim iY As Short

53:         Dim iTotTextureVertexCount As Integer

54:         Dim iTextureVertexCount As Integer

55:         Dim iTexture As Integer

56:         Try

57:             sError = ""

58:             sMsg = ""

                ' Only one component can be changed and at least one geometry must be specified.

59:             If String.IsNullOrEmpty(sOID) OrElse IsNumeric(sOID) = False Then

60:                 sError = "One (and only one) Component must be chosen"

61:                 Exit Sub

62:             End If

                ' Set the OID

63:             iOID = CInt(sOID)

64:             If String.IsNullOrEmpty(sGeomNo) OrElse IsNumeric(sGeomNo) = False Then

65:                 sError = "At least one Geometry must be chosen as a Geometry Number"

66:                 Exit Sub

67:             End If

                ' Geometry No

68:             iGeomNo = CInt(sGeomNo)

                ' X and Y frequency

69:             If String.IsNullOrEmpty(sXfreq) Or String.IsNullOrEmpty(sYfreq) Then

70:                 sError = "A Row and Column tile frequency is missing"

71:                 Exit Sub

72:             End If

73:             If IsNumeric(sXfreq) = False Or IsNumeric(sYfreq) = False Then

74:                 sError = "The Row or Column tile frequency is not a number"

75:                 Exit Sub

76:             End If

77:             iXfreq = CInt(sXfreq)

78:             iYfreq = CInt(sYfreq)

                ' Spatial Reference

79:             pSpatialRef = m_pSxDoc.Scene.SpatialReference

                ' Layer FeatureClass

80:             Call getLayerFC(sLayer, pFC, sError, m_hLayers)

81:             If sError.Length > 0 Then

82:                 sError = "cmdLayerReColour;" & vbCrLf & sError

83:                 MsgBox(sError)

84:                 If g_bLogging = True Then g_wLog.WriteLine(Format(Now, "hh:mm:ss") & " " & sError)

85:                 Exit Sub

86:             End If

87:             pComReleaser.ManageLifetime(pFC)

88:             sFldOID = pFC.OIDFieldName

                ' Get the geometries that make up the component and copy them with the

                ' old or the new colour/texture. Note that you cannot update these values in the

                ' existing multipatches.

89:             pFeat = pFC.GetFeature(iOID)

90:             StatusLabel1.Text = iOID.ToString

91:             StatusStrip1.Refresh()

92:             If pFeat.ShapeCopy.IsEmpty Then

93:                 sError = "EMPTY SHAPE"

94:                 sMsg = "Shape is empty for feature; OID = " & sOID

95:                 Exit Sub

96:             End If

97:             bGeomProgress = False

98:             pExGeomCol = CType(pFeat.ShapeCopy, IGeometryCollection)

                ' Decide if a progressbar of geometry is required

99:             iGeomCount = pExGeomCol.GeometryCount

100:            If iGeomCount > MAX_GEOM_COUNT_IGNORE Then

101:                bGeomProgress = True

102:                ProgressBar1.Value = 0

103:                ProgressBar1.Maximum = iGeomCount

104:            End If

                ' Get the existing Multipatch and it's info

105:            pExMultiPatch = CType(pFeat.ShapeCopy, IMultiPatch)

                ' Make a copy

106:            Dim objectCopy As IObjectCopy = New ObjectCopyClass()

107:            Dim obj As Object = objectCopy.Copy(CObj(pExMultiPatch))

108:            pExMultiPatchCopy = CType(obj, IMultiPatch)

109:            pComReleaser.ManageLifetime(pExMultiPatchCopy)

110:            pGenInfo = pExMultiPatchCopy

                ' Get the relationship between the patches (geometries) and the materials

                ' and the material index of the chosen geometry

111:            iTotTextureVertexCount = 0 ' The existing total texture vertex count. If the new tiles replace

                '                   ' an existing texture then the count from that texture is omitted.

112:            For i = 0 To pGenInfo.PatchCount - 1

113:                j = pGenInfo.PatchMaterialIndex(i)

114:                hPatchMatII.Add(i, j)

115:                If i = iGeomNo Then

116:                    iGeomMatIndex = j

117:                    iTotTextureVertexCount += (iXfreq * iYfreq) + 4 ' Add top left + bottom rt texture pts

118:                ElseIf pGenInfo.IsMaterialTextured(j) = True Then

119:                    iTotTextureVertexCount += pGenInfo.PatchTextureVertexCount(i)

120:                End If

121:            Next i

                ' MultiPatch Info

122:            iVertices = pGenInfo.VertexCount

123:            iPatchCount = pGenInfo.PatchCount

                ' Create the new materials as a copy of the existing ones

124:            pMatList = New GeometryMaterialListClass

125:            For i = 0 To pGenInfo.MaterialCount - 1

126:                pMat = New GeometryMaterial

127:                If i = iGeomMatIndex And pGenInfo.IsMaterialTextured(i) = True Then

                        ' Replace the old with the new texture - no colour

128:                    pMat.TextureImage = sTextureFile

129:                    iNewTexture = i

130:                    bAssigned = True

131:                Else

                        ' Existing Texture

                        ' Colour

132:                    iColourNo = pGenInfo.MaterialColor(i)

133:                    pColour = New RgbColor

134:                    pColour.RGB = iColourNo

135:                    pMat.Color = pColour

136:                    If pGenInfo.IsMaterialTextured(i) = True Then

137:                        hExistingTexturesII.Add(i, i)

                            ' Save an image of the texture

138:                        sTempTextureFile = sFileDir & "\" & TEXTURE_TEMP_FILE & iFileIndex.ToString & ".jpg"

139:                        If IO.File.Exists(sTempTextureFile) Then

140:                            IO.File.Delete(sTempTextureFile)

141:                        End If

142:                        StatusLabel1.Text = "OID " & sOID & " reading Texture No " & i.ToString

143:                        StatusStrip1.Refresh()

144:                        Call textureImageCreate(pGenInfo, i, sTempTextureFile, sError)

145:                        If sError.Length > 0 Then

146:                            sError = "tileComponentGeometry;" & vbCrLf & sError

147:                            Exit Sub

148:                        End If

                            ' Add the file to the list so it can be deleted later

149:                        pColTextureFiles.Add(sTempTextureFile)

150:                        pMat.TextureImage = sTempTextureFile

151:                        iFileIndex += 1

152:                    End If

                        ' Transparency

153:                    dTransparency = pGenInfo.MaterialTransparencyPercent(i)

154:                    pMat.Transparency = dTransparency / 100

155:                End If

156:                pMatList.AddMaterial(pMat)

157:            Next i

158:            If bAssigned = False Then

                    ' Add the new material to the material list - no colour

159:                iNewTexture = pMatList.Count

160:                pMat = New GeometryMaterial

                    ' New texture

161:                pMat.TextureImage = sTextureFile

162:                pMatList.AddMaterial(pMat)

163:            End If

                ' Start the MultiPatch creator for the geometry copy

164:            pNewGeomPatchCreator = New GeneralMultiPatchCreatorClass

165:            pNewGeomPatchCreator.Init(iVertices, iGeomCount, False, False, False, iTotTextureVertexCount, pMatList)

                ' Set the patch types, points, materials and start points for vertices and textures

166:            k = 0 ' Vertex

167:            n = 0 ' Vertex

168:            iTexture = 0 ' Vertex

169:            For i = 0 To iGeomCount - 1

170:                iPatchType = pGenInfo.PatchType(i)

171:                iVertexCount = pGenInfo.PatchVertexCount(i)

172:                iTextureVertexCount = pGenInfo.PatchTextureVertexCount(i)

                    ' Patch Type

173:                pNewGeomPatchCreator.SetPatchType(i, iPatchType)

                    ' Patch No set start of next patch

174:                pNewGeomPatchCreator.SetPatchPointIndex(i, k)

                    ' Patch Material

175:                If i = iGeomNo Then

176:                    pNewGeomPatchCreator.SetMaterialIndex(i, iNewTexture)

177:                Else

178:                    pNewGeomPatchCreator.SetMaterialIndex(i, hPatchMatII(i))

179:                End If

                    ' Patch priority

180:                iPriority = pGenInfo.PatchPriority(i)

181:                pNewGeomPatchCreator.SetPatchPriority(i, iPriority)

                    ' Texture point indexes

                    'pNewGeomPatchCreator.SetPatchTexturePointIndex(i, n)

                    ' Set the texture vertex pts

182:                If i = iGeomNo Then

183:                    pNewGeomPatchCreator.SetPatchTexturePointIndex(i, iTexture)

                        '' Set the top left and bottom right texture pts

                        'pWKSPt = New WKSPoint

                        'pWKSPt.X = 0

                        'pWKSPt.Y = iYfreq

                        'pNewGeomPatchCreator.SetTextureWKSPoint(iTexture, pWKSPt)

                        'iTexture += 1

                        'pWKSPt = New WKSPoint

                        'pWKSPt.X = iXfreq

                        'pWKSPt.Y = 0

                        'pNewGeomPatchCreator.SetTextureWKSPoint(iTexture, pWKSPt)

                        'iTexture += 1

                        ' Left

184:                    For iY = 0 To iYfreq

185:                        pWKSPt = New WKSPoint

186:                        pWKSPt.X = 0

187:                        pWKSPt.Y = iY

188:                        pNewGeomPatchCreator.SetTextureWKSPoint(iTexture, pWKSPt)

189:                        iTexture += 1

190:                    Next iY

                        ' Top

191:                    For iX = 0 To iXfreq

192:                        pWKSPt = New WKSPoint

193:                        pWKSPt.X = iX

194:                        pWKSPt.Y = iY

195:                        pNewGeomPatchCreator.SetTextureWKSPoint(iTexture, pWKSPt)

196:                        iTexture += 1

197:                    Next iX

                        ' Right

198:                    For iY = iYfreq To 0 Step -1

199:                        pWKSPt = New WKSPoint

200:                        pWKSPt.X = iX

201:                        pWKSPt.Y = iY

202:                        pNewGeomPatchCreator.SetTextureWKSPoint(iTexture, pWKSPt)

203:                        iTexture += 1

204:                    Next iY

                        ' Bottom

205:                    For iX = iXfreq To 0 Step -1

206:                        pWKSPt = New WKSPoint

207:                        pWKSPt.X = iX

208:                        pWKSPt.Y = iY

209:                        pNewGeomPatchCreator.SetTextureWKSPoint(iTexture, pWKSPt)

210:                        iTexture += 1

211:                    Next iX

212:                ElseIf hExistingTexturesII.ContainsKey(pGenInfo.PatchMaterialIndex(i)) Then

213:                    pNewGeomPatchCreator.SetPatchTexturePointIndex(i, iTexture)

                        ' This geometry has an existing texture. Reallocate the points

214:                    For j = 0 To pGenInfo.PatchTextureVertexCount(i) - 1

215:                        pWKSPt = New WKSPoint

216:                        pWKSPt = pGenInfo.PatchTextureVertex(i, j)

                            ' Add this point

217:                        pNewGeomPatchCreator.SetTextureWKSPoint(iTexture, pWKSPt)

218:                        iTexture += 1

219:                    Next j

220:                End If

                    ' ***** Set the geometry points *****'

                    ' Point collection type

221:                iPatchType = pGenInfo.PatchType(i)

222:                Select Case iPatchType

                        Case esriPatchType.esriPatchTypeTriangleStrip

223:                        pPtColl = New TriangleStripClass

224:                    Case esriPatchType.esriPatchTypeTriangleFan

225:                        pPtColl = New TriangleFanClass

226:                    Case esriPatchType.esriPatchTypeTriangles

227:                        pPtColl = New TrianglesClass

228:                    Case Else

229:                        pPtColl = New RingClass

230:                        End Select

231:                pGeom = pExGeomCol.Geometry(i)

232:                pPtColl = CType(pGeom, IPointCollection4)

233:                For j = 0 To pPtColl.PointCount - 1

234:                    pPt1 = New ESRI.ArcGIS.Geometry.Point

235:                    pZAware = pPt1

236:                    pZAware.ZAware = True

237:                    pPt1 = pPtColl.Point(j)

238:                    pNewGeomPatchCreator.SetPoint(n, pPt1)

                        ' Texture

                        'pNewGeomPatchCreator.SetTexturePoint(n, pPt1)

239:                    n += 1

240:                Next j

241:                If bGeomProgress = True Then ProgressBar1.Value = i

                    ' User hits stop button

242:                System.Windows.Forms.Application.DoEvents()

243:                If m_bStop = True Then

244:                    sMsg = "Aborted by user"

245:                    Exit Sub

246:                End If

                    'pNewGeomPatchCreator.SetPatchTexturePointIndex(i, k)

247:                k += iVertexCount

248:            Next i

249:            pNewMultiPatch = New MultiPatch

250:            pNewMultiPatch.SpatialReference = pSpatialRef

251:            pNewMultiPatch = pNewGeomPatchCreator.CreateMultiPatch

252:            pFeat.Shape = pNewMultiPatch

253:            pFeat.Store()

254:            pNewGeomPatchCreator.ClearResources()

255:            Marshal.ReleaseComObject(pFeat)

256:            Marshal.ReleaseComObject(pExMultiPatch)

257:            Marshal.ReleaseComObject(pNewMultiPatch)

258:        Catch ex As Exception

259:            sError = "ERROR: tileComponentGeometry; Line: " & Erl() & vbCrLf & "Layer " & sLayer & " OID = " & iOID & vbCrLf & ex.ToString

260:        Finally

261:            ProgressBar1.Visible = False

                ' Delete the texture files

262:            If pColTextureFiles.Count > 0 Then

263:                For Each sTempTextureFile In pColTextureFiles

264:                    Try

265:                        IO.File.Delete(sTempTextureFile)

266:                    Catch ex As Exception

267:                        If g_bLogging = True Then g_wLog.WriteLine(Format(Now, "hh:mm:ss") & " Error deleting file: " & sTempTextureFile & " " & ex.Message)

268:                    End Try

269:                Next sTempTextureFile

270:            End If

271:        End Try

272:    End Using

    End Sub

0 Kudos
nicogis
MVP Frequent Contributor

see my post: Multipatch

0 Kudos