void init(void)
{
    // initialize vector arrays
    Vector3D::arr = new float[3];
    Vector4D::arr = new float[4];
    Camera::viewMatrix = new float[16];

    /*************CAMERA****************/
    // initializam camera principala
    camera = new Camera();
    camera->type=CameraTypeFPS;
    camera->SetPosition(Vector3D(0,5,15));
    camera->SetForwardVector(Vector3D(0,0,-1));
    camera->SetUpVector(Vector3D(0,1,0));
    camera->SetRightVector(Vector3D(1,0,0));
    // pozitionare camera
    camera->Render();

    /*************OBIECTE****************/
    objects = new Object3D*[MAX_OBJECT_COUNT];
    Object3D *newObject;
    //TODO: Creaza obiecte

    // creaza si seteaza obiectul
    newObject = new Plane(10);
    newObject->setColor(Vector3D(0,0.2,0));
    newObject->setLevelOfDetail(1);
    newObject->setSelectable(true);
    objects[objectCount++]=newObject;

    /*************SISTEME PARTICULE****************/
    textura=LoadTextureBMP("snow.bmp",TEXTURA_FILTRARE_TRILINEAR_ANISOTROPIC);
    textura1=LoadTextureBMP("spark.bmp",TEXTURA_FILTRARE_TRILINEAR_ANISOTROPIC);
    pcamera=new MyParticleCamera(camera);
    pcamera->notifyCameraChange();
    manager=new ParticleManager();
    generateTest(currentTest);

    /*************INITIALIZARE SCENA****************/
    glClearColor(0.0, 0.0, 0.0, 0.0);	// stergem tot
    glEnable(GL_DEPTH_TEST);			// activam verificarea distantei fata de camera (a adancimii)
    glShadeModel(GL_SMOOTH);			// shading model: mod de desenare SMOOTH
    //glEnable(GL_LIGHTING);				// activam iluminarea
    glEnable(GL_NORMALIZE);				// activam normalizarea normalelor
    //glLightModelfv(GL_LIGHT_MODEL_AMBIENT,(Vector4D(0.1,0.1,0.1,1)).Array());	// lumina ambientala
    glEnable(GL_ALPHA_TEST);			// activam testarea parametrului alfa, pentru a permite transparenta
}
/**
 * Construct the scene
 */
void ConstructScene()
{
   // -------------------- Geometry -------------------- //
   movingSquare = new UnitSquareFlatSurface(200,32.2f*.814f,true,Vector2(-.01f,0),.03f);

   SceneNode* house = ConstructHouse(70,90);

   // Construct a unit cylinder surface
   WasherSurface* cylinder = new WasherSurface(.9f, 1.0f, 18);
   
   //Wheel
   WasherSurface* washer = new WasherSurface(10,20,14);
   std::vector<LightNode*> lights;
   lights.push_back(new LightNode(GL_LIGHT3));
   lights.push_back(new LightNode(GL_LIGHT4));
   wheel = new WheelNode(10,20,washer,ConstructBox(9,19.5f,1),8,4,lights);

   waterfall = new ParticleNode(25);

   //-------------------- Materials ------------------------- //

   // Wood
   PresentationNode* wood = new PresentationNode;
   wood->SetMaterialAmbientAndDiffuse(Color4(0.5f, 0.5f, 0.5f));
   wood->SetMaterialSpecular(Color4(0.3f, 0.3f, 0.3f));
   wood->SetMaterialShininess(32.0f);
   wood->setTexture(LoadTextureBMP("images/wood.bin",true,128));

   // Stone
   PresentationNode* stone = new PresentationNode;
   stone->SetMaterialAmbient(Color4(0.19225f, 0.19225f, 0.19225f));
   stone->SetMaterialDiffuse(Color4(0.50754f, 0.50754f, 0.50754f));
   stone->SetMaterialSpecular(Color4(0.508273f, 0.508273f, 0.508273f));
   stone->SetMaterialShininess(10.2f);
   stone->setTexture(LoadTextureBMP("images/stone.bin",true,128));

   PresentationNode* steel = new PresentationNode;
   steel->SetMaterialAmbient(Color4(0.19225f, 0.19225f, 0.19225f));
   steel->SetMaterialDiffuse(Color4(0.7f, 0.7f, 0.7f));
   steel->SetMaterialSpecular(Color4(0.7f, 0.7f, 0.7f));
   steel->SetMaterialShininess(90.2f);

   // Water
   PresentationNode* water = new PresentationNode;
   water->SetMaterialAmbient(Color4(0.01f, 0.01f, 0.1f));
   water->SetMaterialDiffuse(Color4(0.2f, 0.2f, 0.6f));
   water->SetMaterialSpecular(Color4(0.5f, 0.5f, 0.5f));
   water->SetMaterialShininess(10);
   water->setTexture(LoadTextureBMP("images/water.bin",true,128));

   PresentationNode* blue = new PresentationNode;
   blue->SetMaterialAmbient(Color4(0.01f, 0.01f, 0.1f));
   blue->SetMaterialDiffuse(Color4(0.2f, 0.2f, 0.6f));
   blue->SetMaterialSpecular(Color4(0.5f, 0.5f, 0.5f));
   blue->SetMaterialShininess(10);
   // ------------------ Transformations ------------------- //
   TransformNode* wheelTransform = new TransformNode;
   wheelTransform->Translate(-80.0f, 35.0f, 40.0f);
   wheelTransform->Rotate(90.0f, 1.0f, 0.0f, 0.0f);

   TransformNode* houseTransform = new TransformNode;
   houseTransform->Translate(-100,35,0);

   TransformNode* house2Transform = new TransformNode;
   house2Transform->Rotate(180,0,0,1);
   house2Transform->Translate(-100,-35,0);

   TransformNode* wallTransform = new TransformNode;
   wallTransform->Translate(0,35,0);

   TransformNode* waterfallTransform = new TransformNode;
   waterfallTransform->Translate(-128.0f,35,15.0f);

   TransformNode* pipeTransform = new TransformNode;
   pipeTransform->Rotate(-90,0,1,0);
   pipeTransform->Translate(76.5f,35,125);
   pipeTransform->Scale(5,5,20);

   // -------------------- Lighting --------------------------/

   // Light 0 - point light source in back right corner
	LightNode* light0 = new LightNode(GL_LIGHT0);
	light0->SetDiffuse(Color4(0.5f, 0.5f, 0.5f, 1.0f));
	light0->SetSpecular(Color4(0.5f, 0.5f, 0.5f, 1.0f));
	light0->SetPosition(HPoint3(90.0f, 90.0f, 30.f, 1.0f));	
	light0->Enable();

   // Light1 - directional light from the ceiling
	LightNode* light1 = new LightNode(GL_LIGHT1);
	light1->SetDiffuse(Color4(0.7f, 0.7f, 0.7f, 1.0f ));
	light1->SetSpecular(Color4(0.7f, 0.7f, 0.7f, 1.0f));
	light1->SetPosition(HPoint3(0.0f, 0.0f, 1.0f, 0.0f));	
	light1->Enable();

   // Light2 - spotlight - we will place at the camera location
   // shining along -VPN
	LightNode* light2 = new LightNode(GL_LIGHT2);
	light2->SetDiffuse(Color4(0.8f, 0.8f, 0.8f, 1.0f ));
	light2->SetSpecular(Color4(0.8f, 0.8f, 0.8f, 1.0f));
	light2->SetPosition(HPoint3(0.0f, 0.0f, 0.0f, 1.0f));	
	light2->SetSpotlight(Vector3(0.0f, 0.0f, -1.0f), 32.0f, 30.0f);
	light2->Enable();

	lights[0]->SetDiffuse(Color4(0.8f, 0.8f, 0.8f, 1.0f));
	lights[0]->SetSpecular(Color4(0.8f, 0.8f, 0.8f, 1.0f));
	lights[0]->SetPosition(HPoint3(-100.0f,35.0f,90.0f,1.0f));
	lights[0]->SetSpotlightDirection(Vector3(0,0,-1));
	lights[0]->SetSpotlight(Vector3(0,0,-1),1,90);
	lights[0]->Disable();

	lights[1]->SetDiffuse(Color4(0.8f, 0.8f, 0.8f, 1.0f));
	lights[1]->SetSpecular(Color4(0.8f, 0.8f, 0.8f, 1.0f));
	lights[1]->SetPosition(HPoint3(100.0f,35.0f,90.0f,1.0f));
	lights[1]->SetSpotlightDirection(Vector3(0,0,-1));
	lights[1]->SetSpotlight(Vector3(0,0,-1),1,90);
	lights[1]->Disable();
  
   // --------------------------- Camera ----------------------- //
   MyCamera = new CameraNode;
   MyCamera->SetPosition(Point3(100.0f, -100.0f, 50.0f));
   MyCamera->SetLookAtPt(Point3(0.0f, 0.0f, 50.0f));
   MyCamera->SetViewUp(Vector3(0.0, 0.0, 1.0));
   MyCamera->SetPerspective(50.0, 1.0, 1.0, 2400);

   // --------------------- Scene construction ----------------- //

   // Construct the scene root node
   SceneRoot = new SceneNode;

   // Create a scene node to hold all scene objects (other than camera
   // and lights)
   SceneNode* myScene = new SceneNode;

   // Add the spotlight as the first child of the root node. Since this is 
   // accessed before the camera it will position the light relative to the
   // camera
   SceneRoot->AddChild(light2);

   // Set the camera

	SceneRoot->AddChild(MyCamera);
	MyCamera->AddChild(light0);
	MyCamera->AddChild(light1);
	MyCamera->AddChild(lights[0]);
	MyCamera->AddChild(lights[1]);
	MyCamera->AddChild(myScene);

   // Construct the room (walls, floor, ceiling)
	SceneNode* skybox = ConstructRoom();

   wallTransform->AddChild(ConstructWall(stone,water,movingSquare));
   myScene->AddChild(wallTransform);

   // Construct the wheel
   AddSubTree(myScene,wood,wheelTransform,wheel);

    // Place 2 Houses
   wood->AddChild(houseTransform);
   houseTransform->AddChild(house);
   wood->AddChild(house2Transform);
   house2Transform->AddChild(house);
   myScene->AddChild(skybox);

   AddSubTree(myScene,steel,pipeTransform,cylinder);
   AddSubTree(myScene,blue,waterfallTransform,waterfall);
}
/**
 * Construct a room. Like a box but looking inward with a texture for each side
 */
SceneNode* ConstructRoom() {
	GLuint textures[6];
	textures[0]=LoadTextureBMP("images/skybox0.bin",true,256);
	textures[1]=LoadTextureBMP("images/skybox1.bin",true,256);
	textures[2]=LoadTextureBMP("images/skybox2.bin",true,256);
	textures[3]=LoadTextureBMP("images/skybox3.bin",true,256);
	textures[4]=LoadTextureBMP("images/skybox4.bin",true,256);
	textures[5]=LoadTextureBMP("images/skybox5.bin",true,256);

	SceneNode* skybox = new SceneNode;
	int SKYBOX_SIZE=2000;
	int HEIGHT = 800;
	int HALF_HEIGHT = HEIGHT * .5f;
	int HALF_SKYBOX = SKYBOX_SIZE * .5f;
	UnitSquareFlatSurface* unitSquare = new UnitSquareFlatSurface(SKYBOX_SIZE,
		SKYBOX_SIZE,true,Vector2(),.01);
	TransformNode* transform[6];

	UnitSquareFlatSurface* wall = new UnitSquareFlatSurface(1,1,true,Vector2(),1);

	// Construct transform nodes for the walls. Perform rotations so the 
	// walls face inwards
	transform[0] = new TransformNode;
	//transform[0]->Scale(SKYBOX_SIZE,SKYBOX_SIZE,1);

	// Back wall is rotated +90 degrees about x: (y -> z)
	transform[1] = new TransformNode;
	transform[1]->Translate(0.0f, HALF_SKYBOX, HALF_HEIGHT);
	transform[1]->Scale(SKYBOX_SIZE,1,HEIGHT);
	transform[1]->Rotate(90.0f, 1.0f, 0.0f, 0.0f);   

	// Front wall is rotated -90 degrees about x: (z -> y)
	transform[2] = new TransformNode;
	transform[2]->Translate(0.0f, -HALF_SKYBOX, HALF_HEIGHT);
	transform[2]->Scale(SKYBOX_SIZE,1,HEIGHT);
	transform[2]->Rotate(-90.0f, 1.0f, 0.0f, 0.0f); 

	// Left wall is rotated 90 degrees about y: (z -> x)
	transform[3] = new TransformNode;
	transform[3]->Translate(-HALF_SKYBOX, 0.0f, HALF_HEIGHT);
	transform[3]->Scale(1,SKYBOX_SIZE,HEIGHT);
	transform[3]->Rotate(90.0f, 0.0f, 1.0f, 0.0f);

	// Right wall is rotated -90 about y: (z -> -x)
	transform[4]= new TransformNode;
	transform[4]->Translate(HALF_SKYBOX, 0.0f, HALF_HEIGHT);
	transform[4]->Scale(1,SKYBOX_SIZE,HEIGHT);
	transform[4]->Rotate(-90.0f, 0.0f, 1.0f, 0.0f);

	// Ceiling is rotated 180 about x so it faces inwards
	transform[5]= new TransformNode;
	transform[5]->Translate(0.0f, 0.0f, HEIGHT);
	transform[5]->Scale(SKYBOX_SIZE,SKYBOX_SIZE,1);
	transform[5]->Rotate(180.0f, 1.0f, 0.0f, 0.0f);

	for(int i=0;i<6;i++){
		PresentationNode* tex = new PresentationNode();
		tex->SetMaterialAmbientAndDiffuse(Color4(0.8f, 0.8f, 0.8f));
		tex->SetMaterialSpecular(Color4(0.3f, 0.3f, 0.3f));
		tex->SetMaterialShininess(32.0f);
		tex->setTexture(textures[i]);
		tex->AddChild(transform[i]);
		transform[i]->AddChild(i==0 ? unitSquare : wall);
		skybox->AddChild(tex);
	}
	return skybox;
}