Multiple extrusion script

Discussions concerning programming of SOFTIMAGE©
pgeissler
Posts: 7
Joined: 05 Jul 2013, 14:45

Multiple extrusion script

Post by pgeissler » 13 Aug 2013, 10:09

Hi,

I'm working on a script (JScript) that create some extrusions from a polygon to get this kind of result:

Image

In this scene, i started from a sphere and perform a 5-stage extrusion with an angle of 90° and a distance of 10. The first object (tagged "1" on the picture) is the center of "rotation". The second object (tagged "2") is used to get the relative plan from the selected quad

The problem is to get a realtime visualisation, in other term, create the extrusions, and destroy it to re-create all with new parameters. I have a PPG inspector with these parameters, and the user is able to select the value he want. To get a realtime visualisation, i need to undo all the previous operations. I've tried:

- Undoing all the extrusions with a loop of "Undo (null);". It doesn't work because when the user modify a value in the PPG, it's undoed too.
- Growing selection and delete all the extrusions: i can't find a way to cap the hole without having to pick a vertex or the edges and cap it manually.
- Saving the operations in an array to delete them and get the initial polymesh: i can't access a global variable in the PPG callback (when changing a value in the inspector of the script). It's seem to be a pure JScript problem because of how the PPG system work. And the DuplicateMeshComponent function (used to get an extrusion on the current polygon) doesn't seem to return
a reference to the corresponding operation on the XSI explorer, so i can't do a "DeleteObj(MyOperation);".

Here is the code. you can create a new scene with a sphere, select a polygon and run the script, and just hitting "OK" to get the same result i have posted before. It doesn't work on some angles but it's another problem. If you try to change the distance value, the extrusions will be added again and again, giving a funny result but not really what we want :)

Code: Select all


onGUI();


function onGUI()
{
		if(!isAlreadyOpened()){
		
			var oPSet = CreatePSet() ;
			
			var oLayout = oPSet.PPGLayout;
		
			oLayout.Logic =OnInit.toString()+
							CreateLayout.toString()+
							onValide_OnClicked+
							PivotDistance_OnChanged.toString()+
							PivotAngle_OnChanged.toString()+
							HingeAngle_OnChanged.toString()+
							HingeStage_OnChanged.toString()+
							AngleCornet_OnChanged.toString()
							
							;
							//Close_OnClicked.toString();
							
			oLayout.Language = "JScript" ;
			
		}
		else
		{
			DeleteObj("Hingeissler");
			var oPSet = CreatePSet() ;
			
			var oLayout = oPSet.PPGLayout;
		
			oLayout.Logic =OnInit.toString()+
							CreateLayout.toString()+
							onValide_OnClicked+
							PivotDistance_OnChanged.toString()+
							PivotAngle_OnChanged.toString()+
							HingeAngle_OnChanged.toString()+
							HingeStage_OnChanged.toString()+
							AngleCornet_OnChanged.toString()

							//Close_OnClicked.toString();
							
			oLayout.Language = "JScript" ;
		}
		//p.UserData =new Array('a', 'b', 'mpilgrim', 'z', 'example');
		
		
		
		var CurrentPolygon=Selection.Item(0);
		SetTransientReferencePlane(CurrentPolygon);
		oPSet.NullName.Value=GetPrim("Null", null, null, null);
		Rotate(null, 0, 0, 0, siAbsolute, siObjCtr, siObj, siX, null, null, null, null, null, null, null, 0, null);
		Rotate(null, 0, 0, 0, siAbsolute, siObjCtr, siObj, siY, null, null, null, null, null, null, null, 0, null);
		Rotate(null, 0, 0, 0, siAbsolute, siObjCtr, siObj, siZ, null, null, null, null, null, null, null, 0, null);
		Translate(null, 0, 0, 0, siAbsolute, siObjCtr, siObj, siX, null, null, null, null, null, null, null, null, null, 0, null);
		Translate(null, 0, 0, 0, siAbsolute, siObjCtr, siObj, siY, null, null, null, null, null, null, null, null, null, 0, null);
		Translate(null, 0, 0, 0, siAbsolute, siObjCtr, siObj, siZ, null, null, null, null, null, null, null, null, null, 0, null);
		oPSet.PivotName.Value=GetPrim("Null", null, null, null);
		MatchTransform(oPSet.PivotName.Value, oPSet.NullName.Value, siSRT, null);
		Translate(oPSet.PivotName.Value, Math.cos(oPSet.PivotAngle.Value*Math.PI/180.0)*oPSet.PivotDistance.Value, 0, Math.sin(oPSet.PivotAngle.Value*Math.PI/180.0)*oPSet.PivotDistance.Value, siAbsolute, siObjCtr, siObj, siXYZ, null, null, null, null, null, null, null, null, null, 0, null);
		oPSet.Polygone.Value=CurrentPolygon;
InspectObj( "Hingeissler", null, null, null, false );		

				

}

function OnInit()
{       
        // Create the initial layout
        CreateLayout();
}

function isAlreadyOpened(){

	var properties = ActiveSceneRoot.Properties;
	for(var i=0;i<properties.Count;i++){
	
		if(properties(i)=="Hingeissler")return true;
	}
	return false;
}

function CreatePSet()
{
        var oPSet = ActiveSceneRoot.AddProperty( "CustomProperty", false, "Hingeissler" ) ;
		var tab=new Array();
        oPSet.AddParameter3( "PivotDistance", siInt2,"10"	) ;
        oPSet.AddParameter3( "PivotAngle", siInt2,"90"		) ;
        oPSet.AddParameter3( "HingeAngle", siFloat,"90"		) ;
        oPSet.AddParameter3( "HingeStage", siInt2,"5"		) ;
        oPSet.AddParameter3( "AngleCornet", siFloat,"1"		) ;
		
		oPSet.AddParameter3( "NullName", siString,""		) ;
		oPSet.AddParameter3( "PivotName", siString,""		) ;
		oPSet.AddParameter3( "Polygone", siString,""		) ;
		oPSet.AddParameter3( "Numberop", siString,""		) ;
		

		
        return oPSet ;
}

function CreateLayout()
{
		
        var oLayout = PPG.PPGLayout ;
       oLayout.Clear() ; // Flush old layout
		oLayout.AddRow();
		oLayout.AddItem( "PivotDistance", "Pivot Distance");
		oLayout.EndRow() ;
		oLayout.AddRow();
		oLayout.AddItem( "PivotAngle", "Pivot Angle");
		oLayout.EndRow() ;
		oLayout.AddRow();
		oLayout.AddItem( "HingeAngle", "Hinge Angle");
		oLayout.EndRow() ;	
		oLayout.AddRow();
		oLayout.AddItem( "HingeStage", "Hinge Stage");
		oLayout.EndRow() ;			
		oLayout.AddRow();
		oLayout.AddItem( "AngleCornet", "Cornet Angle");
		oLayout.EndRow() ;			
		oLayout.AddRow();
			oLayout.AddButton( "onValide", "OK" ) ;
		oLayout.EndRow() ;

        PPG.Refresh();
		
}

function onValide_OnClicked()
{
	
	SetSelFilter("Polygon");
	SelectGeometryComponents(PPG.Polygone.Value);
	for (i=1; i<=PPG.HingeStage.Value; i++)
	{
		DuplicateMeshComponent(PPG.Polygone.Value, siPersistentOperation, null, null, null, null, null, null, null, null, null, null, null, null, null);
		SetTransientReferencePlane(PPG.PivotName.Value);
		Rotate(null,PPG.HingeAngle.Value/PPG.HingeStage.Value, 0, 0, siRelative, siObjCtr, siObj, siXYZ, null, null, null,null,null,null,null, 0, null);
	}
}

function PivotDistance_OnChanged()
{
/*
	for (i=0; i<PPG.HingeStage.Value; i++)
	{
		Undo(null);
		Undo(null);
		Undo(null);

	}*/
	
	Translate(PPG.PivotName.Value, Math.cos(PPG.PivotAngle.Value*Math.PI/180.0)*PPG.PivotDistance.Value, 0, Math.sin(PPG.PivotAngle.Value*Math.PI/180.0)*PPG.PivotDistance.Value, siAbsolute, siObjCtr, siObj, siXYZ, null, null, null, null, null, null, null, null, null, 0, null);
	
	
	SetSelFilter("Polygon");
	SelectGeometryComponents(PPG.Polygone.Value);
	for (i=1; i<=PPG.HingeStage.Value; i++)
	{
		DuplicateMeshComponent(PPG.Polygone.Value, siPersistentOperation, null, null, null, null, null, null, null, null, null, null, null, null, null);
		SetTransientReferencePlane(PPG.PivotName.Value);
		Rotate(null,PPG.HingeAngle.Value/PPG.HingeStage.Value, 0, 0, siRelative, siObjCtr, siObj, siXYZ, null, null, null,null,null,null,null, 0, null);
		
	}
	
}
function PivotAngle_OnChanged()
{

Translate(PPG.PivotName.Value, Math.cos(PPG.PivotAngle.Value*Math.PI/180.0)*PPG.PivotDistance.Value, 0, Math.sin(PPG.PivotAngle.Value*Math.PI/180.0)*PPG.PivotDistance.Value, siAbsolute, siObjCtr, siObj, siXYZ, null, null, null, null, null, null, null, null, null, 0, null);

}
function HingeAngle_OnChanged()
{
for (i=0; i<PPG.HingeStage.Value; i++)
	{
		Undo(null);
		Undo(null);
		Undo(null);

	}
	
	
	
	SetSelFilter("Polygon");
	SelectGeometryComponents(PPG.Polygone.Value);
	for (i=1; i<=PPG.HingeStage.Value; i++)
	{
		DuplicateMeshComponent(PPG.Polygone.Value, siPersistentOperation, null, null, null, null, null, null, null, null, null, null, null, null, null);
		SetTransientReferencePlane(PPG.PivotName.Value);
		Rotate(null,PPG.HingeAngle.Value/PPG.HingeStage.Value, 0, 0, siRelative, siObjCtr, siObj, siXYZ, null, null, null,null,null,null,null, 0, null);
		
	}
}
function HingeStage_OnChanged()
{

}
function AngleCornet_OnChanged()
{

}








Thanks for your help. I believe this script could be very useful, for CAO optimisation and modelisation of non-biological objects.

User avatar
csaez
Posts: 253
Joined: 09 Jul 2012, 15:31
Skype: csaezmargotta
Location: Sydney, Australia

Re: Multiple extrusion script

Post by csaez » 14 Aug 2013, 03:22

Hi there,
What about implement it as an operator?

I think 'model->modify->extrude along curve' does a similar job, perhaps you could work on the curve side via scripting and take advantage of the existing extrude operator.

pgeissler
Posts: 7
Joined: 05 Jul 2013, 14:45

Re: Multiple extrusion script

Post by pgeissler » 14 Aug 2013, 11:20

The curve solution is a truly good idea, but i'm afraid i'm running out of time to implement it for now.. If i can work on this script again i will surely consider it, thanks!

Here is the current version of the script:

Code: Select all



onGUI();


function onGUI()
{
		if(!isAlreadyOpened()){
		
			var oPSet = CreatePSet() ;
			
			var oLayout = oPSet.PPGLayout;
		
			oLayout.Logic =OnInit.toString()+
							CreateLayout.toString()+
							onValide_OnClicked+
							PivotDistance_OnChanged.toString()+
							PivotAngle_OnChanged.toString()+
							HingeAngle_OnChanged.toString()+
							HingeStage_OnChanged.toString()+
							TaperValue_OnChanged.toString()
							
							;
							//Close_OnClicked.toString();
							
			oLayout.Language = "JScript" ;
			
		}
		else
		{
			DeleteObj("Westhinge");
			var oPSet = CreatePSet() ;
			
			var oLayout = oPSet.PPGLayout;
		
			oLayout.Logic =OnInit.toString()+
							CreateLayout.toString()+
							onValide_OnClicked+
							PivotDistance_OnChanged.toString()+
							PivotAngle_OnChanged.toString()+
							HingeAngle_OnChanged.toString()+
							HingeStage_OnChanged.toString()+
							TaperValue_OnChanged.toString()

							//Close_OnClicked.toString();
							
			oLayout.Language = "JScript" ;
		}
		
		
		
		var CurrentPolygon=Selection.Item(0);
		SetTransientReferencePlane(CurrentPolygon);
		oPSet.NullName.Value=GetPrim("Null", null, null, null);
		Rotate(null, 0, 0, 0, siAbsolute, siObjCtr, siObj, siX, null, null, null, null, null, null, null, 0, null);
		Rotate(null, 0, 0, 0, siAbsolute, siObjCtr, siObj, siY, null, null, null, null, null, null, null, 0, null);
		Rotate(null, 0, 0, 0, siAbsolute, siObjCtr, siObj, siZ, null, null, null, null, null, null, null, 0, null);
		Translate(null, 0, 0, 0, siAbsolute, siObjCtr, siObj, siX, null, null, null, null, null, null, null, null, null, 0, null);
		Translate(null, 0, 0, 0, siAbsolute, siObjCtr, siObj, siY, null, null, null, null, null, null, null, null, null, 0, null);
		Translate(null, 0, 0, 0, siAbsolute, siObjCtr, siObj, siZ, null, null, null, null, null, null, null, null, null, 0, null);
		oPSet.PivotName.Value=GetPrim("Null", null, null, null);
		MatchTransform(oPSet.PivotName.Value, oPSet.NullName.Value, siSRT, null);
		Translate(oPSet.PivotName.Value, Math.cos(oPSet.PivotAngle.Value*Math.PI/180.0)*oPSet.PivotDistance.Value, 0, Math.sin(oPSet.PivotAngle.Value*Math.PI/180.0)*oPSet.PivotDistance.Value, siAbsolute, siObjCtr, siObj, siXYZ, null, null, null, null, null, null, null, null, null, 0, null);
		Rotate (oPSet.PivotName.Value,0,oPSet.PivotAngle.Value*Math.PI/180.0,0);
		oPSet.Polygone.Value=CurrentPolygon;
InspectObj( "Westhinge", null, null, null, false );		

				

}

function OnInit()
{       
        // Create the initial layout
        CreateLayout();
}

function isAlreadyOpened(){

	var properties = ActiveSceneRoot.Properties;
	for(var i=0;i<properties.Count;i++){
	
		if(properties(i)=="Westhinge")return true;
	}
	return false;
}

function CreatePSet()
{
        var oPSet = ActiveSceneRoot.AddProperty( "CustomProperty", false, "Westhinge" ) ;
		var tab=new Array();
        oPSet.AddParameter3( "PivotDistance", siFloat,"10"	) ;
        oPSet.AddParameter3( "PivotAngle", siFloat,"90","-180","180"		) ;
        oPSet.AddParameter3( "HingeAngle", siFloat,"90","-360","360"		) ;
        oPSet.AddParameter3( "HingeStage", siInt2,"5"		) ;
        oPSet.AddParameter3( "TaperValue", siFloat,"1", "0","2"		) ;
		
		oPSet.AddParameter3( "NullName", siString,""		) ;
		oPSet.AddParameter3( "PivotName", siString,""		) ;
		oPSet.AddParameter3( "Polygone", siString,""		) ;
		oPSet.AddParameter3( "Numberop", siString,""		) ;
        oPSet.AddParameter3( "PivotOldAngle", siFloat,"90","-180","180"		) ;


		
        return oPSet ;
}

function CreateLayout()
{
		
        var oLayout = PPG.PPGLayout ;
       oLayout.Clear() ; // Flush old layout
		oLayout.AddRow();
		oLayout.AddItem( "PivotDistance", "Pivot Distance");
		oLayout.EndRow() ;
		oLayout.AddRow();
		oLayout.AddItem( "PivotAngle", "Pivot Angle");
		oLayout.EndRow() ;
		oLayout.AddRow();
		oLayout.AddItem( "HingeAngle", "Hinge Angle");
		oLayout.EndRow() ;	
		oLayout.AddRow();
		oLayout.AddItem( "HingeStage", "Hinge Precision"); 
		oLayout.EndRow() ;			
		oLayout.AddRow();
		oLayout.AddItem( "TaperValue", "Taper");
		oLayout.EndRow() ;			
		oLayout.AddRow();
			oLayout.AddButton( "onValide", "OK" ) ;
		oLayout.EndRow() ;

        PPG.Refresh();
		
}

function onValide_OnClicked()
{
	SetValue("preferences.Interaction.autoinspect", false, null);
	SetSelFilter("Polygon");
	SelectGeometryComponents(PPG.Polygone.Value);
	
	for (i=1; i<=PPG.HingeStage.Value; i++)
	{
		DuplicateMeshComponent(PPG.Polygone.Value, siPersistentOperation, null, null, null, null, null, null, null, null, null, null, null, null, null);
		SetTransientReferencePlane(PPG.PivotName.Value);
		Rotate(null,PPG.HingeAngle.Value/PPG.HingeStage.Value, 0, 0, siRelative, siObjCtr, siObj, siXYZ, null, null, null,null,null,null,null, 0, null);
		
		var scaleValue=(PPG.HingeStage.Value+i*(PPG.TaperValue.Value-1))/(PPG.HingeStage.Value+(i-1)*(PPG.TaperValue.Value-1));
		
		
		Scale(null, scaleValue, scaleValue, scaleValue, siRelative, siLocal, siObj, siXYZ, null, null, null, null, null, null, null, 0, null);
	}
	
	DeleteObj(PPG.PivotName.Value);
	DeleteObj(PPG.NullName.Value);
	SetValue("preferences.Interaction.autoinspect", true, null);
}

function PivotDistance_OnChanged()
{

	
	Translate(PPG.PivotName.Value, 0, 0, 0, siAbsolute, siObjCtr, siObj, siXYZ, null, null, null, null, null, null, null, null, null, 0, null);
	Translate(PPG.PivotName.Value, 0, 0, PPG.PivotDistance.Value, siRelative, siLocal, siObj, siXYZ, null, null, null, null, null, null, null, null, null, 0, null);
	

	
}
function PivotAngle_OnChanged()
{

Rotate(PPG.PivotName.Value, 0, -PPG.PivotOldAngle.Value, 0, siRelative, siObjCtr, siObj, siXYZ, null, null, null, null, null, null, null, 0, null);
Rotate(PPG.PivotName.Value, 0, PPG.PivotAngle.Value, 0, siRelative, siObjCtr, siObj, siXYZ, null, null, null, null, null, null, null, 0, null);
 PPG.PivotOldAngle.Value=PPG.PivotAngle.Value;
}
function HingeAngle_OnChanged()
{

}
function HingeStage_OnChanged()
{

}
function TaperValue_OnChanged()
{

}



You can run it after selecting one or more polygons on a model.
- Pivot distance is the distance of the center of the extrusion circle
- Pivot Angle is the direction where the extruded part will going.
- Hinge Angle is the angle
- Hinge precision is the total of successive extrusion
- Taper is the scale between the original selection and the last extrusion. It allow you to get a cone-shaped extrusion (not sure if the curve-based solution allow it)

This script is far from perfect and based on my very limited scripting experience in XSI, i hope it will be improved in the future..

User avatar
myara
Posts: 358
Joined: 28 Sep 2011, 10:33

Re: Multiple extrusion script

Post by myara » 19 Aug 2013, 09:56

I'm not exactly sure what kind of tool are you working on, but I think the default Extrusion Operator does something very similar if you play with its parameters. Maybe working with its parameters to adjust it to your needs could be a better and faster approach.
M.Yara
Character Modeler | Softimage Generalist (sort of)

RoN43
Posts: 18
Joined: 09 Nov 2009, 18:32

Re: Multiple extrusion script

Post by RoN43 » 08 Mar 2016, 09:14

not working with cylinder
Image