particlebounds.py (6745B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\trinutils\particlebounds.py 2 from __future__ import absolute_import 3 import logging 4 import greatergranny.grannyutils as grannyutils 5 import remotefilecache 6 import uthread2 as ut 7 import trinutils.trinparser as trinparser 8 import yamlext 9 try: 10 import blue 11 import trinity 12 import geo2 13 except ImportError: 14 trinity = None 15 blue = None 16 geo2 = None 17 18 logger = logging.getLogger(__name__) 19 20 def YamlStrToTrinObj(yamlstr): 21 trinobj = trinparser.DictToTrinityParser(yamlext.loads(yamlstr)) 22 trinity.WaitForResourceLoads() 23 return trinobj 24 25 26 class MeshLoadError(Exception): 27 28 def __init__(self, meshpath): 29 msg = 'Mesh failed to load: %s' % meshpath 30 Exception.__init__(self, msg) 31 32 33 def HasParticleSystem(node): 34 psys = node.Find('trinity.Tr2ParticleSystem') 35 if psys: 36 return True 37 return False 38 39 40 def _GetMaxPartSize(et): 41 if not et.mesh.geometry.isGood: 42 raise MeshLoadError(et.mesh.geometryResPath) 43 geoSize = et.mesh.geometry.GetBoundingBox(0) 44 gs = geo2.Vec3Distance(geoSize[0], geoSize[1]) 45 for em in et.Find('trinity.Tr2DynamicEmitter'): 46 for each in em.generators: 47 if each.name == 'sizeDynamic' or each.name == 'size': 48 return max(each.minRange + each.maxRange) * gs 49 50 for em in et.Find('trinity.Tr2StaticEmitter'): 51 for ps in em.Find('trinity.Tr2ParticleSystem'): 52 for each in ps.elements: 53 if each.name == 'size': 54 remotefilecache.prefetch_single_file(em.geometryResourcePath) 55 return grannyutils.GetMaxPartSize(blue.paths.ResolvePath(em.geometryResourcePath), each.usageIndex, em.meshIndex) * gs 56 57 logger.warning('No Particle Emitters found for %s' % et.name) 58 59 60 class ParticleBoundsSimulation(object): 61 62 def __init__(self, trinobj, pumpBlue = False, passes = 2, time = 3.0): 63 trinity.WaitForResourceLoads() 64 self._passes = passes 65 self._time = time 66 self.redNodeMutated = trinobj.CopyTo() 67 self.redNodeCopy = trinobj.CopyTo() 68 self.systems = self.redNodeMutated.Find('trinity.Tr2ParticleSystem') 69 self.curveSets = self.redNodeMutated.Find('trinity.TriCurveSet') 70 self.activeIndex = [0] 71 self._ets = [] 72 self._staticMeshes = [] 73 self.started = [False] 74 self._pumpBlue = pumpBlue 75 self._CollectMeshes() 76 77 def _CollectMeshes(self): 78 79 def _FilterMesh(et): 80 return isinstance(et.mesh, trinity.Tr2InstancedMesh) and ('unit_plane' or 'unitplane' in et.mesh.geometryResPath) 81 82 def _CollectTransforms(tf, indices): 83 if _FilterMesh(tf): 84 if isinstance(tf.mesh.instanceGeometryResource, trinity.TriGeometryRes): 85 self._staticMeshes.append(tf.mesh) 86 else: 87 self._ets.append({'et': tf, 88 'mesh': tf.mesh, 89 'min': (0.0, 0.0, 0.0), 90 'max': (0.0, 0.0, 0.0), 91 'partSize': _GetMaxPartSize(tf) / 2, 92 'hierarchy': indices}) 93 for ci in range(len(tf.children)): 94 child = tf.children[ci] 95 clst = list(indices) 96 clst.append(ci) 97 _CollectTransforms(child, clst) 98 99 for ci in range(len(self.redNodeMutated.children)): 100 child = self.redNodeMutated.children[ci] 101 _CollectTransforms(child, [ci]) 102 103 def GetTrinobj(self): 104 self.RunSimulation() 105 self.FixPSBB() 106 self._EnableParticleSorting() 107 self._UpdateStaticBoundingBoxes() 108 return self.redNodeCopy 109 110 def _UpdateStaticBoundingBoxes(self): 111 for each in self._staticMeshes: 112 self._UpdateStaticBoundingBox(each) 113 114 def _UpdateStaticBoundingBox(self, mesh): 115 geoSize = mesh.instanceGeometryResource.GetBoundingBox(0) 116 size = grannyutils.GetMaxPartSize(blue.paths.ResolvePath(mesh.instanceGeometryResPath), 0, mesh.meshIndex) / 2 117 mesh.minBounds = (geoSize[0][0] - size, geoSize[0][1] - size, geoSize[0][2] - size) 118 mesh.maxBounds = (geoSize[1][0] + size, geoSize[1][1] + size, geoSize[1][2] + size) 119 120 def _PumpBlue(self): 121 while self._pumpBlue: 122 blue.os.Pump() 123 ut.Yield() 124 125 def _EnableParticleSorting(self): 126 for ps in self.systems: 127 ps.requiresSorting = True 128 129 def _GetRedNodeCopyTransform(self, transformEntry): 130 indices = transformEntry['hierarchy'] 131 tf = self.redNodeCopy 132 for i in indices: 133 tf = tf.children[i] 134 135 return tf 136 137 def FixPSBB(self): 138 for d in self._ets: 139 mps = d['partSize'] 140 tf = self._GetRedNodeCopyTransform(d) 141 tf.mesh.minBounds = [d['min'][0] - mps, d['min'][1] - mps, d['min'][2] - mps] 142 tf.mesh.maxBounds = [d['max'][0] + mps, d['max'][1] + mps, d['max'][2] + mps] 143 144 def AccumulateBounds(self): 145 for d in self._ets: 146 ps = d['mesh'].instanceGeometryResource 147 d['max'] = max(ps.aabbMax, d['max']) 148 d['min'] = min(ps.aabbMin, d['min']) 149 150 def RunSimulation(self): 151 trinity.settings.SetValue('frustumCullingDisabled', 1) 152 trinity.settings.SetValue('eveSpaceSceneVisibilityThreshold', 0) 153 trinity.settings.SetValue('eveSpaceSceneLowDetailThreshold', 0) 154 trinity.settings.SetValue('eveSpaceSceneMediumDetailThreshold', 0) 155 trinity.settings.SetValue('eveSpaceSceneLODFactor', 0) 156 ut.StartTasklet(self._PumpBlue) 157 from . import sceneutils 158 scene = sceneutils.GetOrCreateScene() 159 scene.objects.append(self.redNodeMutated) 160 self._EnableParticleSorting() 161 rj = trinity.CreateRenderJob('CallbackJob') 162 projection = trinity.TriProjection() 163 projection.PerspectiveFov(1, 1, 1, 10000000) 164 rj.steps.append(trinity.TriStepSetProjection(projection)) 165 view = trinity.TriView() 166 view.SetLookAtPosition((50000, 0, 0), (0, 0, 0), (0, 1, 0)) 167 rj.steps.append(trinity.TriStepSetView(view)) 168 rj.steps.append(trinity.TriStepUpdate(scene)) 169 rj.steps.append(trinity.TriStepRenderScene(scene)) 170 rj.steps.append(trinity.TriStepPythonCB(self.AccumulateBounds)) 171 rj.ScheduleRecurring() 172 for i in range(self._passes): 173 self.activeIndex[0] = i 174 for cs in self.curveSets: 175 cs.Play() 176 177 for sys in self.systems: 178 sys.ClearParticles() 179 180 self.started[0] = True 181 ut.SleepSim(self._time) 182 183 rj.UnscheduleRecurring() 184 self._pumpBlue = False