generate point on edge

Discussions concerning programming of SOFTIMAGE©
Post Reply
anhungxadieu
Posts: 167
Joined: 17 Apr 2014, 10:39
Skype: nguyenvuducthuy

generate point on edge

Post by anhungxadieu » 28 Dec 2017, 18:17

Hi i want to create very simple ice node that can generate point on edge, but i'm get lost when it doesn't create number point that i want per edge :(

This is a ice node --> https://drive.google.com/open?id=1kL1To ... MSItSbriqn

Code: Select all

// PointGeneratorFromGeometry Plugin
// Initial code generated by Softimage SDK Wizard
// Executed Mon Feb 2 15:16:26 EST 2009 by belzilm
// 
// 
// Tip: You need to compile the generated code before you can load the plug-in.
// After you compile the plug-in, you can load it by clicking Update All in the Plugin Manager.
#include <xsi_application.h>
#include <xsi_context.h>
#include <xsi_pluginregistrar.h>
#include <xsi_status.h>

#include <xsi_icenodecontext.h>
#include <xsi_icenodedef.h>
#include <xsi_command.h>
#include <xsi_factory.h>
#include <xsi_math.h>
#include <xsi_vector2f.h>
#include <xsi_vector3f.h>
#include <xsi_vector4f.h>
#include <xsi_matrix3f.h>
#include <xsi_matrix4f.h>
#include <xsi_rotationf.h>
#include <xsi_quaternionf.h>
#include <xsi_color4f.h>
#include <xsi_shape.h>
#include <xsi_indexset.h>
#include <xsi_dataarray.h>
#include <xsi_dataarray2D.h>
#include <xsi_icegeometry.h>
#include <xsi_doublearray.h>
#include <xsi_random.h>
#include <xsi_progressbar.h>
#include <xsi_uitoolkit.h>
#include <vector>

// Defines port, group and map identifiers used for registering the ICENode
enum IDs
{
	ID_IN_geometry = 0,
	ID_IN_sampling_type = 1,
	ID_IN_random_point_count = 2,
	ID_G_100 = 100,
	ID_G_101 = 101,
	ID_OUT_sample_points = 200,
	ID_TYPE_CNS = 400,
	ID_STRUCT_CNS,
	ID_CTXT_CNS,
	ID_UNDEF = ULONG_MAX
};

XSI::CStatus RegisterPointGeneratorFromGeometry(XSI::PluginRegistrar& in_reg);

using namespace XSI;

XSIPLUGINCALLBACK CStatus XSILoadPlugin(PluginRegistrar& in_reg)
{
	in_reg.PutAuthor(L"belzilm");
	in_reg.PutName(L"PointGeneratorFromGeometry Plugin");
	in_reg.PutVersion(1, 0);

	RegisterPointGeneratorFromGeometry(in_reg);

	return CStatus::OK;
}

CStatus RegisterPointGeneratorFromGeometry(PluginRegistrar& in_reg)
{
	ICENodeDef nodeDef;
	nodeDef = Application().GetFactory().CreateICENodeDef(L"PointGeneratorFromGeometry", L"Point Generator From Geometry");

	CStatus st;

	// Add input ports and groups.
	st = nodeDef.AddPortGroup(ID_G_100);
	st.AssertSucceeded();

	st = nodeDef.AddPortGroup(ID_G_101);
	st.AssertSucceeded();

	st = nodeDef.AddInputPort(ID_IN_geometry, ID_G_100,
		siICENodeDataGeometry, siICENodeStructureSingle, siICENodeContextSingleton,
		L"geometry", L"geometry");
	st.AssertSucceeded();

	st = nodeDef.AddInputPort(ID_IN_sampling_type, ID_G_101,
		siICENodeDataLong, siICENodeStructureSingle, siICENodeContextSingleton,
		L"sampling type", L"sampling type", (LONG)0);
	st.AssertSucceeded();

	st = nodeDef.AddInputPort(ID_IN_random_point_count, ID_G_101,
		siICENodeDataLong, siICENodeStructureSingle, siICENodeContextSingleton,
		L"random points", L"random points", (LONG)3);
	st.AssertSucceeded();

	// Add output ports.
	st = nodeDef.AddOutputPort(ID_OUT_sample_points,
		siICENodeDataVector3, siICENodeStructureSingle, siICENodeContextElementGenerator,
		L"sample points", L"sample points");
	st.AssertSucceeded();

	PluginItem nodeItem = in_reg.RegisterICENode(nodeDef);
	nodeItem.PutCategories(L"Custom ICENode Sample");

	return CStatus::OK;
}

/*
PointGeneratorFromGeometry_BeginEvaluate:
This callback generates points according to the sampling method selected by the user.

*/
XSIPLUGINCALLBACK CStatus PointGeneratorFromGeometry_BeginEvaluate(ICENodeContext& in_ctxt)
{

	Application app;
	CDataArrayLong samplingType(in_ctxt, ID_IN_sampling_type);
	CDataArrayLong randomPointCount(in_ctxt, ID_IN_random_point_count);

	CICEGeometry geom(in_ctxt, ID_IN_geometry);

	CDoubleArray points;
	geom.GetPointPositions(points);

	MATH::CMatrix4f transfo;
	geom.GetTransformation(transfo);

	std::vector< MATH::CVector3f >* pPointVector = new std::vector< MATH::CVector3f >;

	switch (samplingType[0])
	{
	/* segment center points */
	case 2:
	{
		ULONG nCount = geom.GetSegmentCount();
		in_ctxt.PutNumberOfElementsToProcess(nCount);

		CLongArray indices;
		geom.GetSegmentIndices(indices);

		ULONG nOffset = 0;
		for (ULONG i = 0; i<nCount; i++)
		{
			MATH::CVector3f vTotal;
			MATH::CVector3f v0((float)points[indices[nOffset] * 3],
				(float)points[indices[nOffset] * 3 + 1],
				(float)points[indices[nOffset] * 3 + 2]);
			MATH::CVector3f v((float)points[indices[nOffset+1] * 3],
				(float)points[indices[nOffset+1] * 3 + 1],
				(float)points[indices[nOffset+1] * 3 + 2]);
			//app.LogMessage(CString(i) +"-->"+ CString(nOffset));
			app.LogMessage(CString(nOffset));
			app.LogMessage(CString(nOffset+1));

			for (int o = 0; o <= 10; o++) //resample .. ?
			{
				vTotal.MulByMatrix4InPlace(transfo);
				vTotal.LinearlyInterpolate(v0, v, (float)o/99);
				pPointVector->push_back(vTotal);
			}
			nOffset += 2;
		}
	}
	break;


	default:
	{
		in_ctxt.PutNumberOfElementsToProcess(0);
	}
	};

	in_ctxt.PutUserData((CValue::siPtrType) pPointVector);

	return CStatus::OK;
}

/*
PointGeneratorFromGeometry_Evaluate:
Sets the node output port with the points computed in the _BeginEvaluate callback.

*/
XSIPLUGINCALLBACK CStatus PointGeneratorFromGeometry_Evaluate(ICENodeContext& in_ctxt)
{
	ULONG out_portID = in_ctxt.GetEvaluatedOutputPortID();

	switch (out_portID)
	{
	case ID_OUT_sample_points:
	{
		std::vector<MATH::CVector3f>* pPointVector = (std::vector<MATH::CVector3f>*)(CValue::siPtrType)in_ctxt.GetUserData();

		CDataArrayVector3f outData(in_ctxt);

		CIndexSet indexSet(in_ctxt);
		for (CIndexSet::Iterator it = indexSet.Begin(); it.HasNext(); it.Next())
		{
			// Note: The output buffer is relative to the 'batch' data therefore we can index the batch with the iterator directly.
			// On the other hand pPointVector has to be indexed with the 'batch' global index i.e. CIndexSet::Iterator::GetAbsoluteIndex()
			outData[it] = (*pPointVector)[it.GetAbsoluteIndex()];
		}
	}
	break;
	};

	return CStatus::OK;
}

/*
PointGeneratorFromGeometry_EndEvaluate:
Release the memeory allocated to store the points;

*/
XSIPLUGINCALLBACK CStatus PointGeneratorFromGeometry_EndEvaluate(ICENodeContext& in_ctxt)
{
	CValue userData = in_ctxt.GetUserData();
	if (userData.IsEmpty())
	{
		return CStatus::OK;
	}

	std::vector<MATH::CVector3f>* pPointVector = (std::vector<MATH::CVector3f>*)(CValue::siPtrType)userData;

	if (pPointVector)
		delete pPointVector;

	in_ctxt.PutUserData(CValue());

	return CStatus::OK;
}

User avatar
rray
Moderator
Posts: 1511
Joined: 26 Sep 2009, 15:51
Location: Bonn, Germany
Contact:

Re: generate point on edge

Post by rray » 29 Dec 2017, 03:47

Hi,

Didn't know it was possible to generate ICE Geo from C++.. nice to learn!

Do you plan to modify the C++ code to do that?

Generating a number of particles on the edges of a mesh should be possible in ICE directly without much coding.
Softimage Resources section (formerly known as rray.de/xsi) updated Oct 01 2017

anhungxadieu
Posts: 167
Joined: 17 Apr 2014, 10:39
Skype: nguyenvuducthuy

Re: generate point on edge

Post by anhungxadieu » 29 Dec 2017, 04:41

rray wrote:
29 Dec 2017, 03:47
Hi,

Didn't know it was possible to generate ICE Geo from C++.. nice to learn!

Do you plan to modify the C++ code to do that?

Generating a number of particles on the edges of a mesh should be possible in ICE directly without much coding.
Yes, i try to modify "PointGeneratorFromGeometry" from sdk example. But i think that code only generate one point per one edge, in my case i want o create an interpolation array of point between 2 point per edge. This is my first try to use softimage api :).
This is what effect i try to do, if you know the way in ice please show me.
https://drive.google.com/open?id=1lZBQR ... l7l3krvj9E
ps: i don't know why i can't insert image? :(
Last edited by anhungxadieu on 29 Dec 2017, 11:21, edited 4 times in total.

User avatar
FXDude
Posts: 923
Joined: 19 Jun 2012, 21:59

Re: generate point on edge

Post by FXDude » 29 Dec 2017, 05:57

Hi,
just to say nice endeavor! ... and I think you image didn't go through,
would like to see what you mean in 1000 words (in an image ;) )

Edit: never mind.. you posted it :), I think the image tag expects direct links, otherwise must be attachments.

anhungxadieu
Posts: 167
Joined: 17 Apr 2014, 10:39
Skype: nguyenvuducthuy

Re: generate point on edge

Post by anhungxadieu » 29 Dec 2017, 09:55

Hi,
i was modify that code and luckily it's work now. But i still don't know how i can create that effect like my image i posted above :-?
ice node --> https://drive.google.com/open?id=13LYcr ... PZSVDwVNXB
https://www.youtube.com/watch?v=1x2BQw1 ... e=youtu.be

User avatar
rray
Moderator
Posts: 1511
Joined: 26 Sep 2009, 15:51
Location: Bonn, Germany
Contact:

Re: generate point on edge

Post by rray » 29 Dec 2017, 19:04

The hardest part is to identify which of all these positions go into the strandposition attribute and in which order. Do you plan to use short strands that go across 1 polygon only (looks like that in your picture)?
Softimage Resources section (formerly known as rray.de/xsi) updated Oct 01 2017

anhungxadieu
Posts: 167
Joined: 17 Apr 2014, 10:39
Skype: nguyenvuducthuy

Re: generate point on edge

Post by anhungxadieu » 30 Dec 2017, 03:44

rray wrote:
29 Dec 2017, 19:04
The hardest part is to identify which of all these positions go into the strandposition attribute and in which order. Do you plan to use short strands that go across 1 polygon only (looks like that in your picture)?
Yes, rray. I like to create a strand position exactly like my image. I think i need to create a point position per edge in order ... Start from one edge to get closet to another edge that not directly connect to it

User avatar
FXDude
Posts: 923
Joined: 19 Jun 2012, 21:59

Re: generate point on edge

Post by FXDude » 31 Dec 2017, 23:36

 
Which may be of interest, Furax can run strands along meshes,

If you want here is a link to an importable EZ Furax setup (EZ drag-drop sources to preset input groups)

FuraxEZSetup_0.2.zip

 
Furax1.jpg
Furax1.jpg (28.98 KiB) Viewed 170 times
 
 
________________________
In this setup, the head volume defines the strands starting points along guiding geo, ...
 
Furax2.jpg
 
But this volume could fairly easily be from a curve  
( or curvelists of multiple curves possibly kept live from deformed selected edge extractions, to make many little volumes around starting points)
as well as the source ... of other sources including ::
- the emitter geo (short extrusion),
- the guiding geo (long extrusion),
( then all much more self-contained )

Good luck, and whichever method you end up using, let us know how it goes!
 

anhungxadieu
Posts: 167
Joined: 17 Apr 2014, 10:39
Skype: nguyenvuducthuy

Re: generate point on edge

Post by anhungxadieu » 12 Jan 2018, 08:18


User avatar
rray
Moderator
Posts: 1511
Joined: 26 Sep 2009, 15:51
Location: Bonn, Germany
Contact:

Re: generate point on edge

Post by rray » 12 Jan 2018, 11:41

nice progress.
that seam is from the proportional transform tool. when points come into its influence area that werent in the initial cluster, they won't be translated. it's better to use the normal move tools, which store the translation for each point, or move the proportional further down in the operator stack
Softimage Resources section (formerly known as rray.de/xsi) updated Oct 01 2017

anhungxadieu
Posts: 167
Joined: 17 Apr 2014, 10:39
Skype: nguyenvuducthuy

Re: generate point on edge

Post by anhungxadieu » 15 Jan 2018, 15:15

Hi, thank rray!

i have a question, it's possible to put multiple userdata?
i try to do in "BeginEvaluate" but it crash like a boss!

Code: Select all

pData->pos_array.push_back(v);
pData->id_array.push_back(LONG(vIndecies[i]));
in_ctxt.PutUserData((CValue::siPtrType) pData);

User avatar
rray
Moderator
Posts: 1511
Joined: 26 Sep 2009, 15:51
Location: Bonn, Germany
Contact:

Re: generate point on edge

Post by rray » 16 Jan 2018, 14:38

Shouldn't be a problem

From your code it looks like you're calling PutUserData from inside a loop, it's better to call it only once, outside of the loop
Softimage Resources section (formerly known as rray.de/xsi) updated Oct 01 2017

anhungxadieu
Posts: 167
Joined: 17 Apr 2014, 10:39
Skype: nguyenvuducthuy

Re: generate point on edge

Post by anhungxadieu » 17 Jan 2018, 05:49

HI thank rray,
I got it work, but actually i'm not call PutUserData form inside of a loop. I just create another class and put the data in there

Code: Select all

// thuyPointFromEdge Plugin
// Initial code generated by Softimage SDK Wizard
// Executed Mon Jan 13 15:11:50 UTC+07:00 2018 by Thuy
// 
// 
// Tip: You need to compile the generated code before you can load the plug-in.
// After you compile the plug-in, you can load it by clicking Update All in the Plugin Manager.
#include <iostream>     // std::cout
#include <algorithm>    // std::set_difference, std::sort
#include <set>       // std::vector
#include <list>
#include <tuple>
#include <cmath>

#include <map>
#include <vector>

#include <xsi_application.h>
#include <xsi_context.h>
#include <xsi_pluginregistrar.h>
#include <xsi_status.h>

#include <xsi_icenodecontext.h>
#include <xsi_icenodedef.h>
#include <xsi_command.h>
#include <xsi_factory.h>
#include <xsi_longarray.h>
#include <xsi_doublearray.h>
#include <xsi_math.h>
#include <xsi_vector2f.h>
#include <xsi_vector3f.h>
#include <xsi_vector4f.h>
#include <xsi_matrix3f.h>
#include <xsi_matrix4f.h>
#include <xsi_rotationf.h>
#include <xsi_quaternionf.h>
#include <xsi_color4f.h>
#include <xsi_floatarray.h>
#include <xsi_shape.h>
#include <xsi_icegeometry.h>
#include <xsi_iceportstate.h>
#include <xsi_indexset.h>
#include <xsi_dataarray.h>
#include <xsi_dataarray2D.h>

// Defines port, group and map identifiers used for registering the ICENode

enum IDs
{
	ID_IN_geometry = 0,
	ID_ID_pointNeighbors = 1,
	//ID_IN_resample_point_count=2,
	ID_IN_root_point=3,
	ID_IN_root_index = 4,
	ID_IN_nextPointIndex = 5,
	ID_IN_pPos = 6,
	ID_IN_point_normal = 7,
	ID_G_100 = 100,
	ID_OUT_sample_points = 200,
	//ID_OUT_distance = 201,
	ID_OUT_upv = 202,
	ID_TYPE_CNS = 400,
	ID_STRUCT_CNS,
	ID_CTXT_CNS,
	ID_UNDEF = ULONG_MAX
};

XSI::CStatus RegisterThuyStrandFromEdge(XSI::PluginRegistrar& in_reg);

using namespace XSI;

class CData
{
public:
	CData(LONG count,const LONG* vIndecies, const double* normals, const double* positions);
	~CData();

	std::vector<XSI::MATH::CVector3f> pos_array, nor_array;
	int rootSize, step;
};

CData::CData(LONG count,const LONG* vIndecies, const double* normals, const double* positions)
{
	for (LONG i = 0; i < count ; i++)
	{
		MATH::CVector3f v(
			(float)positions[vIndecies[i] * 3],
			(float)positions[vIndecies[i] * 3 + 1],
			(float)positions[vIndecies[i] * 3 + 2]
		);
		MATH::CVector3f n(
			(float)normals[vIndecies[i] * 3],
			(float)normals[vIndecies[i] * 3 + 1],
			(float)normals[vIndecies[i] * 3 + 2]
		);
		//app.LogMessage("push pos: " + CString(v));
		//app.LogMessage("push normal: " + CString(n));
		pos_array.push_back(v);
		nor_array.push_back(n);
	}
}

//CData::~CData()
//{
//	for (int i = 0; i < pos_array.size(); ++i)
//		delete pos_array[i];
//}

//=========
//FUNTION
//=========

bool checkEleInArray(CDataArray2DLong::Accessor &inArray, ULONG val);
CStatus getNextIndex(CDataArray2DLong &pointNeighbors, CLongArray &rootIndex, CLongArray &preRoots, CLongArray &result);
CStatus getPointLoop(ULONG &rootIndex, ULONG &nextPointIndex, ULONG &vIndex, CDataArray2DLong &pointNeighbors, CLongArray &result);
CStatus checkPointNeighbors(CLongArray &rootIndex, CDataArray2DLong &pointNeighbors);

CStatus RegisterThuyStrandFromEdge(PluginRegistrar& in_reg)
{
	ICENodeDef nodeDef;
	nodeDef = Application().GetFactory().CreateICENodeDef(L"ThuyStrandFromEdge", L"Thuy Strand From Edge");

	CStatus st;

	st = nodeDef.PutColor(188, 188, 188);
	st.AssertSucceeded();

	// Add input ports and groups.
	st = nodeDef.AddPortGroup(ID_G_100);
	st.AssertSucceeded();

	st = nodeDef.PutThreadingModel(XSI::siICENodeSingleThreading);
	st.AssertSucceeded();

	st = nodeDef.AddInputPort(
		ID_IN_geometry,
		ID_G_100,
		siICENodeDataGeometry,
		siICENodeStructureSingle,
		siICENodeContextSingleton,
		L"geometry", L"geometry"
	);
	st.AssertSucceeded();

	//st = nodeDef.AddInputPort(
	//	ID_IN_resample_point_count,
	//	ID_G_100,
	//	siICENodeDataLong,
	//	siICENodeStructureSingle,
	//	siICENodeContextSingleton,
	//	L"resample points", L"resample points",
	//	(LONG)3,
	//	ID_UNDEF,
	//	ID_UNDEF,
	//	ID_UNDEF
	//	);
	//st.AssertSucceeded();

	st = nodeDef.AddInputPort(
		ID_IN_root_index,
		ID_G_100,
		siICENodeDataLong,
		siICENodeStructureSingle,
		siICENodeContextComponent0D,
		L"root index", L"root index",
		CValue(),
		CValue(),
		CValue(),
		ID_UNDEF,
		ID_UNDEF,
		ID_CTXT_CNS
	);
	st.AssertSucceeded();

	st = nodeDef.AddInputPort(
		ID_IN_nextPointIndex,
		ID_G_100,
		siICENodeDataLong,
		siICENodeStructureSingle,
		siICENodeContextSingleton,
		L"next point index", L"next point index"/*,
		CValue(),
		CValue(),
		CValue(),
		ID_UNDEF,
		ID_UNDEF,
		ID_CTXT_CNS*/
	);
	st.AssertSucceeded();

	st = nodeDef.AddInputPort(
		ID_ID_pointNeighbors,
		ID_G_100,
		siICENodeDataLong,
		siICENodeStructureArray,
		siICENodeContextComponent0D,
		L"point Neighbors", L"point Neighbors",
		(LONG)3,
		ID_UNDEF,
		ID_UNDEF,
		ID_UNDEF
	);
	st.AssertSucceeded();

	st = nodeDef.AddInputPort(
		ID_IN_point_normal,
		ID_G_100,
		siICENodeDataVector3,
		siICENodeStructureSingle,
		siICENodeContextComponent0D,
		L"point normal", L"point normal"
	);
	st.AssertSucceeded();

	st = nodeDef.AddInputPort(	
		ID_IN_root_point,
		ID_G_100,
		siICENodeDataVector3,
		siICENodeStructureSingle,
		siICENodeContextComponent0D,
		L"root points", L"root points",
		CValue(),
		CValue(),
		CValue(),
		ID_UNDEF,
		ID_UNDEF,
		ID_CTXT_CNS
		);
	st.AssertSucceeded();

	// Add output ports.
	st = nodeDef.AddOutputPort(
		ID_OUT_sample_points,
		siICENodeDataVector3,
		siICENodeStructureArray,
		siICENodeContextComponent0D,
		L"sample points", L"sample points",
		ID_UNDEF,
		ID_UNDEF,
		ID_CTXT_CNS
		);
	st.AssertSucceeded();

	st = nodeDef.AddOutputPort(
		ID_OUT_upv,
		siICENodeDataVector3,
		siICENodeStructureArray,
		siICENodeContextComponent0D,
		L"upv", L"upv",
		ID_UNDEF,
		ID_UNDEF,
		ID_CTXT_CNS
	);
	st.AssertSucceeded();

	//st = nodeDef.AddOutputPort(
	//	ID_OUT_distance,
	//	siICENodeDataFloat,
	//	siICENodeStructureArray,
	//	siICENodeContextComponent0D,
	//	L"distance", L"distance",
	//	ID_UNDEF,
	//	ID_UNDEF,
	//	ID_CTXT_CNS
	//);
	//st.AssertSucceeded();
	PluginItem nodeItem = in_reg.RegisterICENode(nodeDef);
	nodeItem.PutCategories(L"Thuy Custom ICENode");

	return CStatus::OK;
}

//set MultiThreading
//XSIPLUGINCALLBACK CStatus ThuyStrandFromEdge_SubmitEvaluationPhaseInfo(ICENodeContext& in_ctxt)
//{
//	ULONG nPhase = in_ctxt.GetEvaluationPhaseIndex();
//	switch (nPhase)
//	{
//	case 0:
//	{
//		in_ctxt.AddEvaluationPhaseInputPort(ID_IN_root_point);
//		in_ctxt.AddEvaluationPhaseInputPort(ID_ID_pointNeighbors);
//	}
//	break;
//	case 1:
//	{
//		in_ctxt.AddEvaluationPhaseInputPort(ID_IN_geometry);
//		//in_ctxt.AddEvaluationPhaseInputPort(ID_IN_resample_point_count);
//		in_ctxt.AddEvaluationPhaseInputPort(ID_IN_root_index);
//		in_ctxt.AddEvaluationPhaseInputPort(ID_IN_nextPointIndex);
//		// This phase is the last one. All ports specified for phase 1 will be evaluated in multi-threaded batches.
//		in_ctxt.SetLastEvaluationPhase();
//	}
//	break;
//	}
//	return CStatus::OK;
//}

XSIPLUGINCALLBACK CStatus ThuyStrandFromEdge_BeginEvaluate(ICENodeContext& in_ctxt)
{

	Application app;
	CStatus st;

	CICEGeometry geom(in_ctxt, ID_IN_geometry);
	//CDataArrayLong resamplePointCount(in_ctxt, ID_IN_resample_point_count);
	CDataArray2DLong pointNeighbors(in_ctxt, ID_ID_pointNeighbors);
	CDataArrayLong inRootIndex(in_ctxt, ID_IN_root_index);
	CDataArrayLong inNextPointIndex(in_ctxt, ID_IN_nextPointIndex);
	CDataArrayVector3f rootPoints(in_ctxt, ID_IN_root_point);
	CDataArrayVector3f inPointNormal(in_ctxt, ID_IN_point_normal);

	//get point position
	CDoubleArray points;
	geom.GetPointPositions(points);

	//get transform
	MATH::CMatrix4f transfo;
	geom.GetTransformation(transfo);

	//get point normal
	CDoubleArray pointNormal;
	for (ULONG i = 0; i < inPointNormal.GetCount(); i++)
	{
		pointNormal.Add(double(inPointNormal[i][0]));
		pointNormal.Add(double(inPointNormal[i][1]));
		pointNormal.Add(double(inPointNormal[i][2]));
		//app.LogMessage("in Normal_"+CString(inPointNormal[i]));
	}

	//CREATE USER DATA
	//CData *pData = new CData;

	//loop though inPoints
	//for (size_t i = 0; i < pointNeighbors.GetCount(); i++)
	//{
	//	CDataArray2DLong::Accessor daume = pointNeighbors[i];
	//	for (size_t x = 0; x < daume.GetCount(); x++)
	//	{
	//		app.LogMessage("daume:"+CString(daume[x]));
	//	}
	//}
	//app.LogMessage("v_" + CString(rootIndex.GetCount()) + "\n-------");
	
	//================
	//get root index
	//================
	CLongArray roots, vIndecies;

	//ULONG rootsIndex = inRootIndex[0];
	ULONG nextPointIndex = inNextPointIndex[0];

	//check if roots point invalid
	//CDataArray2DLong::Accessor startIndex = pointNeighbors[rootsIndex];
	//if (startIndex.GetCount() > 2 || !checkEleInArray(startIndex, nextPointIndex)) return CStatus::False;

	//find vPoint
	//ULONG vIndex;
	//startIndex[0] == nextPointIndex ? vIndex = startIndex[1] : vIndex = startIndex[0];
	//------------
	//--> and now we have -nextPointIndex- and -vIndex- for start to find a next root point :)
	//------------

	//recursion from roots index to find roots
	//roots.Add(rootsIndex);
	//roots.Add(nextPointIndex);
	//st = getPointLoop(rootsIndex, nextPointIndex, vIndex, pointNeighbors, roots);
	for (ULONG i = 0; i < inRootIndex.GetCount(); i++)
	{
		roots.Add(inRootIndex[i]);
	}

	//check roots found count
	//if (roots.GetCount() != rootPoints.GetCount()) return CStatus::False;
	st = checkPointNeighbors(roots, pointNeighbors);
	//app.LogMessage("roots: " + CString(roots));

	//define step and rootSize
	int step, rootSize;
	rootSize = roots.GetCount();

	//find vIndecies
	CLongArray preRoots(rootSize);
	for (int i = 0; i < rootSize; i++)
	{
		preRoots[i] = -1;
		vIndecies.Add(roots[i]);
	}
	if (st == CStatus::OK)
	{
		//app.LogMessage("dauma!");
		st = getNextIndex(pointNeighbors, roots, preRoots, vIndecies);
		if (st != CStatus::OK) return CStatus::OK;
		//app.LogMessage("vIndecies: " + CString(vIndecies));
		step = vIndecies.GetCount() / rootSize;
		
		//CREATE USER DATA
		CData *pData = new CData( vIndecies.GetCount(), vIndecies.GetArray(), pointNormal.GetArray(), points.GetArray());

		//set step and rootsize
		pData->rootSize = rootSize;
		pData->step = step;

		//for (LONG i = 0; i < vIndecies.GetCount(); i++)
		//{
		//	MATH::CVector3f v(
		//		(float)points[vIndecies[i] * 3],
		//		(float)points[vIndecies[i] * 3 + 1],
		//		(float)points[vIndecies[i] * 3 + 2]
		//	);
		//	MATH::CVector3f n(
		//		(float)pointNormal[vIndecies[i] * 3],
		//		(float)pointNormal[vIndecies[i] * 3 + 1],
		//		(float)pointNormal[vIndecies[i] * 3 + 2]
		//	);
		//	//app.LogMessage("push pos: " + CString(v));
		//	//app.LogMessage("push normal: " + CString(n));
		//	pData->pos_array.push_back(v);
		//	pData->normal_array.push_back(n);
		//}
		in_ctxt.PutUserData((CValue::siPtrType) pData);
	}


	return CStatus::OK;
}


XSIPLUGINCALLBACK CStatus ThuyStrandFromEdge_Evaluate(ICENodeContext& in_ctxt)
{
	Application app;

	//set MultiThreading
	//ULONG nPhase = in_ctxt.GetEvaluationPhaseIndex();
	//switch (nPhase)
	//{
	//case 0:
	//{
	//	return CStatus::OK;
	//}
	//break;
	//};

	ULONG out_portID = in_ctxt.GetEvaluatedOutputPortID();

	switch (out_portID)
	{
	case ID_OUT_sample_points:
	{
		CValue userData = in_ctxt.GetUserData();
		if (!userData.IsEmpty())
		{	
			//app.LogMessage("dauma!");
			//CREATE USER DATAs
			CData *pData = (CData*)(CValue::siPtrType)in_ctxt.GetUserData();
			//CDataArrayLong resamplePointCount(in_ctxt, ID_IN_resample_point_count);
			CDataArray2DVector3f outData(in_ctxt);
			CDataArrayVector3f rootPoints(in_ctxt, ID_IN_root_point);

			CIndexSet indexSet(in_ctxt);
			//app.LogMessage("dauma_"+CString(indexSet.Indices));
			for (CIndexSet::Iterator it = indexSet.Begin(); it.HasNext(); it.Next())
			{
				CDataArray2DVector3f::Accessor accessor = outData.Resize(it, pData->step);
				for (int i = 0; i < pData->step; i++)
				{
					accessor[i] = pData->pos_array[it + i*pData->rootSize];
					//app.LogMessage("id_"+CString(pData->id_array[it + i*pData->rootSize]));
					//app.LogMessage("id_"+CString(it + i*pData->rootSize));
					//app.LogMessage("it_" + CString(int(it)));
					//app.LogMessage("rootsCount_"+CString(rootPoints.GetCount()));
				}
			}
		}
	}
	break;
	case ID_OUT_upv:
	{
		CValue userData = in_ctxt.GetUserData();
		if (!userData.IsEmpty()){
			//CREATE USER DATAs
			CData *pData = (CData*)(CValue::siPtrType)in_ctxt.GetUserData();
			CDataArray2DVector3f outData(in_ctxt);
			CDataArrayVector3f rootPoints(in_ctxt, ID_IN_root_point);

			CIndexSet indexSet(in_ctxt);
			for (CIndexSet::Iterator it = indexSet.Begin(); it.HasNext(); it.Next()){
				CDataArray2DVector3f::Accessor accessor = outData.Resize(it, pData->step);
				for (int i = 0; i < pData->step; i++){
					accessor[i] = pData->nor_array[it + i*pData->rootSize];
					//app.LogMessage("normal_"+CString(pData->normal_array[it + i*pData->rootSize]));
				}
			}
		}
	}
	//break;
	//case ID_OUT_distance:
	//{
	//	CValue userData = in_ctxt.GetUserData();
	//	if (!userData.IsEmpty())
	//	{
	//		//////CREATE USER DATAs
	//		CData *pData = (CData*)(CValue::siPtrType)in_ctxt.GetUserData();
	//		CDataArray2DFloat outData(in_ctxt);
	//		CDataArrayVector3f rootPoints(in_ctxt, ID_IN_root_point);
	//		CIndexSet indexSet(in_ctxt);
	//		//app.LogMessage("dauma_"+CString(indexSet.Indices));
	//		CFloatArray distance;
	//		MATH::CVector3Array center, curPos;
	//		for (ULONG i = 0; i < pData->pos_array.size(); i++)
	//		{

	//		}
	//		for (CIndexSet::Iterator it = indexSet.Begin(); it.HasNext(); it.Next())
	//		{
	//			CDataArray2DFloat::Accessor accessor = outData.Resize(it, pData->step);
	//			MATH::CVector3f v1,v2,v3;
	//			MATH::CVector3 v;
	//			for (int i = 0; i < pData->step; i++)
	//			{
	//				v1 = pData->pos_array[it + i*pData->rootSize];
	//				v.Set(v1[0], v1[1], v1[2]);
	//				curPos.Add(v);
	//				if (it + 1 >= pData->rootSize) break;
	//				v3 = pData->pos_array[it + 1 + i*pData->rootSize];
	//				v.Set((v3[0]+v1[0])*0.5f, (v3[1]+v[1])*0.5f, (v3[2]+v3[2])*0.5f);
	//				center.Add(v);
	//			}
	//			for (LONG j = 0; j < curPos.GetCount(); j++)
	//			{
	//				MATH::CVector3 v, vc1, vc2;
	//				vc1 = center[j];
	//				//v = curPos[j];s
	//				if (j == 0) vc2 = center[j];
	//				if (j + 1 > (LONG)(center.GetCount())) break;
	//				vc2 = center[j+1];
	//				v = vc1;
	//				v -= vc2;
	//				distance.Add((float)(v.GetLength()));
	//			}
	//			for (int i = 0; i < pData->step; i++)
	//			{
	//				app.LogMessage("distance_"+CString(distance[i]));
	//				//accessor[i] = distance[i];
	//			}
	//		}
	//	}
	//}
	//break;
	};

	return CStatus::OK;
}

XSIPLUGINCALLBACK CStatus ThuyStrandFromEdge_EndEvaluate(ICENodeContext& in_ctxt)
{
	CValue userData = in_ctxt.GetUserData();
	if (userData.IsEmpty())
	{
		return CStatus::OK;
	}

	CData *pData = (CData*)(CValue::siPtrType)in_ctxt.GetUserData();
	if (pData)
		delete pData;

	in_ctxt.PutUserData(CValue());

	return CStatus::OK;
}

bool checkEleInArray(CDataArray2DLong::Accessor &inArray, ULONG val)
{
	for (ULONG i = 0; i < inArray.GetCount(); i++)
	{
		if (inArray[i] == val)
			return true;
	}
	return false;
}

CStatus getNextIndex(CDataArray2DLong &pointNeighbors, CLongArray &rootIndex, CLongArray &preRoots, CLongArray &result)
{
	Application app;

	//app.LogMessage("preRoots: " + CString(preRoots));
	//app.LogMessage("rootIn: " + CString(rootIndex));
	bool done = true;
	while (done)
	{
		done = false;
		CLongArray foundPoints;
		for (LONG i = 0; i < rootIndex.GetCount(); i++)
		{
			if ((i + 1) > rootIndex.GetCount()) return CStatus::OK;
			LONG startIndex = rootIndex[i - 1 < 0 ? 0 : i - 1];
			CDataArray2DLong::Accessor curIndex = pointNeighbors[rootIndex[i]];
			LONG nextIndex = rootIndex[i + 1];
			//app.LogMessage("startIndex: " + CString(startIndex));
			//app.LogMessage("nextIndex: " + CString(nextIndex));

			LONG foundPoint = -1;
			for (ULONG c = 0; c < curIndex.GetCount(); c++)
			{
				//app.LogMessage("current inter: " + CString(LONG(i)));
				if (i - 1 < 0) {
					//check point neighbors count
					if (curIndex.GetCount() > 3) {
						app.LogMessage("start V false: " + CString(curIndex[c]));
						return CStatus::False;
					}
					//check point neighbors
					if (curIndex[c] == preRoots[i] ||
						curIndex[c] == nextIndex) continue;

					foundPoint = curIndex[c];
					preRoots[i] = rootIndex[i];
					//app.LogMessage("foundPoint: " + CString(foundPoint));

					if (foundPoint == -1) {
						done = false;
					}
					else
					{
						foundPoints.Add(foundPoint);
						done = true;
					}
					break;
				}
				if (i + 1 == rootIndex.GetCount()) {
					//check point neighbors count
					if (curIndex.GetCount() > 3) {
						app.LogMessage("end V false: " + CString(curIndex[c]));
						return CStatus::False;
					}
					//check point neighbors
					if (curIndex[c] == preRoots[i] ||
						curIndex[c] == startIndex) continue;

					foundPoint = curIndex[c];
					preRoots[i] = rootIndex[i];
					//app.LogMessage("foundPoint: " + CString(foundPoint));

					if (foundPoint == -1) {
						done = false;
					}
					else
					{
						foundPoints.Add(foundPoint);
						done = true;
					}
					break;
				}
				else
				{
					//check point neighbors count
					if (curIndex.GetCount() > 4){
						app.LogMessage("V loop false: " + CString(curIndex[c]));
						return CStatus::False;
					}
					//check point neighbors
					if (curIndex[c] == preRoots[i] ||
						curIndex[c] == startIndex ||
						curIndex[c] == nextIndex) continue;

					foundPoint = curIndex[c];
					preRoots[i] = rootIndex[i];
					//app.LogMessage("foundPoint: " + CString(foundPoint));

					if (foundPoint == -1) {
						done = false;
					}
					else
					{
						foundPoints.Add(foundPoint);
						done = true;
					}
					break;
				}
			}
		}
		if (done)
		{
			for (int i = 0; i < foundPoints.GetCount(); i++)
			{
				rootIndex[i] = foundPoints[i];
				result.Add(foundPoints[i]);
			}
		}
	}
	//app.LogMessage("rootFound: " + CString(rootIndex));
	//app.LogMessage("result: "+CString(result));
	//app.LogMessage("done: "+CString(done));
	//if (done)
	//{
	//	getNextIndex(pointNeighbors, rootIndex, preRoots, result);
	//}
	return CStatus::OK;
}

CStatus getPointLoop(ULONG &rootIndex, ULONG &nextPointIndex, ULONG &vIndex, CDataArray2DLong &pointNeighbors, CLongArray &result)
{
	Application app;

	bool done = true;
	{
		//get data from per points data 
		CDataArray2DLong::Accessor curIndex = pointNeighbors[nextPointIndex];
		CDataArray2DLong::Accessor aVIndex = pointNeighbors[vIndex];
		//for (ULONG i = 0; i < curIndex.GetCount(); i++)
		//{
		//	app.LogMessage("curIndex: "+CString(curIndex[i]));
		//}
		//app.LogMessage("vIndex: "+CString(vIndex));

		if (curIndex.GetCount() < 3)
		{
			done = false;
		}
		LONG find = -1;
		for (ULONG i = 0; i < curIndex.GetCount(); i++)
		{
			if (curIndex[i] == rootIndex ||
				curIndex[i] == vIndex ) continue;
			if (checkEleInArray(aVIndex, curIndex[i]))
			{
				vIndex = curIndex[i];
				continue;
			}
			find = curIndex[i];
		}
		if (find == -1) {
			done = false;
			return CStatus::False;
		}
		else
		{
			rootIndex = nextPointIndex;
			nextPointIndex = find;
			result.Add(nextPointIndex);
			done = true;
		}
	}
	//app.LogMessage("root: "+CString(rootIndex));
	//app.LogMessage("next: "+CString(nextPointIndex));
	//app.LogMessage(CString(done));
	if (done)
	{
		getPointLoop(rootIndex, nextPointIndex, vIndex, pointNeighbors, result);
	}

	return CStatus::OK;
}

CStatus checkPointNeighbors(CLongArray &rootIndex, CDataArray2DLong &pointNeighbors)
{
	Application app;
	for (LONG i = 0; i < rootIndex.GetCount(); i++)
	{
		if ((i + 1) > rootIndex.GetCount()) return CStatus::OK;
		LONG startIndex = rootIndex[i - 1 < 0 ? 0 : i - 1];
		CDataArray2DLong::Accessor curIndex = pointNeighbors[rootIndex[i]];
		LONG nextIndex = rootIndex[i + 1];

		//app.LogMessage("startIndex: " + CString(startIndex));
		//for(int o = 0; o < curIndex.GetCount(); o++) app.LogMessage("pointNeighbors: " + CString(curIndex[o]));
		//app.LogMessage("nextIndex: "+ CString(nextIndex));

		if (i - 1 < 0 && curIndex.GetCount() == 2){
			if (!checkEleInArray(curIndex, nextIndex)){
				app.LogMessage("first root false!");
				return CStatus::False;
			}
			continue;
		}
		if(i + 1 == rootIndex.GetCount() && curIndex.GetCount() == 2){
			if (!checkEleInArray(curIndex, startIndex)){
				app.LogMessage("last root false!");
				return CStatus::False;
			}
			continue;
		}
		if (curIndex.GetCount() == 2) {
			if (!checkEleInArray(curIndex, nextIndex)) continue;
			if (!checkEleInArray(curIndex, startIndex)) continue;
			return CStatus::False;
			continue;
		}
		if (!checkEleInArray(curIndex, nextIndex) ||
			!checkEleInArray(curIndex, startIndex)){
			app.LogMessage("curIndex: " + CString(rootIndex[i]));
			app.LogMessage("in loop root false!");
			return CStatus::False;
		}
	}

	return CStatus::OK;
}
I think my current code not work good actually, i'm try to find another way.

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest