root/trunk/RBRapier/RBRapier/Formats/Wavefront/MeshedObject.py

Revision 702, 9.5 kB (checked in by sholloway, 5 years ago)

Added GL prefix to Execute/Select/Deselect

Line 
1 #!/usr/bin/env python
2 ##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3 ##~ License
4 ##~
5 ##- The RuneBlade Foundation library is intended to ease some
6 ##- aspects of writing intricate Jabber, XML, and User Interface (wxPython, etc.)
7 ##- applications, while providing the flexibility to modularly change the
8 ##- architecture. Enjoy.
9 ##~
10 ##~ Copyright (C) 2002  TechGame Networks, LLC.
11 ##~
12 ##~ This library is free software; you can redistribute it and/or
13 ##~ modify it under the terms of the BSD style License as found in the
14 ##~ LICENSE file included with this distribution.
15 ##~
16 ##~ TechGame Networks, LLC can be reached at:
17 ##~ 3578 E. Hartsel Drive #211
18 ##~ Colorado Springs, Colorado, USA, 80920
19 ##~
20 ##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21
22 """Uses Loader and Renderer to describe a meshed object"""
23
24 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 #~ Imports
26 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27
28 import weakref
29
30 import Loader
31
32 from RBRapier.Tools.Geometry.Analysis import TriangleLister
33 from RBRapier.Tools.Geometry.Analysis import TriangleStripifier
34 from RBRapier.Tools.Geometry.Analysis import TriangleMesh
35 from RBRapier.Tools.Geometry.Analysis import LocalityRemapper
36 from RBRapier.Tools.Geometry.ConvexPolygonTesselation import TesselateConvexPolygon
37
38 from RBRapier.Renderer.Geometry import VertexArrays
39 from RBRapier.Renderer.Geometry import ArrayTraversal
40 from RBRapier.Renderer import SequenceMgr
41
42 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
43 #~ Definitions
44 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
45
46 class GeoObject(SequenceMgr.Sequence):
47     class GeoSubGroup(object):
48         def __init__(self, geoobj, name):
49             self.Traversals = []
50             self.geoobj = weakref.proxy(geoobj)
51             self.name = name
52
53         def AddTraversal(self, traversal):
54             self.Traversals.append(traversal)
55             self.geoobj.AddElement(traversal)
56
57         def LoadFinalized(self):
58             pass
59
60     def SetVertices(self, Vertices):
61         try: self.RemoveElement(self.Vertices)
62         except AttributeError: pass
63         self.Vertices = Vertices
64         self.AddElement(self.Vertices.GLSelect, -1)
65
66     def SetNormals(self, Normals):
67         try: self.RemoveElement(self.Normals)
68         except AttributeError: pass
69         self.Normals = Normals
70         self.AddElement(self.Normals.GLSelect, -1)
71
72     def SetTextureCoords(self, TexCoords):
73         try: self.RemoveElement(self.TexCoords)
74         except AttributeError: pass
75         self.TexCoords = TexCoords
76         self.AddElement(self.TexCoords.GLSelect, -1)
77
78     def AddGroup(self, name):
79         group = self.GeoSubGroup(self, name)
80         try: self.Groups.append(group)
81         except AttributeError:
82             self.Groups = [group]
83         return group
84
85     def LoadFinalized(self):
86         pass
87
88 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
89
90 class MeshedObjectBuilder(object):
91     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
92     #~ Constants / Variables / Etc.
93     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
94
95     GeoObjectFactory = GeoObject
96     IndexedTraversal = ArrayTraversal.IndexedCollectionTraversal
97
98     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
99     #~ Public Methods
100     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
101
102     def Build(self, FileInFormat, optimizetraversal=1, optimizemesh=3):
103         self.Load(FileInFormat)
104         self.Process(optimizetraversal, optimizemesh)
105         result = self.GeoObjectFactory()
106
107         result.SetVertices(self.Vertices)
108         if self.Normals:
109             result.SetNormals(self.Normals)
110         if self.TexCoords:
111             result.SetTextureCoords(self.TexCoords)
112
113         if self.FormatGroups:
114             for Group in self.FormatGroups:
115                 resultgroup = result.AddGroup(Group.Names[0])
116                 for each in Group.Traversals.itervalues():
117                     resultgroup.AddTraversal(each)
118                 resultgroup.LoadFinalized()
119
120         result.LoadFinalized()
121         return result
122
123     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
124     #~ Public Utilities
125     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
126
127     def Process(self, optimizetraversal=1, optimizemesh=3):
128         if optimizemesh > 0:
129             self.OptimizeMesh(optimizemesh)
130         elif optimizemesh == 0:
131             self.SimpleMesh()
132         if optimizetraversal > 0:
133             self.OptimizeTraversals(optimizetraversal)
134         elif optimizetraversal == 0:
135             self.SimpleTraversals()
136
137     def Load(self, FileInFormat):
138         obj = Loader.WavefrontOBJLoader()
139         obj.ReadFormat(FileInFormat)
140
141         if obj.OffsetIndicesDetected:
142             from Tools import IndexOffsetRemapping
143             IndexOffsetRemapping.RemapOffsetIndices(obj)
144
145         self.Name = obj.Name or FileInFormat.name
146         self.Vertices = obj.Vertices and VertexArrays.VertexArray(obj.Vertices) or None
147         self.Normals = obj.Normals and VertexArrays.NormalArray(obj.Normals) or None
148         self.TexCoords = obj.TexCoords and VertexArrays.asarray(obj.TexCoords) or None
149         self.FormatGroups = obj.Groups
150
151     def SimpleMesh(self):
152         TriLister = TriangleLister.TriangleLister()
153         self.TraverseMesh(TriangleMesh.FaceMesh, TriLister)
154
155     def OptimizeMesh(self, level):
156         TriStripifier = TriangleStripifier.TriangleStripifier()
157         TriStripifier.GLSelector = TriangleStripifier.ExperimentGLSelector(level, 3)
158         self.TraverseMesh(TriangleMesh.FaceEdgeMesh, TriStripifier)
159
160     def TraverseMesh(self, MeshFactory, TraversalMaker):
161         for Group in self.FormatGroups:
162             if not Group.Faces:
163                 Group.Traversals = {}
164             else:
165                 mesh = MeshFactory()
166                 for FaceTraversal in Group.Faces:
167                     FaceTraversal = TesselateConvexPolygon([idx[0] for idx in FaceTraversal])
168                     for each in FaceTraversal:
169                         face = mesh.AddFace(*each)
170                 #if __debug__:
171                 #    print '%-20s[%6d]: ' % (Group.Names[0], len(mesh.Faces)*3),
172                 #    Group.Traversals = dict(TraversalMaker(mesh, OnProgress=TriangleStripifier.PrintOnProgress(0)))
173                 #    print " [",
174                 #    for name, each in Group.Traversals.iteritems():
175                 #        try:
176                 #            count = 0
177                 #            maxcount = 0
178                 #            for e in each:
179                 #                count += len(e)
180                 #                maxcount = max(maxcount, len(e))
181                 #            print '%s=%d (%d, %1.1f, %d),' % (name, len(each), count, count/float(len(each) or 1.), maxcount),
182                 #        except TypeError:
183                 #            print '%s=%d (%d),' % (name, 1, len(each)),
184                 #    print "]"
185                 #else:
186                 #    Group.Traversals = dict(TraversalMaker(mesh))
187                 Group.Traversals = dict(TraversalMaker(mesh))
188
189     def SimpleTraversals(self):
190         for Group in self.FormatGroups:
191             listdata = Group.Traversals.get('list')
192             if listdata:
193                 Group.Traversals['list'] = self.IndexedTraversal('trilist', [listdata])
194
195             fandatacollection = Group.Traversals.get('fan')
196             if fandatacollection:
197                 Group.Traversals['fan'] = self.IndexedTraversal('tristrip', fandatacollection)
198
199             stripdatacollection = Group.Traversals.get('strip')
200             if stripdatacollection:
201                 Group.Traversals['strip'] = self.IndexedTraversal('tristrip', stripdatacollection)
202
203     def OptimizeTraversals(self, level):
204         optimizer = LocalityRemapper.LocalityRemapper(len(self.Vertices.data))
205
206         for Group in self.FormatGroups:
207             listdata = Group.Traversals.get('list')
208             if listdata:
209                 optimizer.Visit(listdata)
210                 Group.Traversals['list'] = self.IndexedTraversal('trilist', [listdata])
211             elif listdata is not None:
212                 del Group.Traversals['list']
213
214             fandatacollection = Group.Traversals.get('fan')
215             if fandatacollection:
216                 for fandata in fandatacollection:
217                     optimizer.Visit(fandata)
218                 Group.Traversals['fan'] = self.IndexedTraversal('tristrip', fandatacollection)
219             elif fandatacollection is not None:
220                 del Group.Traversals['fan']
221
222             stripdatacollection = Group.Traversals.get('strip')
223             if stripdatacollection:
224                 for stripdata in stripdatacollection:
225                     optimizer.Visit(stripdata)
226                 Group.Traversals['strip'] = self.IndexedTraversal('tristrip', stripdatacollection)
227             elif stripdatacollection is not None:
228                 del Group.Traversals['strip']
229
230         if self.Vertices: optimizer.RemapIndices(self.Vertices.data)
231         if self.Normals: optimizer.RemapIndices(self.Normals.data)
232         if self.TexCoords: optimizer.RemapIndices(self.TexCoords.data)
233
234 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
235 #~ Testing
236 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
237
238 if __name__=='__main__':
239     print "Testing..."
240     import doctest
241     #import MODULE as _testmod
242     #doctest.testmod(_testmod)
243
244     test = MeshedObjectBuilder()
245     obj = test.Build(open('data/shuttle.obj', 'r'))
246     #obj = test.Build(open('data/cessna.obj', 'r'))
247     #obj = test.Build(open('data/oldtree.obj', 'r'))
248     #obj = test.Build(open('data/porsche.obj', 'r'))
249     #obj = test.Build(open('data/soccerball.obj', 'r'))
250     #obj = test.Build(open('data/sword.obj', 'r'))
251     print "Test complete."
252
253
Note: See TracBrowser for help on using the browser.