anomalaus last edited by anomalaus
@fbs7 have you made progress on transferring material trees? I have developed Python routines which can save and load pose, character and scene files to and from the library, bypassing Poser's own load and save routines, but have yet to implement the material tree creation. It's been a while since I last looked at it, but IIRC I found something missing from the Python materials API which meant I couldn't just create all the nodes and trees. I'll have another look, but the simplest solution for transferring materials may end up being just save from the field prop and reload them from the library onto the metaball prop(s).
@fbs7 would you like me to see whether the Mac version is less prone to the crashes you are experiencing? I'm quite happy to bulk the think up with debugging statements, and I have unbuffered logging routines that write to an external file which can be externally monitored in real time, so Poser crashing won't prevent any of the previously issued logging being swallowed by the output buffering.
That's a good idea. Try these two scripts, if you would. This one is "Create Metaball.py":
import poser from numpy import oldnumeric # # This script creates a cube to limit an isosurface, and a handler for a metaball # fbs 12/7/2017 # # Check if 'IsoField' already exists, if not create one scene = poser.Scene() try: isoField = scene.Actor('IsoField') except: # Vertices of a cube c = 1.0 # Cube size verts = oldnumeric.array( [[0,0,0],[0,0,c],[0,c,0],[0,c,c],[c,0,0],[c,0,c],[c,c,0],[c,c,c]] ) # Sets = vertex indexes sets = numpy.array( [0,1,3,2, 0,4,5,1, 0,2,6,4, 7,5,4,6, 7,3,1,5, 7,6,2,3] ) # Polys = faces, index to sets polys = oldnumeric.array( [[0,4],[4,4],[8,4],[12,4],[16,4],[20,4]] ) # Create the geometry meshGeom = poser.NewGeometry() meshGeom.AddGeneralMesh( polys, sets, verts ) # Create the prop isoField = scene.CreatePropFromGeom(meshGeom,'IsoField') # Set draw style to wireframe isoField.SetDisplayStyle( poser.kDisplayCodeWIREFRAME ) # End Frame parmEndFrame = isoField.CreateValueParameter('End Frame') parmEndFrame.SetValue(30) parmEndFrame.SetMinValue(1) parmEndFrame.SetSensitivity(1) parmEndFrame.SetForceLimits(1) # Start Frame parmStartFrame = isoField.CreateValueParameter('Start Frame') parmStartFrame.SetValue(1) parmStartFrame.SetMinValue(1) parmStartFrame.SetSensitivity(1) parmStartFrame.SetForceLimits(1) # Resolution parmResolution = isoField.CreateValueParameter('Resolution') parmResolution.SetValue(10) parmResolution.SetMinValue(1) parmResolution.SetMaxValue(20) parmResolution.SetSensitivity(1) parmResolution.SetForceLimits(1) # Threshold parmThreshold = isoField.CreateValueParameter('Threshold') parmThreshold.SetValue(1) scene.DrawAll() # Find the smallest N that 'MetaBallN' does not already exist as children of the iso field childList = isoField.Children() found = 0 for n in xrange(1,101): metaBallName = u'MetaBall' + str(n) # Poser needs Unicode found = 0 for child in childList: if child.Name() == metaBallName: found = 1 break if found == 0: break # Now let's create a metaball handler; it will be a little cube; code is the same as above c = 0.01 verts = oldnumeric.array( [[0,0,0],[0,0,c],[0,c,0],[0,c,c],[c,0,0],[c,0,c],[c,c,0],[c,c,c]] ) - c/2 sets = oldnumeric.array( [0,1,3,2, 0,4,5,1, 0,2,6,4, 7,5,4,6, 7,3,1,5, 7,6,2,3] ) polys = oldnumeric.array( [[0,4],[4,4],[8,4],[12,4],[16,4],[20,4]] ) # Create the geometry meshGeom = poser.NewGeometry() meshGeom.AddGeneralMesh( polys, sets, verts ) # Create the prop and make it a child of isoField metaBall = scene.CreatePropFromGeom(meshGeom,metaBallName ) parmStickness = metaBall.CreateValueParameter('Stickness') parmStickness.SetValue(2.0) metaBall.SetParent(isoField, 0, 0) parmStrength = metaBall.CreateValueParameter('Strength') parmStrength.SetValue(5.0) # Position the prop in the middle of the iso field geom = isoField.Geometry() vertex7 = geom.Vertex(7) sX = vertex7.X() sY = vertex7.Y() sZ = vertex7.Z() metaBall.SetParameter('xTran',sX/2) metaBall.SetParameter('yTran',sY/2) metaBall.SetParameter('zTran',sZ/2) # All done; now we have a the cube for the iso field, and a smaller cube to center metaballs in that field
hmm... can't post Run Metaballs.py; too large; and can't attach .txt or .py either...
let's see if I can find some file sharing service somewhere
@fbs7 I use DropBox
Try this guy:
Now, these crashes are sporadic. In my last test it took some 3 hours of continuous running and some 20 simulations to get it to crash, so it's not like it runs once and crashes. Some people might live with a crash in 3 hours, but that's not good enough.
I've disabled some aspects of it to see if the crashes would go away, so testing will have to be in a particular sequence.
(a) Start from blank document
(b) Execute "Create Metaball" 3 times; it will create a big wireframe box and 3 small boxes one on top of the other
(c) At frame 1, separate the 3 small boxes into 3 positions within the big wireframe
(d) Check the big frame "isoField" properties; set threshold=1, resolution=20, start frame=1, end frame=20
(e) Check the small boxes "Metaball n" properties; set strength=1.0, stickness=2.0
(d) At frame 20, move the metaballs to other positions, rotate and scale them, can change the field strength (a field strength=10 means the metaball diameter covers the whole field, =1 means its diameter is 10% of the field), change stickness slightly (stickness=2 means it will stick to other metaballs up to 2x of its radius away)
(e) Save the file so you don't have to redo this again
(f) Execute "Run Metaballs"; once it says "Generate mesh frame 20" it's done; then click on Play to play the animation
(g) repeat (d) to (f); eventually it will crash
Thanks for the help!
@fbs7 first problem is numpy namespace definition
Traceback (most recent call last): File "/Applications/Poser 11/Runtime/Python/poserScripts/ScriptsMenu/Partners/FBS/Create Metaball.py", line 19, in <module> sets = numpy.array( [0,1,3,2, 0,4,5,1, 0,2,6,4, 7,5,4,6, 7,3,1,5, 7,6,2,3] ) NameError: name 'numpy' is not defined
I'll try just:
Hmm.. how odd; that works ok for me; I took that import from one of the samples in PP11, but some of these samples look broken
Actually, scrap that; that was my typo; I copying stuff to the Python script a bit ago and touched that line; please chaneg to this
# Sets = vertex indexes sets = oldnumeric.array( [0,1,3,2, 0,4,5,1, 0,2,6,4, 7,5,4,6, 7,3,1,5, 7,6,2,3] )
Anomalous, have you tried anything about using that SetGeometry() little monster to set a dynamic geometry?
If that thing worked reliably, then it would be easy to manipulate any geometry dynamically. Just bake it in memory, and do the switcharoo in an appropriate callback.
For example, one could do 3D Join and Minus operations with solids, or switch figures with a reduced poly version of them for faster preview.
@fbs7 OK, that explains that, I had success just importing numpy, but none of my other scripts did any more than oldnumeric.
First crash report: Segmentation fault
Looks like memory (mis)management, for which Poser is renowned (or at least some of the libraries they are forced to use, if not actual SMS code).
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 SMArtSkinBase.dylib ... MEM_IsMemBlock + 9
1 SMArtSkinBase.dylib ... GEOM_VerifyAndFix(GEOM*) + 28
2 com.SmithMicro.Poser ... PEActor3D::SetGeom(GEOM*, VERTEX*, bool, BArray<long>) + 384
3 com.SmithMicro.Poser ... setGeometry(actorObject, _object*) + 267
Had run Create Metaball.py (with import numpy), and changed the metaBall1 strength from 5.0 to 1.0, yScale from 100 to 50% and xScale from 100 to 200% at frame 30.
Ran 'Run Metaballs.py' which created the isoSurfaces, clicked Run and got through 2 cycles of frames before Poser crashed.
The previous iteration, I had made no metaball parameter changes and Poser cycled through all of the identical isoSurfaces without any crashing, so it definitely looks like a problem with memory management. Whether this can be worked around, I am unsure. Perhaps, as you suggested, cycling the visibility of a series of once created props will be an interim solution. I'd definitely be reporting this kind of memory fault to SMS, though. Once you've sent your report in, I can follow up with mine, so they know it's across platforms and focus on how SetGeom() garbage collection happens.
@fbs7 I have not played with "dynamic" geometry since I changed my figures from Poser Traditional to Unimesh, and noticed that Geometry switching no longer worked for body parts.
The only other time I've used SetGeometry() was when trying to modify an existing mesh tesselation routine to preserve the UV mapping of existing vertices and interpolate the UV mapping for the new tesselation vertices.
If anything, I think the Mac platform is less robust than Windows, where Poser memory management is concerned. Though, I guess the pendulum swings occasionally.
Oh.. that's a pretty nice stack trace you got there. You always get tht in the Mac, or do you use an external tool to get it?
In Windows I only get "Your application has crashed, dummy! Do you want to find a solution at Microsoft?" or something like that
Hmmm... sooo... if that's indeed in SetGeometry... maybe that means that the list I use to keep geometries has been reclaimed, but I'm still keeping a pointer to it... hmm...
Time to check the inner workings of memory management and object lifecycle in Python.
@fbs7 the stack trace is a very useful feature of MacOS, though the trace probably only gets sent to Apple (I'd love them to all be automatically sent to SMS, so they'd get real-time feedback of what the poor Poser slobs have to go through.
@fbs7 just to clarify, I did not have to resort to your full suggested list of actions to induce Poser to crash. Just these:
(a) Start from blank document (I have a New Construct scene without Andy, which I load, replacing the default scene).
(b) Executed "Create Metaball.py" just once.
(f) Executed "Run Metaballs.py"; it generated 30 frames. Turned off skip frames. Clicked play, and waited till I got bored with unchanging, identical isoSurfaces before terminating the loop.
(d-2nd) Changed the metaball1 strength from 5.0 to 1.0, xScale from 100% to 200%, yScale from 100% to 50% at frame 30.
(g) Re-executed "Run Metaballs.py" and clicked play when it had regenerated to 30 frames. Got through 2-3 iterations of the 30 frame loop before Poser crashed.
So, it seems to me that the Mac platform is more prone to memory management issues that PC. BTW, I have 32GB RAM, and I can guarantee that there is absolutely no way Poser was using all of that, so it's probably not a recursion problem, but may be an inaccurate memory allocation issue. I very frequently see Poser crashes with attempts to free unallocated pointers.
Wow, that's pretty neat!!
A beautiful stack trace, indeed; one could even get a glimpse of what Poser is doing by forcing these exceptions!
movie loop -> computer scene transformations (probably a camera thingie) -> apply parameters to actors -> calculate local matrices for the actors -> (grabs in our callback) -> set geometry -> crash
Maybe we really can't call SetGeometry() within any of the callbacks... but at the very bottom of the trace it seems it's handling some event... let's see if there's some undocumented event callback that shows when a frame has changed... hmm....
Hmm.. check this:
def eventCallback(scene, code): if code <> 16: print 'Code = ',code ... scene.SetEventCallback(eventCallback)
It will display a continuous series of code = 16, even when nothing's happening. No idea yet what is that 16. Whenever you change frames manually, it sends a code = 17.
So, 1 = kEventCodeKEYSCHANGED, 16 = undocumented... but 16 keeps happening all the time, so it must be Draw or something like that. Let's see how the thing behaves if I hook on event = 16, haha...
@fbs7 from my Poser Pro 22.214.171.124338 Python 2.7.2 Shell
>>> poser.kEventCodeACTORADDED 64 >>> poser.kEventCodeACTORDELETED 4 >>> poser.kEventCodeACTORSELECTIONCHANGED 8 >>> poser.kEventCodeANIMSETSCHANGED 4096 >>> poser.kEventCodeITEMRENAMED 256 >>> poser.kEventCodeKEYSCHANGED 1 >>> poser.kEventCodePARMADDED 128 >>> poser.kEventCodePARMDELETED 32 >>> poser.kEventCodeSCENECLOSING 1048576 >>> poser.kEventCodeSETUPMODE 8192
Looking at one of @bagginsbill 's Parmatic scripts, he uses the explicit constant 16 and it's bitwise inverse ~16 in his event decoding callback, so yes, it's undocumented. My guess would be it coincides with a "ProcessSomeEvents" or idle moment.