Script request, center cplane on export

Next
 From:  Samuel Zeller
5461.1 
Hi,

I have a document with many variations of a single object

They are all around, none of them is centered on the origin

When I export to Cinema 4D I want them to be centered on the origin

Is there a way in MoI 3D to center the selection to the origin then export then put the selection back where it was ?

So I can export all my objects without tweaking pivots in C4D later :)
-- shapenoid.com
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  coi (MARCO)
5461.2 In reply to 5461.1 
oi there!

you mean something like this?

http://moi3d.com/forum/messages.php?webtag=MOI&msg=2409.1

ah, i see..you want this just on export.

-marco
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Michael Gibson
5461.3 In reply to 5461.1 
Hi DesuDeus, I've made a plug-in attached here called ExportCentered, does it do what you need?

It makes a copy of each object and positions the copied object at the origin, then the copied objects will be the ones that are exported and when the export is finished the copied objects are removed. So your original objects are never touched.

Note that with multiple objects each one will be positioned itself at the origin so they will be stacked up on top of each other there, but if I understand correctly that is what you want.

- Michael
Attachments:

  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Martin (MARTIN3D)
5461.4 In reply to 5461.3 
Hi Michael,
I was impressed how fast you where able to deliver such a well crafted script yesterday.

I was about to post another update of my threadmaking script but after I looked at your code I started to rewrite it. I like the elegant (but undocumented) factory.getCreatedObjects() solution you used here.

My simple test script, boolean diffs two cylinders and then another one from the result. Unfortunately the second boolean diff doesn't work therefore I assume object variables generated by sweep or boolean diff must be extracted differently. But how? Thanks for your help.

code:
	/*make cylinder 1*/
	frame = moi.vectorMath.createTopFrame();
	frame.origin = moi.vectorMath.createPoint( 0, 0, 0 );
	factory = moi.command.createFactory( 'cylinder' );
	factory.setInput( 1, frame );
	factory.setInput( 3, 30 );
	factory.setInput( 4, moi.vectorMath.createPoint( 0, 0, 60 ) );
	factory.update();
	var cyl1 = factory.getCreatedObjects();
	factory.commit();
	
	/*make cylinder 2*/
	frame = moi.vectorMath.createTopFrame();
	frame.origin = moi.vectorMath.createPoint( 0, 0, 0 );
	factory = moi.command.createFactory( 'cylinder' );
	factory.setInput( 1, frame );
	factory.setInput( 3, 60 );
	factory.setInput( 4, moi.vectorMath.createPoint( 0, 0, 30 ) );
	factory.update();
	var cyl2 = factory.getCreatedObjects();
	factory.commit();
	
	moi.ui.alert("Before first Diff");
	
	/*cyl2 minus cyl1*/
	moi.geometryDatabase.deselectAll();
	factory = moi.command.createFactory( 'booleandifference' );
	factory.setInput( 0, cyl2 );
	factory.setInput( 1, cyl1 );
	factory.setInput( 2, false );
	factory.update();
	var result = factory.getCreatedObjects(); //result doesn't work in the next diff 
	factory.commit();

	/*make cylinder 3*/
	frame = moi.vectorMath.createTopFrame();
	frame.origin = moi.vectorMath.createPoint( 25, 0, 0 );
	factory = moi.command.createFactory( 'cylinder' );
	factory.setInput( 1, frame );
	factory.setInput( 3, 30 );
	factory.setInput( 4, moi.vectorMath.createPoint( 25, 0, 30 ) );
	factory.update();
	var cyl3 = factory.getCreatedObjects();
	factory.commit();
	
	moi.geometryDatabase.selectAll();
	moi.view.resetAll();
	
	moi.ui.alert("Before second Diff");
	
	/*result minus cyl3*/
	moi.geometryDatabase.deselectAll();
	factory = moi.command.createFactory( 'booleandifference' );
	factory.setInput( 0, result );
	factory.setInput( 1, cyl3 );
	factory.setInput( 2, false );
	factory.commit();
Attachments:

  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Michael Gibson
5461.5 In reply to 5461.4 
Hi Martin,

> My simple test script, boolean diffs two cylinders and then another one from the result.
> Unfortunately the second boolean diff doesn't work therefore I assume object variables
> generated by sweep or boolean diff must be extracted differently.

It's a "race condition" / timing problem - certain factories (including booleans and sweeps) do asynchronous updates. That means that when a script calls .update() on it, what actually happens is the update is only queued up to be processed on a worker process and will be completed some time in the future. Then .update() returns and the script continues on, so in these cases that you're running into here the actual calculation done by the factory has not happened yet at the time that the script calls .getCreatedObjects(), and so it gets back no created objects.

Factories that may take a while to finish their calculations are set up with this asynchronous mechanism, it's the thing that makes the "Calculating..." message display on long calculations and prevents MoI from just looking like it is frozen while some big calculation is crunching away.


For these async factories it won't work right now to use the .update() and then .getCreatedObjects() method, you'll have to use factory.calculate() instead which is synchronous.

But I will tune this up for the next v3 beta - I've modified .getCreatedObjects() to make it automatically pause there and wait inside that function if there is an async update currently in progress for that factory. So in the next v3 beta your script there will run ok. But to make it work in the current build you'll need to use .calculate() instead.

I'll also add a factory.waitForAsyncUpdate() method as well that you can call to make a script pause until any async update for that factory is finished.

In general I'd like to try and hide the asynchronous mechanism from scripting so that it appears to the script that things are just happening in sequence by adding in built-in waiting in strategic areas like inside .getCreatedObjects() . That one just hasn't been used much so it's still in the process of working out the kinks like this. Thanks for reporting the problem, someday these things will end up working smoothly maybe.... ;)

- Michael
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Samuel Zeller
5461.6 In reply to 5461.3 
Hi Michael and thanks for the script !

It's not exactly what I need but it could be useful.

I have multiple models on my gridplane (each one has multiple objects and styles), I work like that so I can get an overview of the different variations I made of the same design (for example right now I'm working for Parmigiani Fleurier, making watch displays so I got many things on my single document. That's why I can't keep everything overlapping on the origin point)

What I need is a script that create a bounding box of the selection, pick the bottom point (centered) of it, move it to origin, export then put it back where it was and delete the bounding box :)

Thank you for your help
-- shapenoid.com
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Michael Gibson
5461.7 In reply to 5461.6 
Hi DesuDeus, I guess I'd better make sure I understand 100% this time so I can make what you actually need.

When you say create a bounding box and delete the bounding box, do you mean that you want an actual separate box object to be created so that there's a big extra box geometry additionally inserted into your export?

Or are you just talking about creating a bounding box only as an internal calculation step (not actually creating any box geometry to export) for getting the base point?

If I understand you correctly you want the entire selection to move more all together keeping the pieces in the same relative position and not move each one separately to the origin, is that the main thing that you need different from the one that I posted?

- Michael
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Martin (MARTIN3D)
5461.8 In reply to 5461.5 
Hi Michael,

is this correct?
code:
/*cyl2 - cyl1*/
moi.geometryDatabase.deselectAll();
factory = moi.command.createFactory( 'booleandifference' );
factory.setInput( 0, cyl2 );
factory.setInput( 1, cyl1 );
factory.setInput( 2, false );
var result = factory.calculate();
factory.commit();


My test script goes into a never ending Calculating... loop when it uses "result" in the next Boolean Diff factory.
Image Attachments:
Size: 97.3 KB, Downloaded: 27 times, Dimensions: 675x318px
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  bemfarmer
5461.9 In reply to 5461.8 
Does the line factory.commit(); do anything useful (or harmful) after the .calculate?
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Michael Gibson
5461.10 In reply to 5461.8 
Hi Martin, you can leave out the .commit() when you're using .calculate() instead, basically calculate() is an alternate mechanism to the update/commit mechanism.

The never ending calculating loop is because of another quirk of async factories, in order for async factories to work correctly right now objects must have unique ID value generated for them and that happens when they are added to the geometry database.

But when you call .calculate(), the objects are handed back to you and they are not automatically added to the geometry database as they are with the update/commit mechanism. So they won't be visible in the display and also won't get unique IDs assigned to them. Also when you do .calculate() there won't be any input objects removed from the geometry database automatically as well so both the adding and the removing will need to be done manually for that case.

Try this (note the additional calls after .calculate() ):

code:
	/*make cylinder 1*/
	frame = moi.vectorMath.createTopFrame();
	frame.origin = moi.vectorMath.createPoint( 0, 0, 0 );
	factory = moi.command.createFactory( 'cylinder' );
	factory.setInput( 1, frame );
	factory.setInput( 3, 30 );
	factory.setInput( 4, moi.vectorMath.createPoint( 0, 0, 60 ) );
	factory.update();
	var cyl1 = factory.getCreatedObjects();
	factory.commit();
	
	/*make cylinder 2*/
	frame = moi.vectorMath.createTopFrame();
	frame.origin = moi.vectorMath.createPoint( 0, 0, 0 );
	factory = moi.command.createFactory( 'cylinder' );
	factory.setInput( 1, frame );
	factory.setInput( 3, 60 );
	factory.setInput( 4, moi.vectorMath.createPoint( 0, 0, 30 ) );
	factory.update();
	var cyl2 = factory.getCreatedObjects();
	factory.commit();
	
	/*cyl2 minus cyl1*/
	moi.geometryDatabase.deselectAll();
	factory = moi.command.createFactory( 'booleandifference' );
	factory.setInput( 0, cyl2 );
	factory.setInput( 1, cyl1 );
	factory.setInput( 2, false );
	var result = factory.calculate();
	moi.geometryDatabase.addObjects( result );
	moi.geometryDatabase.removeObjects( cyl2 );
	moi.geometryDatabase.removeObjects( cyl1 );

	/*make cylinder 3*/
	frame = moi.vectorMath.createTopFrame();
	frame.origin = moi.vectorMath.createPoint( 25, 0, 0 );
	factory = moi.command.createFactory( 'cylinder' );
	factory.setInput( 1, frame );
	factory.setInput( 3, 30 );
	factory.setInput( 4, moi.vectorMath.createPoint( 25, 0, 30 ) );
	factory.update();
	var cyl3 = factory.getCreatedObjects();
	factory.commit();
	
	moi.geometryDatabase.selectAll();
	moi.view.resetAll();
	
	/*result minus cyl3*/
	moi.geometryDatabase.deselectAll();
	factory = moi.command.createFactory( 'booleandifference' );
	factory.setInput( 0, result );
	factory.setInput( 1, cyl3 );
	factory.setInput( 2, false );
	factory.commit();
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Michael Gibson
5461.11 In reply to 5461.8 
Tomorrow I'll try to take a look and see what's involved in making "loose" (meaning not actually a part of the geometry database) objects work as input into async factories, maybe I can also get that tuned up to work.

- Michael
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Samuel Zeller
5461.12 In reply to 5461.7 
"When you say create a bounding box and delete the bounding box, do you mean that you want an actual separate box object to be created so that there's a big extra box geometry additionally inserted into your export?"

No

"Or are you just talking about creating a bounding box only as an internal calculation step (not actually creating any box geometry to export) for getting the base point?"

Exactly :)

"If I understand you correctly you want the entire selection to move more all together keeping the pieces in the same relative position and not move each one separately to the origin"

Spot on :D
-- shapenoid.com
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Martin (MARTIN3D)
5461.13 In reply to 5461.10 
Ha, now it works perfectly :-) and your explanations make sense to me. Thanks a lot.

>Tomorrow I'll try to take a look and see what's involved in making "loose" (meaning not actually a part of the geometry database) objects work as input into async factories, maybe I can also get that tuned up to work.

That would mean that, when the script makes a thread for example, the profile and helix created using just .calculate()) will never appear? Also the cutter object and the cylinder would just be .calculated() in the background and just the finished thread pops up after some time like magic?
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Martin (MARTIN3D)
5461.14 In reply to 5461.13 
Two observations:
When using this var = factory.calculate() method for sweep and boolean diff

a) the "Calculating ..." message doesn't apear
b) the calculation terminates after 90 s. It seems that this certain JavaScript protection also kicks in here.
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Michael Gibson
5461.15 In reply to 5461.12 
Hi DesuDeus, please try the attached ExportCentered2 command, hopefully it does what you were wanting.

- Michael
Attachments:

  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Michael Gibson
5461.16 In reply to 5461.13 
Hi Martin,

> That would mean that, when the script makes a thread for example, the profile and helix
> created using just .calculate()) will never appear? Also the cutter object and the cylinder
> would just be .calculated() in the background and just the finished thread pops up after
> some time like magic?

Well by the "fixing it" part I meant that I'll see if I can get loose objects (objects that are only referenced by the script engine itself and not added into MoI's geometry database) to work ok as input objects into async factories.

What I was referring to there would not change the behavior of when things appear on screen or not.

And yes, when you use the .calculate() method the result returned back will not by itself automatically appear on the screen - that's because the returned object is only referenced in that case by the script engine - when MoI redraws the screen the things that are drawn are all the stuff that's in it's geometry database, so if you want to have an object actually displayed you need to add it to the geometry database, just adding it will trigger a screen redraw.


> When using this var = factory.calculate() method for sweep and boolean diff
>
> a) the "Calculating ..." message doesn't apear
> b) the calculation terminates after 90 s. It seems that this certain JavaScript protection also kicks in here.

Yes, the .calculate() method is synchronous, it runs directly on the main thread and does not use the worker process mechanism. So that means no "Calculating..." message and also MoI will appear frozen while it is crunching away. It could very well be triggering the script timeout because of that as well, but with the next v3 beta that script timeout will be removed so hopefully that limit will go away with it.

But also in the next v3 beta you will not be forced to use .calculate(), that other .getCreatedObjects() method will pause the script until the async update is complete so with the next v3 release that method you were using previously will work ok with async factories.

- Michael
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Martin (MARTIN3D)
5461.17 In reply to 5461.16 
Thanks Michael, I understood that you are just looking. Anyway I went back to my old method. The script is more reliable and - very important - it also works in older MoI versions.
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Samuel Zeller
5461.18 In reply to 5461.15 
Hi,

Tried ExportCentered2

Two things are not working.

1. Once the export in 3DM is done it doesn't revert the centered model (I need to cmd+Z)

2. It doesn't work if I try to output an OBJ, it doesn't display the meshing settings

I need this script specially for exporting to OBJ -> Cinema 4D :)
-- shapenoid.com
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
 From:  Michael Gibson
5461.19 In reply to 5461.18 
Hi DesuDeus, I just tested ExportCentered2 over here both in Windows and Mac versions and I can't reproduce any of those problems.

How are you installing and running it? Make sure that you are placing it into the \commands folder and to trigger it put in only: ExportCentered2 as the command name, nothing else like "script:" for this case.

- Michael
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged
 

Reply to All Reply to All