Cinder++::Cinder Creative Coding Cookbook 2

Bookmark and Share

Continue reviewing the book Cinder Creative Coding Cookbook. In chapter two, the writers provides simple recipes that can be very useful in a project.

The Chapter two covers:
_Setting up a GUI for tweaking parameters.
_Saving and loading configurations
_Making a snapshot of the current parameter state
_Using MayaCamUI
_Using 3D space guides
_Communicating with other software
_Preparing your application for iOS.

Nevertheless I’m going to focus in the creation of graphical user interface (GUI) to control the geometry in a 3D space.

CINDER 3D SPACE
Whe we creates 3D models in the computer, they really exists in a 3D space. But The digital magic in somewhere transform the model into a 2D image that can be showed in the screen. The frustum is a region of space similar to cameras. The frustum takes care of display all the 3D objects that are inside in of the area. And is the responsible for creating the 2D image on the screen.

frustumblog

Red spheres, outside of the frustum are going to be ignored. In the other hand the green spheres are going to be displayed on the screen.

Cinder use OpenGL to manage the 3D coordinates of the objects to the 2D scene in the screen. And three types of matrix are used in the process. the model matrix, the view matrix and the projection matrix. The model matrix maps the object coordinates. The view matrix maps to the camera space. and the projection maps to the scene 2D. The coordinate system in Cinder is similar to processing.

CinderCSblog
The origin is in the top-left corner of the screen. But the OpenGl Coordinates are quite different. The good thing is the Built-in OpenGL drawing functions in Cinder takes care of the mapping.

DRAWING 3D

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include "cinder/app/AppNative.h"
#include "cinder/app/AppNative.h"
#include "cinder/gl/gl.h"
#include "cinder/params/Params.h" //include the interface...
 
using namespace ci;
using namespace ci::app;
using namespace std;
 
class BaseInterfaceApp : public AppNative {
  public:
	void setup();
	void mouseDown( MouseEvent event );	
	void update();
	void draw();
 
	//fields.
	int numCubes;
	float myDef;
	ColorA clrRing;
 
	Quatf myOrientCube;
	ColorA clrCube;
 
	//interfaceGL
	params::InterfaceGl userParams;	//declare the InterfaceGL class member
 
};
 
void BaseInterfaceApp::setup()
{
	myDef = 12;
	numCubes = 10;
 
	/*
	A 3D model has vertices and faces that are placed at different depths in the
	current projection. to create a sorted system of vertices, faces at different
	depths we call enableDepthRead();
	*/
	gl::enableDepthRead();
	userParams = params::InterfaceGl("Basic parameters", Vec2i(200, 400)); 
	userParams.addParam("Number", &numCubes, "min=3 max=50 step=1 keyIncr=n keyDecr=N"); 
	userParams.addParam("smooth", &myDef, "min=1 max=200 step=1 keyIncr=z keyDecr=Z");
	userParams.addParam("color", &clrRing);
 
	userParams.addSeparator("CUBE controls");
	userParams.addParam("rotation ", &myOrientCube);
}
 
void BaseInterfaceApp::mouseDown( MouseEvent event )
{
}
 
void BaseInterfaceApp::update()
{
}
 
void BaseInterfaceApp::draw()
{
	gl::clear( Color( 0, 0, 0 ) );
 
	//translate the 3D world to the center of the screen...
	//so now we can rotate, scale and so on.
	gl::translate( Vec3f(getWindowWidth()/2,getWindowHeight()/2,0) );
	int i;
 
	/*
	this loop is for the spheres:
	If we want the geometry in a constant rotation the rotate() function
	works similar to the translate() function. Per each turn we are modifying
	the modelview matrix. and is not easy to undo this.
 
	Each estate has a copy of the current transformation matrices. If we call the
	pushModelView() we make a copy of the current modelview matrix. Later we can
	make something scary and call the popModelView(), that deletes the current
	modelview matrix and return the model to the previous state.
 
	*/
	for(int i = 0 ; i < numCubes; i++)
	{
		gl::pushModelView();
		gl::color(clrRing);
		gl::rotate(Vec3f::zAxis() * (360.f / numCubes* i));
		gl::drawSphere(Vec3f(200, 0, 0), 25, myDef);
		gl::popModelView();
	}
 
 
	gl::rotate(myOrientCube);
	gl::drawColorCube( Vec3f::zero(), Vec3f(100,100,100) );
 
	/*translate again to put back again the scene...
	We have to call the function again because each time we call translate() the
	values are added instead replaced.*/
	gl::translate( Vec3f(-getWindowWidth()/2,-getWindowHeight()/2,0) );
 
	userParams.draw(); //draw the Interface.
 
}
 
CINDER_APP_NATIVE( BaseInterfaceApp, RendererGl )

cinder result
 
PD: On page 35 there is a silly mistake: Instead of params::InterfaceGL::draw() should be mParams.draw();

1 Comment

  • mocno Jun 11, 2015, 22:04

    Good article. I will be dealing with a few of these issues
    as well..

Leave a Reply