Generic study # 2 and vectors

One of the most common bottlenecks I have experienced when porting processing sketches into iOS/OFW is the way to pass vectors into classes. There is a good share of discussion if passing by object, reference or pointer is the best option. The answer to that question relies deeply in the context of the porting and the usability of the whole project.

In my case, I like my good share of vector pointers for my particle/chaos systems. So I decided to write a very small example of how to pass vectors of pointers as references. Notice the huge amount of notes! C++ is a huge jungle so forget about unique ways of reaching a result. You can notice, for instance, that my constructor has a different way to assign the vectors. Also that the function that applies arithmetic to the vector can be called directly from the main loop or from the class itself. Matter of taste. Finally, I declared the class generically (maybe our particles systems might have different types).

#include <iostream>
#include <vector>
#include "PassVector.h"

using namespace std;

int main(int argc, const char * argv[])
{
    vector<int*>randomValuesA;
    vector<int*>randomValuesB;
    
    PassVector<int> mPassVector;
    
    for(unsigned int i=0;i<10;i++){
        randomValuesA.push_back(new int(rand()%100));
        randomValuesB.push_back(new int(rand()%100));
    }
    
    mPassVector = PassVector<int>(randomValuesA,randomValuesB);
    //passing the values from the main loop//////////////////////////////
    //mPassVector.addTheReferences(randomValuesA, randomValuesB);
    mPassVector.addTheReferences();
    
    return 0;
}

The PassVector class. It is generic!

#include <iostream>
#include <vector>

using namespace std;

template <typename T>
class PassVector{
public:
    
    PassVector(){
        
    }
    
    PassVector(vector<T*>&_vecA,vector<T*>&_vecB):vecA(_vecA),vecB(_vecB){
        //if you are more into the java-ish style
        //vecA = _vecA;
        //vecB = _vecB;
    }
    
    ~PassVector(){
        
    }
    
    //create new vectors containing info related with speed, physics and etc
    //you might want to use iterators for calling functions here
    void addTheReferences(){
        for(unsigned int i=0;i<vecA.size();i++){
            addedVectorsAsReferences.push_back(new T(addPoinerValues(vecA[i], vecB[i])));
            cout<<"adding the value "<<*addedVectorsAsReferences[i]<<" at index "<<i<<endl;
        }
    }
    
    /*
     //passing the values directly from the main loop
    void addTheReferences(vector<T*>&v1,vector<T*>&v2){
        for(unsigned int i=0;i<v1.size();i++){
            addedVectorsAsReferences.push_back(new T(addPoinerValues(v1[i], v2[i])));
            cout<<"adding the value "<<*addedVectorsAsReferences[i]<<" at index "<<i<<endl;
        }
    }
     */
    
    //this function for any pointer arithmetic 
    T addPoinerValues(T* x, T* y){
        return *x + *y;//+,/,-, %
    }
    
    vector<T*>vecA;
    vector<T*>vecB;
    //new values
    vector<T*>addedVectorsAsReferences;
    
};

happy coding!

Generic study # 1

More and more I study the Cinder architecture more I am amazed how well written it is and how nice c++ can be when used properly. I strongly suggest any creative cpp coder to go and open the guts of our friend, there are some revealing lessons waiting there.
Two things in Cinder architecture that I love the most are generics and shared pointers. The later would require to speak about Boost (which itself is amazing and huuuuuuuuge). Generics are nice and useful. They can be tricky when mixed with iterators and some other STL facilities but in general are quite straight forward to implement and they can save loads of code when writing classes with flexible data types. So here a small small study on that, very simple but useful to start exploring this side of c++.

#include <iostream>
#include <vector>
#include <cstdlib>

using namespace std;

template <typename T>
class Adder{
	public:
	Adder(){}
	Adder(T _x, T _y):x(_x), y(_y){}
	~Adder(){}
	
	T addValue(){
		return x+y;
	}
	
	T restValue(){
		return x-y;
	}
	
	protected:
	T x,y;
	
};


template <typename T>
class AdderRef{
	public:
	AdderRef();
	AdderRef(const T &_x, const T &_y):x(_x),y(_y){}
	~AdderRef(){}
	
	T addValueRef(){
		return x+y;
	}
	
	protected:
	T x, y;
};

template <typename T>
class RandomNumber{
	public:
	RandomNumber(){}
	~RandomNumber(){}
	
	void setValue(){
		number = (T) random() % (T)50;
	}
	
	
	T getValue(){
		return number;
	}

	
	protected:
	T number;
};

template <typename T>
class NumberIter{
	public:
	NumberIter(){}
	~NumberIter(){}
	
	void createNumbers(){
		for(unsigned int i=0; i<10; i++){
			RandomNumber<T> number;
			number.setValue();
			mNumbers.push_back(number);
		}
	}
	
	
	void printNumbers(){
		for(rIter r = mNumbers.begin(); 
		r != mNumbers.end(); ++r){
			cout<<r->getValue()<<endl;
		}
	}
	
	protected:
	std::vector< RandomNumber<T> > mNumbers;
	typedef typename std::vector< RandomNumber<T> >::iterator  rIter;

	
};



////////////////////////////////////////////
//main loop

int main(){
	
	int x = 10;
	int y = 20;
	
	Adder<int> mAdder(10,20);
	AdderRef<int> mAdderRef(x,y);
	
	cout<<"this is adding the values: "<<mAdder.addValue()<<endl;
	cout<<"this is the adding with references: "<<mAdderRef.addValueRef()<<endl;
	
	//testing the random number generator
	
	RandomNumber<int> mNumber;
	mNumber.setValue();
	cout<<mNumber.getValue()<<endl;



	NumberIter<int> mNumberIter;
	mNumberIter.createNumbers();
	mNumberIter.printNumbers();
	
	
	
	return 0;
}

Notice that there is not a generic+pointers example. That is topic for later and which will include an intro to our dear friends the smart pointers.

Is this the first step for a c++ Frankenstein->mix well Cinder, OFW and et al!

Going west with Cg

During the last tour we did in England I had a lot of time during the travels between cities and airports, a perfect chance to play around with some ideas!
For a while I have been thinking ‘how can I bridge HLSL shaders to GL-land?’. Of course the answer is kind of straight forward: use Cg!. So before our little trip I got the Cg official tutorial and started reading. Far away so close, Cg indeed does feel like HLSL with some slightly differences. So at a conceptual level it was kind of straight forward. To be sincere I like much more when I can ‘expose’ all the transformation matrices and have a more direct control with the different parts of the program (sometimes GLSL feels slightly cryptic).
Now, the hard part was to figure out how to wrap it inside the jxs dialect, in particular the use of the matrices and the passing of values between the vertex and the pixel (fragment) shaders.
So here a little example for the ‘wave’ Cg shader:

<jittershader name="wave">
	
	<param name="modelViewProj" type="float4x4" state="MODELVIEW_PROJECTION_MATRIX" transform="IDENTITY"/>
	<param name="colorValue" type="float4" default="1. 1. 0. 1."/>
	<param name="posXDiv" type="float" default="5.0"/>
	<param name="posZDiv" type="float" default="4.0"/>
	<language name="cg" version="1.0">
		<bind param="modelViewProj" program="vp"/>
		<bind param="colorValue" program="fp"/>
		<bind param="posXDiv" program="vp"/>
		<bind param="posZDiv" program="vp"/>
	
		<program name="vp" type="vertex" entry="VS">
<![CDATA[
void VS(
	in float4 position : POSITION,
	in float4 color : COLOR0,
	in float4 wave : COLOR1,
	
	out float4 HPos : POSITION,
	out float4 Col0 : COLOR0,
	
	uniform float4x4 modelViewProj,
	uniform float posXDiv,
	uniform float posZDiv
)
{
	position.y = ( sin(wave.x + (position.x / posXDiv) ) + sin(wave.x + (position.z / posZDiv) ) ) * 2.5f;
	
	HPos = mul(modelViewProj, position);

	Col0.xyz = color.xyz;

}
	
]]>

		</program>
		
		
		<program name="fp" type="fragment" entry="PS">
<![CDATA[
void PS(
	in float3 position : POSITION,
	
	out float4 color : COLOR0,
	
	uniform float4 colorValue)
{

    color = colorValue;
}

]]>
		</program>
	
	

	</language>
</jittershader>

with the max patch:

----------begin_max5_patcher----------
949.3oc4Yt0aZCCFF9Z3WgUztjghyY1UcR62vzzllPlDSvcI1LaSKcU8+97g
.kVATSZHkpJA4fwI40O98y9Kl6GNvaFaMV3A9B3WfACte3fAlhzELn47Ad0n
04UHgoZdyqXzU0dir+j5P1JYEVZ9wflRWhj4KHzxobbtzdyCy7G6OBD.M6hM
agoi8A+t4Zr2F4cKw1KP+fPRuQ.uYHZo215QJLxfM65OGjsQFyYTIEUatTuu
xInJusRgqJWh4SwTzrJSM724pDj+YJaxX+GaRD5lVDTW1CCGp2LxQBUiEBTI
diBj30FFXkBXIS7yuQtA7I39YH7kYXXhdWVjggwGig6GaSdYr4.ZBZAZZo4I
HE18lmz2mlmezRyyFF1Xdhaq4I9My7HYkkU3SOpw1hiLgKA9a1d31MgJ2aSG
l3hu374.XU2MslUfU89sZzCKGRCM8+9sr+GF8tavifjcF7HLtKF7Xx4XrCEd
H0pFnthGX.kQawxlZpBp6OTByfcNJCS9fxxny.KS+fxR+ftmkYuyYIEeqpcr
mDI9CvlLQNqhw+NpZEVokseN44UlXlPIHxrCFl9xve+7taxJMo6H00D43aIz
B1sf7RH3pB1JUe7rUymi4.04yEHD.1hjYyrHJwtK3kAlwjN5.fqalPtKyTgi
EX4I6ifprxhU4oYhdCCzG2l7S7eyxO4H1nxpwKPzhJr0IQnKvbhbpjinh4Ld
s1NcCQPT9qV3nZHWRrM21HGh.OjYJ6MyLcb5UxIEhEnkM.zdnjwWITmjipzC
gYKuPEblWp1bUAoFj3q+bEhJUs.BRzB51j2LDFXmbwgYWThdZMRxIqOHnSuP
A8VBpGfin35snaviyKGe8ZEp0B0P2SlhwFWYXViG0uSfXxaFDa46hZW5hnjW
6qhF2KuI5wcJbLcqSAyQB7TSBEp.w3c+d5NEq2HzNK4D3qb5wvKs.MIXFvvq
1RF+3GMQtAF6iauKmykFc9qxMyYpvhVFaYWXiXWcM6MEhNOCBySwqhPe9Rsa
ZF5xeJnDrU77M5rY8F.O1TJvBIghjDFcm5nSfFDusRKHEEX5tiGTPD5gHLMz
8+BEtJmLWjySpy4TMwNnFXuolPW5qR5O4j4p0InezSpq5IrezShq5IpWzSvk
k8IvE6yyz7YUOtXeBh6O8DeY0ccQMvrVMvKF0.cIRW+2azW5IxA8j1exw2A4
j0exwk37VpFa5XnkKuAyEM2RiPTYndMiaVFwQCsqVq8Tyczii0qQis9gC02s
GF9eo5SvwC
-----------end_max5_patcher-----------

So what is the benefit? well, for me would be an interesting bridge to start porting some vvvv shaders into cinder and jitter. I want to test this idea using either jxs or straight glsl with c++.
We will see…

Port the shaders for artists

The process of learning HLSL has been an enjoyable one. In particular I’ve found Sebastien St-Laurent’s book ‘Shaders for game programmers and artists’ an amazing resource. Together with the vvvv forum it has been my main source of information about how to code with HLSL.

As an exercise I decided to port to vvvv some of the examples I found on the book in order to deepen on the described techniques. I am amazed how well the shader compiler works in vvvv and how nice the process was, very enjoyable. I decided to share some of the examples as they might be useful for some people willing to jump into the HLSL ocean.

I have more chapters ported but the patches and shaders are rather messy. I will clean them up and then post them here. Happy shading!

chapter9

chapter10

chapter12

chapter16

chapter17

Set the cell!

One of the most useful methods when developing java-jitter is, for sure, the setcell family. So, let’s say that you have something like this:

setcell 1 1 plane 1 val 233

 
translated as a java-jitter class:
 

import com.cycling74.max.*;
import com.cycling74.jitter.*;

public class SetcellBasic extends MaxObject{
	JitterMatrix sc1 = new JitterMatrix(3,"char",3,3);
	int[] cells = new int[2];
	int value;
	int plane;

	public SetcellBasic(){
		declareInlets(new int[]{DataTypes.ALL});
		declareOutlets(new int[]{DataTypes.ALL});

		value = 0;
		plane = 0;
	}

	public void setCells(int _x, int _y){
		cells[0] = _x;
		cells[1] = _y;

		post("the position of the cell is "+ cells[0] + " " + cells[1]);
	}

	public void setValue(int _value){
		value = _value;
	}

	public void setPlane(int _plane){
		plane = _plane;
	}

	public void bang(){
		//remember that setcell(int[], int, int)
		//also floats can be used as values
		sc1.setcell(cells, plane, value);

		outlet(0,"jit_matrix", sc1.getName());
	}
}

 
The utility of setcell should not be bypassed, it can be a powerful method to gain control over the data flow of your matrices. Let’s have for example the next simple processing sketch:
 

void setup() {
  size(700, 500);
}

void draw() {
  background(0);
  stroke(255);
  line(width / 2, height / 2, mouseX, mouseY);
}

now let’s make the equivalent in matrixland using java-jitter:

import com.cycling74.max.*;
import com.cycling74.jitter.*;

public class Lesson2 extends MaxObject{

	JitterMatrix l2= new JitterMatrix(3,"float32",2);
	int[] cells = new int[2];
	float x, y;

	public Lesson2(){
		declareInlets(new int[]{DataTypes.ALL});
		declareOutlets(new int[]{DataTypes.ALL});
		x = 0; y = 0;
		cells[0]=0; cells[1] = 0;
	}

	public void setX(float _x){
		x = _x;
	}

	public void setY(float _y){
		y = _y;
	}

	public void resetValues(){
		x = 0;
		y = 0;
	}

	public void bang(){
		int plane = 0;
		l2.setcell(cells, plane, x);

		plane = 1;
		l2.setcell(cells, plane, y);

		plane = 2;
		l2.setcell(cells, plane, 0.0f);

		outlet(0,"jit_matrix", l2.getName());
	}

}

 
Notice how each plane represents the x, y and z values. Remember that setters are our friends here!

Finally, we need to ‘draw’ the matrix in jitter. I give priority to the sketch object but there are several ways to achieve the result, even declaring your objects on the java class. I find this a less flexible way to work as i prefer to keep all the matrix calculation inside java but the graphic prototyping in jitter.

----------begin_max5_patcher----------
1174.3oc2Z10iahCEF95jeEVn8xLQ9Xv7wdU6c6E60U6pUUibBdRYJAlEb5j
1p9eeM1jlLSIfIh33cDiBByWu7vqOmiMy2mOyaU4ddsG52Q+CZ1ruOe1LUSM
MLqc6YdaY6WmypUGl2VdcMaC2agdeB9dgp8JdMWr.kVwddKSTksGkKOxxBR6
VOUlUHpObZOTJ2H6a7lSMYIts0xchbtP70m3ZE44g9X6tdhIV+orhM2WwWKz
60mDIOSj9WHLPsxeI9mmSVpRYkqd7N+SuwErspaf2evy+BWjslcXuE61lUHk
f5QkbrQsvTsBMM9i4ya9YggLqf+rTD+BxpWyx4Hrb4NXIBVNovgF2vCeBsYU
b3RpDNQcCGJtS579pLVdmjI7ZSl6PvHggzb0KOnThxrP70XoOdDjLRdP9+GO
BRhMmGQtFOtp8b7STjQ1mYvdNAg2tdN61thWcAthEHuUrhMlzaARTwVoX0Fm
iAzQx.nSFPbMFz1CwLFDb6XP28P1U7Da8mUcQjKWFh90U8xqHMhzIdh5mWjI
gWAW.uNW8KMbBBik+fOlOLOqfutbWg3znZSQPl.rJ5BDfOZtZRU2Ir.2K7aE
mWnXv3XRdVsxKoVahYxWkdhFzmYxO4MZ.HsGg3GOb.H+32lLvusrMiXPnqED
VdYq40BlfOUAfMHNreHUSIcbX+dQFLIHiNcHSfvisZtGxKY8iDPOJHBEzlo9
PBAOIHAlvTSpgV+AV9N9jN9Y.2NjHEbn5gQelbPf+MKGj70q7hbQdBShvPHZ
SAkNbDF31ko4bdCoy3uQ+FLk9hCDIV0OI.50WD9F2W.IDC7EAtnu3utR9BRf
A9BhqUyp7Eep5k93Hxv9DekAIPE9HHt2TKItYpkIc1SRTEsFFdxzJcNOB9l4
QtzIwtY7fSZN3V2iFW.Mou4vFhbwIw9wLwxM4Kq+LW9vgxyIn2stLurBA5kw
RqElQrXMpH81gKw0FPPCrdNqHs7YModnlwFMhzQwFp3NH53zvnmBqyQoXWjR
RKUEuHkWoAEuhUyuWarvKa+azy6qQjin6K529Ykn8gtHWCcBzJ0hhWWHcd8Z
80x.jgUlsPnOhEdyl3uyPr+cKWTUhH3IuvfSRDR6kIzaVdPQ4lM4+zmL5Ohj
9QT2SgfO7amyg4Ut9ldhjzUh7Q9tVdYt+vIN3D6pPBVOGC5QXe15Act4qZ+i
n+TyooNsslKD8zQ0eHBXxwh5t3oKd6E+qNnDZS6ujU0k6pVe3Q6vWDFcTro7
ZQVASjUVbxA07YCjU7b3f9TVZJWs+CTaaVZ6+EDpSB8wNeyYplT2tgzD7Rge
s0TyzPaFmrmlZ99jCpo.6xolua7vu6Br66NSzzqD9UmSQlpIh8zTfIZJxtbR
FuF4Ojln1WSjgzjk83lDGWIbWSSfUysPLQS9VN2BXfe5UIfrhlfgzjciYFZB
l.qJIhQkpD5fZxtgmZ9JaCpIB18zjcsSPn6IoD2ygCD2CSlT6DX27ufIABra
pNHx4jjQUD.QVOSG3T96PCJC29LB6TJxjgia4QYZxjVX2..lTGfcqz8JGQRt
wOl+eKwRGiC
-----------end_max5_patcher-----------

One interesting thing to notice is how 3 lines of processing become a considerably bigger patch in jitter, where is the gain here?. I think this little bouncing between code and graphic paradigms provide a lot of freedom and refresh our perspective about the tools we are using, what do you think?

Phongy depth

Made variation to Natan Sinigaglia’s ‘DOF’ patch: implemented a phong light model for the depth pass. It makes the image ‘crunchier’.
Notice that there are several techniques. In those with a ‘viewmatrix depth’ I found a kind of discontinuity with the shading interpolation. In the case of the ‘distance to camera’ techniques I used the next formula:

float4 interpolation = lerp(input, col, pow(Interpolation,2));

Remember to place the “PhongDirectional.fxh” file on the same root folder as the shader. You can find the original file on the effects folder inside vvvv.

I like the result, next step would be to explore more light models and, perhaps, to implement a crepuscular ray model on top of the depth!

//transform
float4x4 tW: WORLD;
float4x4 tV: VIEW;
float4x4 tWV: WORLDVIEW;
float4x4 tVP: VIEWPROJECTION;
float4x4 tWVP: WORLDVIEWPROJECTION;
float4x4 tP: PROJECTION;

#include "PhongDirectional.fxh"

float dNear = 1;
float dFocus = 0;
float dFar = 2;
float clampFar = .9;
float3 camPos;

//textures
//not used but feasible to implement
texture Tex;
sampler Samp = sampler_state{
	Texture = (Tex);
	MipFilter = LINEAR;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
};
float4x4 tTex: TEXTUREMATRIX;
float4x4 tColor: COLOR;


//struct
struct vs2ps{
	float4 Pos: POSITION;
	float4 TexCd: TEXCOORD0;
	 float3 LightDirV: TEXCOORD1;
    float3 NormV: TEXCOORD2;
    float3 ViewDirV: TEXCOORD3;
	float4 col: COLOR;
};

vs2ps VS(
	float4 Pos: POSITION)
{
	vs2ps Out = (vs2ps) 1;
	
	Pos = mul(Pos, tW);
	float depth = distance(Pos, camPos);
	
	if(depth&lt;dFocus){
		depth = (depth-dNear)/(dFocus-dNear)/2;
	}else{
		depth = (depth-dFocus)/(dFar - dFocus)/2 + 0.5;
		//optional:
		depth = clamp(depth, 0 , clampFar);
	}
	
	Out.Pos = mul(Pos, tVP);
	Out.col.rgb = depth;
	
	return Out;
}

vs2ps VS2(
	float4 Pos: POSITION)
{
	vs2ps Out = (vs2ps) 1;
	
	Out.Pos = mul(Pos, tWVP);
	
	float depth = Out.Pos.z;
	
	if    (depth &lt; dFocus)
     {
           depth = (depth - dNear)/(dFocus - dNear)/2;
     }
        
     else
     {
           depth = (depth-dFocus)/(dFar - dFocus)/2 + 0.5;
           //OPTIONAL:
           depth = clamp (depth, 0, clampFar) ;
     }

     Out.col.rgb = depth;

    return Out;
}

////
vs2ps VS_PHONG_DCD(
	float4 Pos: POSITION,
    float3 NormO: NORMAL,
    float4 TexCd : TEXCOORD0
)
{
	vs2ps Out = (vs2ps) 1;
	
	//depth stuff
	Pos = mul(Pos, tW);
	float depth = distance(Pos, camPos);
	
	if    (depth &lt; dFocus)
     {
           depth = (depth - dNear)/(dFocus - dNear)/2;
     }
        
     else
     {
           depth = (depth-dFocus)/(dFar - dFocus)/2 + 0.5;
           //OPTIONAL:
           depth = clamp (depth, 0, clampFar) ;
     }
	
	//phong stuff
	//inverse light direction in view space
    Out.LightDirV = normalize(-mul(lDir, tV));
    
    //normal in view space
    Out.NormV = normalize(mul(NormO, tWV));
	
	Out.Pos  = mul(Pos, tVP);
    Out.TexCd = mul(TexCd, tTex);
    Out.ViewDirV = -normalize(mul(Pos, tWV));
	
	
	Out.col.rgb = depth;
	
    return Out;
}

////
vs2ps VS_PHONG_VMD(
	float4 Pos: POSITION,
    float3 NormO: NORMAL,
    float4 TexCd : TEXCOORD0
)
{
	vs2ps Out = (vs2ps) 1;
	
	//depth stuff
	Out.Pos = mul(Pos, tWVP);
	
	float depth = Out.Pos.z;
	
	if    (depth &lt; dFocus)
     {
           depth = (depth - dNear)/(dFocus - dNear)/2;
     }
        
     else
     {
           depth = (depth-dFocus)/(dFar - dFocus)/2 + 0.5;
           //OPTIONAL:
           depth = clamp (depth, 0, clampFar) ;
     }
	
	//phong stuff
	//inverse light direction in view space
    Out.LightDirV = normalize(-mul(lDir, tV));
    
    //normal in view space
    Out.NormV = normalize(mul(NormO, tWV));
	
	Out.Pos  = mul(Pos, tWVP);
    Out.TexCd = mul(TexCd, tTex);
    Out.ViewDirV = -normalize(mul(Pos, tWV));
	
	
	Out.col.rgb = depth;
	
    return Out;
}

///////////////////////////////////////////////////////
//pixel
float4 PS(vs2ps In): COLOR{
	return In.col;
}

float Alpha  = 1;

float4 PS_PHONG(vs2ps In):COLOR{
	//In.TexCd = In.TexCd / In.TexCd.w; // for perpective texture projections (e.g. shadow maps) ps_2_0

	//orthodox phong!
	//here we can implement the texture
    //float4 col = tex2D(Samp, In.TexCd);
	
	float4 input = In.col;
	float4 col = In.col;

    col.rgb *= PhongDirectional(In.NormV, In.ViewDirV, In.LightDirV);
	col = col * input;
    col.a *= Alpha;
    

    return mul(col, tColor);
}

//softer interpolation
float Interpolation = 0.1f;
float4 PS_PHONG2(vs2ps In):COLOR{
	float4 input = In.col;
	float4 col = In.col;
	
	col.rgb *= PhongDirectional(In.NormV, In.ViewDirV, In.LightDirV);
	
	//float4 interpolation = lerp(input, col, Interpolation);
	float4 interpolation = lerp(input, col, pow(Interpolation,2));
	
	col.a *= Alpha;
	
	return col;
	
	
}

//techniques
//distance camera depth
technique DCD{
	pass P0{
		VertexShader = compile vs_2_0 VS();
		PixelShader = compile ps_2_0 PS();
	}
}

//view matrix depth
technique VMD{
	pass P0{
		VertexShader = compile vs_2_0 VS2();
		PixelShader = compile ps_2_0 PS();
	}
}

//phong + DCD
technique phDCDInter{
	pass P0{
		VertexShader = compile vs_2_0 VS_PHONG_DCD();
		PixelShader = compile ps_2_0 PS_PHONG2();
	}
}

//phong + VMD
technique phVMD{
	pass P0{
		VertexShader = compile vs_2_0 VS_PHONG_VMD();
		PixelShader = compile ps_2_0 PS_PHONG();
	}
}


//phong + VMD + interpolation
technique phVMDInter{
	pass P0{
		VertexShader = compile vs_2_0 VS_PHONG_VMD();
		PixelShader = compile ps_2_0 PS_PHONG2();
	}
}

The final result looks like this, once the DOF is implemented:

phong depth with HLSL

Cinder to touchdesigner # 2

note: I will migrate this blog to my webpage very soon thus having a proper display of the source code.

Next step on having a kind of template for porting OFW/Cinder patches into TD. So, I have the next class called ‘Lines’:

#pragma once
#include "TOP_CPlusPlusBase.h"

#include <windows.h>
#include <gl/gl.h>

class Lines
{
public:
	Lines();
	~Lines();

	virtual void draw(int _x1, int _y1, int _x2, int _y2);

	int		x1,x2,y1,y2;

};

the body of the class:

#include "Lines.h"

Lines::Lines(){
	x1 = x2 = y2 = y1 = 0;
}

Lines::~Lines(){

}

void Lines::draw(int _x1, int _y1, int _x2, int _y2){

	x1 = _x1;
	y1 = _y1;
	x2 = _x2;
	y2 = _y2;

	::glVertex2i(x1,y1);
	::glVertex2i(x2,y2);
}

next step might be to implement containers with pointers and shared pointers.

Cinder to touchdesigner # 1

When I am about to start a project I always ask myself ‘spaghetti or code?’. Indeed, choosing the correct tool for the correct job/piece/toy is, from MHO, one of the most important steps of media design. However, I often find myself willing to have the benefits of one tool available into another. That has been the reason behind porting java and processing code into jitter as I can benefit a performing tool with data management resources( just to put an example). Of course working with such idea always provides interesting insights about the tools themselves, their possibilities and limitations. It also exposes the many things that I need to learn in order to implement my ideas. In other words, turns the world slightly upside down.
Today I managed to compile my first, very simple simple, TOP object for TouchDesigner. I need to admit that the most difficult past was not to deal with the internal logic of the c++ file but to compile it: TouchDesigner is only available for the windows system, meaning that I am learning how to do all this compilation management with Visual Studio c++. So far so good although I still use too many concepts from XCode in order to deal with the new IDE( which is probably not a good idea).
The TouchDesigner gl externals are quite straight forward. Basically you are calling gl commands ‘as they are’. So for a cluster of lines you would do something like this:

	::glBegin(GL_LINES);
	::glLineWidth(1.0f);
	for(unsigned int i=0;i<amount;i++){
		int y1 = rand()% outputFormat->height;
		int x2 = rand()% outputFormat->width;
		int y2 = rand()% outputFormat->height;
		::glVertex2i(x1 ,y1);
		::glVertex2i(x2, y2);
	}
	::glEnd();

pretty direct, right?

So now to plan the proper way to port my Cinder and OFW apps into TouchDesigner. Let’s see how it goes…

Tutorial 46 to java

I had the impression that the only “official” particle system example on jitter( tutorial 46) was rather slow using javascript so I ported it to java. The porting was really straight forward and I think it might be a nice study source. Notice that the methods bang_expr() and bang_iter() are not implemented( yet!).
Hope someone finds this useful.

import com.cycling74.max.*;
import com.cycling74.jitter.*;
import java.io.*;

public class MxTutorial46b extends MaxObject{
	int PARTICLE_COUNT = 1000;
	int ATTRACTOR_COUNT = 3;
	JitterObject noisegen;
	JitterObject attgen;
	JitterObject myexpr;
	JitterObject myexpr2;
	//matrices
	JitterMatrix particlemat;
	JitterMatrix velomat;
	JitterMatrix attmat;
	JitterMatrix distmat;
	JitterMatrix tempmat;
	JitterMatrix summat;
	JitterMatrix summat2;
	JitterMatrix scalarmat;
	JitterMatrix amat;

	float a = 0.001f;
	float d = 0.01f;
	//String perform_mode = "op";
	//String perform_mode;
	int perform_mode;
	//String draw_primitive = "points";
	String draw_primitive;

	public MxTutorial46b(){
		declareInlets(new int[]{DataTypes.ALL});
		declareOutlets(new int[]{DataTypes.ALL});

		//perform_mode = new String("op");
		perform_mode = 0;
		draw_primitive = new String("points");

		//declare the noise objects
		//noisegen = new JitterObject("jit.noise","float32");
		noisegen = new JitterObject("jit.noise");
		noisegen.setAttr("dim", PARTICLE_COUNT);
		noisegen.setAttr("planecount",3);
		noisegen.setAttr("type", "float32");

		attgen = new JitterObject("jit.noise");
		attgen.setAttr("dim", ATTRACTOR_COUNT);
		attgen.setAttr("planecount", 3);
		attgen.setAttr("type", "float32");

		myexpr = new JitterObject("jit.expr");
		myexpr.setAttr("expr", "in[0].p[0]+in[0].p[1]+in[0].p[2]");
		// second expression: evaluate a+((b-c)*d/e)

		myexpr2 = new JitterObject("jit.expr");
		myexpr2.setAttr("expr", "in[0]+((in[1]-in[2])*in[3]/in[4])");

		//matrices declaration
		particlemat = new JitterMatrix(3,"float32",PARTICLE_COUNT);
		velomat = new JitterMatrix(3,"float32",PARTICLE_COUNT);
		attmat = new JitterMatrix(3,"float32",ATTRACTOR_COUNT);
		distmat = new JitterMatrix(3,"float32",PARTICLE_COUNT);
		tempmat = new JitterMatrix(3,"float32", PARTICLE_COUNT);
		summat = new JitterMatrix(3,"float32", PARTICLE_COUNT);
		summat2 = new JitterMatrix(3,"float32",PARTICLE_COUNT);
		scalarmat = new JitterMatrix(3,"float32",PARTICLE_COUNT);
		amat = new JitterMatrix(3,"float32",PARTICLE_COUNT);

		init();

		post("this is a port of tutorial 46!\n");
	}

	public void init(){
		noisegen.matrixcalc(particlemat, particlemat);
		particlemat.op("*", 2.0f);
		particlemat.op("-", 1.0f);
	    // generate a matrix of random velocities spread between -1 and 1
	    noisegen.matrixcalc(velomat, velomat);
	    velomat.op("*", 2.0);
	    velomat.op("-", 1.0);
	    // generate a matrix of random attractors spread between -1 and 1
	    attgen.matrixcalc(attmat, attmat);
	    attmat.op("*", 2.0);
	}

	public void bang(){
	    switch(perform_mode) { // choose from the following...
        case 0: // use Jitter matrix operators
            bang_op();
            break;
        case 1: // use [jit.expr] for the bulk of the algorithm
            bang_expr();
            break;
        case 2: // iterate cell-by-cell through the matrices
            bang_iter();
            break;
        default:
        	bang_op();
            break;
	    }

	    outlet(0,"jit_matrix",particlemat.getName());
	}

	public void bang_op(){
		//int plane = 0;


		for(int i =0;i<ATTRACTOR_COUNT;i++){
			scalarmat.setall(attmat.getcell1d(i));
			tempmat.op("-", scalarmat, particlemat);
			distmat.op("*", tempmat, tempmat);

			//summat.planemap = 0;
			summat.setAttr("planemap", 0);
			summat.frommatrix(distmat);
			summat.setAttr("planemap", 1);
			summat.frommatrix(distmat);
			summat.setAttr("planemap", 2);
			summat2.frommatrix(distmat);
	        summat.op("+", summat, summat2);

	        tempmat.op("*", a);
	        // divide our distances by the sum of the distances
	        // to derive gravity for this frame:
	        tempmat.op("/", summat);
	        // add to the current velocity bearings to get the
	        // amount of motion for this frame:
	        velomat.op("+", tempmat);
		}

		particlemat.op("+", velomat);
        // reduce our velocities by the decay factor for the next frame:
        velomat.op("*", d);
	}

	public void bang_expr(){
		//not implemented yet

	}

	public void bang_iter(){
		//not implemented yet

	}

	public void particles(int v){
	    PARTICLE_COUNT = v;

	    // resize matrices
	    noisegen.setAttr("dim", PARTICLE_COUNT);
	    particlemat.setAttr("dim", PARTICLE_COUNT);
	    velomat.setAttr("dim", PARTICLE_COUNT);
	    distmat.setAttr("dim", PARTICLE_COUNT);
	    attmat.setAttr("dim",PARTICLE_COUNT);
	    tempmat.setAttr("dim", PARTICLE_COUNT);
	    summat.setAttr("dim", PARTICLE_COUNT);
	    summat2.setAttr("dim", PARTICLE_COUNT);
	    scalarmat.setAttr("dim",PARTICLE_COUNT);
	    amat.setAttr("dim",PARTICLE_COUNT);

	    init(); // re-initialize particle system
	}

	public void attractors(int v){
		ATTRACTOR_COUNT = v;

		attgen.setAttr("dim", ATTRACTOR_COUNT);

		init();
	}

	public void accel(float v){
		a = v * 0.001f;
	}

	public void decay(float v){
		d = v * 0.001f;
	}

//	public void mode(String v){
//		perform_mode = v;
//	}

	public void mode(int v){
		perform_mode = v;
	}

	public void primitive(String v){
		draw_primitive = v;
	}

	/*
	function smear(v) // turn on drawing smear by zeroing the alpha on the renderer's erase color
	{
	    if(v) {
	        // smear on (alpha=0):
	        outlet(0, "erase_color", 1., 1., 1., 0.);
	    }
	    else {
	        // smear off (alpha=0.1):
	        outlet(0, "erase_color", 1., 1., 1., 0.1);
	    }
	}
	*/

}

----------begin_max5_patcher----------
1997.3oc6ZszjiZCD9rmeEDW4nWWnG7JoRUSpJGxkbK21jxkLnwV6hAGPddj
s1+6QHA1fMHj8XXsSs6rE1FIDs95O0cqt0WdXxzkouRymZ8SVezZxju7vjIx
aUbiIk+dxzMjWCiI4xtMMLcyFZBe5LUab5qb482lQyysVSynV7TKVBaeW1R3
gqYIqVjQC4pWED.maOyBgJt56TbE3M215uKeDVjbLSW9oO3TMLOklvSHanxV
90LFItpkjcaXIwTtT.A05dN6ekcOP7B120zc7p9ZWbyu9vCEWlY37Og9hPrN
c5a8zt38RTXZbZlZpZO2F6Y6DLS7s..xC5T+afZS5VvIe2BnwAHAKasvj2Yh
S1mANUgopaweaKUIdSm1T3oYk.WIxIFcVL8YZVNKMo1.MY5gonC1QMGKd4Vt
X4rD6aeXZJzHqhSC+LMplbOYZD8oyaTR2RSN7Dxdz3RydxRJXzBlNgWJ70ey
jcw7EsBcMa9IRHsymsUszjoqxXQoIExPimr31UusOZATKZbpK1xdjP11xCyS
SiWRxdlkyVFSanJDzcRBaCgS4Lk7.s2+brMayXI7FiEMgHFi04gYoBFe8gR0
xyszRD8YVH8EVDesbrNfVML.Ui5zXgXi6qaAYyEk4zXKaKP81ZyXjqbUF.6o
9v8Dj8n0Z.u5iXCM4uSieVfigj58nM6Scu1qk0enZsbxZvkjjUSmc3SwZxpd
KMso9xrKDc2HrpSVQaEd+4+JSzWq70ouHbIrSvup2sXVBMLcmh7.MSE3IWKF
HUDPnFMf+6PC.u.M.PmFXzQ70rH56DwQd3ZHte+Hdv+eQb0v2iUB.T5EF5Dn
9n5ZW.lmQV.NJdjZsTEmUw3M8JNY0Xt7G9kdsUB7T9cv9x4u2wgjbBsoSVSC
edCOiQ5DarVlVDJnvIHklX8i8gndPk6FI6x0uOeOvaE.85hl7zUqholAU16C
8QOTgtfUfiKGpmPWfdFAH9RS3Hm9VKhGQpCzjHVFMv7yz2LBIcUaavtOjz4B
QR6K.Iw8wHm01GiYDIehw4zLqvcY4oYGYv6bBIATFRhxHnePedXcusMEdXeY
EfPGawQBCEs2tZHOcWVX0qobNa0DPhn4bVx9Mo9w8QebT+DwLF0bSgR8LKZa
pfvTJdFRaNWoFdWJ0HCkZvkI09RO9fR61934Nk+ZflN.CmNt2kJA3MkTiMTp
QWL0ofrXqb+q3Q1vAi43X3rAeSoC.dlt90+xjanXuPEpAWjZuPG90PNi.lLi
BtrYDBEn7.KmQHezPOiL1Dq26yFKrtFB00JkxaJlXpbZmSdlFsP79Egnrfv4
Yrk63JO40ywsAozUSS8jL4UwoKIwkYWe+PzXfOIGymSdoe3.FblEBQD127m1
luZGSSgdPkIUUsGkxcp.auDFXuKrTOaRin0RSpQkz.1YIMNrwjqSkgJvoUwy
EAQu1ZKIima8XTF4kEERskhrZ8nrfQV1yK+OXt0iKioIQKToTWrpu72xmx0x
SLHzs706aWWw1TUNBppMB1AoqNRX7YpDBtFft.iVrgHVf85PA+qIIQBbpTAv
RDqlDuSdFII+ozrME.LYGOcQVJmvoBaMOVVqDK6pgrwdYvZJZGpFb66qpDU6
nMxc.qt43Qw2krkD9YAnI+SCUzwQZI1yuVxt5fHB5GYN3B.7dwJbWXUO6v95
fewojnhMYKhhy11BIHi.CPQG2CEKoKTDNpnnt5DeAnUWG0feikuMl7lFDRkB
GHVEFiN.x+F63EXjWUn5zS.CNjzptbpBbturv7Tbp3crmaVnyabXJ78rc78m
05254vTfrUEYTcpSvZoEPvH.aB+c4gDU43smGzEXJfDBeeEd2KsKW0DXbE+y
aVqeCTEv6YpLZl3uCK.ingj2NjoOcfsJZC7IIquAXCOSvF9sylz.xOgXTM9o
i1i6CD8c9Y27SRXHMVO+rBrK4mPs7S78C+TL3KoYCi8SU4d8jdc7zSOctcnm
kwr89HmU6zjkv1HV9WHw2VJmR9rR43pcKdP2uqbNGiIbwtDC4oY483wq7zPn
b7oNlHcZQw69whRW3RwVoYgwzbyLzVBK5CDv+9GV56jOqRFixsCRKIAgtib6
z9Fa275mr9iW+ychUOBgF6trkCHMPc7a8CrAAtxCha425yhW4AhVktEerNSd
H780tf5hbUbhj0wtTXAHPBFP8rKm6d1UwdkegkDk9hJudS66fzWF5BTKUw6a
AU4niDy0Ae3VKE+QyH4zdSlfBZTmBsNglgLYIn9flpOUymAHEwYzjHZVUJhk
ulEp7xClW9e643dQRn5jq.70ikA2ezrFGROM.fJ+21UWasLC1ZmjFZM4ZmG1
+YCkmkZA6cJpVmf05yAC9VXfsLR5ZXhT1ZdFjTPzwEqsDnNs7+MJ9ZWmjglc
5jpy1dQ+OQsYpLgvFHSX73JStlfSAiqL4eiJSvaLYJv.bB3LpxTwA1B0iHAA
cHRfASj.8IRNitH0GYB5OphTgys9MNAFUxzQutNVz4O5D79DIn6np5flXCGN
tvDDYhLMt95fFo6fiqL4XhLMtwo.MwsxnxvQlfRH2avn47F+nT5yWG5LW0g8
jm.QO0NjPA6+06klYTH5movhPtR4SkW6JoE589kV7.HsPG3.gsvg.aANCjz5
OfX6UmIfPCfzdztee3qO7ePT8obF
-----------end_max5_patcher-----------


So the controversy continues…

For sure one of the most interesting and elusive topics I have dealt with the last months has been the idea of porting processing libraries to jitter. I’ve gotten a lot of feedback from different friends that are( by far) more proficient java users.
But first an important question: why bothering porting libraries from an applet-based programing language into jitter. Many possible answers can be given, some of them as simple as to say it is an interesting challenge. However, the tool of having java inside jitter provides an interesting window to some of the functionalities that are not ‘native’ to the way jitter handles visuals. Let’s put as a very simple example the traer physics engine: it is a very simple and elegant way to handle physical modeling. So why not using such nice facility within jitter?
Second interesting point to deal with is the way things should be implemented. As far as my understanding goes jitter manages only planar arrays( not multidimensional). There are two basic methods to assign the value of each one of the members:
-copyArrayToVectorPlanar
-setcell

so far I am not sure which one of the methods is better as both methods seem to be quite efficient their usage criteria falls more into specific needs.
Take the next example:
case 1-a random cluster of lines. Then to have something like this on the bang() method:


		int plane=0;
		int dim=0;
		int[] offset=new int[]{0};
		int count=amount;
		int arrayoffset=0;

		for(int i=0;i<amount;i++){
			x[i]=(float)Math.random()-0.5f;
			y[i]=(float)Math.random()-0.5f;
			z[i]=(float)Math.random()-0.5f;
		}

		gl1.copyArrayToVectorPlanar(plane,dim,offset,x,count,arrayoffset);
		plane=1;
		gl1.copyArrayToVectorPlanar(plane,dim,offset,y,count,arrayoffset);
		plane=2;
		gl1.copyArrayToVectorPlanar(plane,dim,offset,z,count,arrayoffset);

from here it would be easier to use the sketch object providing ‘raw’ gl commands. Notice that each plane is filled with an array of values coming from the for loop( don’t forget to declare your arrays or containers!).

case 2- using a wrapper to gain a more ‘literal’ version of the processing original patch into jitter’s matrixland. So for instance:

    public void toMatrix(JitterMatrix jm) {
        if (jm == null) { return;}
        final int size = (jm.getDim()[0] >= _particles.size()) ? _particles.size() : jm.getDim()[0] ;
        if (_particles.isEmpty()) {
            populateParticleList();
        }
        Vector3D vec = null;

        for (int i = 0; i < size; i++) {
            vec = _particles.get(i).position();
            pos[0] = i;
            jm.setcell(pos, 0,(vec.x() - 200.0f) / 200.0f );
            jm.setcell(pos, 1,(vec.y() - 200.0f) / 200.0f );
            jm.setcell(pos, 2,(vec.z() - 200.0f) / 200.0f );
        }
    }
    /**
     * run once in setup, after all elements of the system are created
     */
    protected final void populateParticleList() {
        for (int i = 0; i < _ps.numberOfParticles(); i++) {
            //
            _particles.add(i, _ps.getParticle(i));
        }
    }

So far I am still trying to put my hands on this approach( thanks Panos for the eye opener!). Not sure if this is more efficient or easier( this type of implementation relies deeply on overriding methods).

We will see, I will try to post more examples as soon as I can!

P.S.By opening the source of the traer physics I was kinda of amazed how old the java lang used on the package seemed to be. There are not even containers on them! Still the library is super cool!

Page 1 of 212