Browse Source

Add support for interlaced polarized 3d screens
Add (experimental) support for topbottom as well as sidebyside 3d mode

sapier 10 years ago
parent
commit
09970b7b6d
17 changed files with 909 additions and 423 deletions
  1. 9 3
      minetest.conf.example
  2. 1 0
      src/CMakeLists.txt
  3. 52 27
      src/camera.cpp
  4. 21 4
      src/camera.h
  5. 5 6
      src/client.cpp
  6. 4 4
      src/clientmap.cpp
  7. 2 1
      src/clientmap.h
  8. 183 114
      src/content_cao.cpp
  9. 2 2
      src/defaultsettings.cpp
  10. 529 0
      src/drawscene.cpp
  11. 37 0
      src/drawscene.h
  12. 30 234
      src/game.cpp
  13. 0 4
      src/hud.cpp
  14. 3 3
      src/localplayer.cpp
  15. 12 2
      src/localplayer.h
  16. 15 15
      src/sky.cpp
  17. 4 4
      src/sky.h

+ 9 - 3
minetest.conf.example

@@ -127,9 +127,15 @@
 #view_bobbing_amount = 1.0
 # Amount of fall bobbing (0 = no fall bobbing, 1.0 = normal, 2.0 = double)
 #fall_bobbing_amount = 0.0
-# Anaglyph stereo
-#anaglyph = false
-#anaglyph_strength = 0.1
+# 3d support,
+# right now:
+#     "none"       = no 3d output,
+#     "anaglyph"   = cyan/magenta color 3d,
+#     "interlaced" = odd/even line based polarisation screen support,
+#     "topbottom"  = split screen top boton,
+#     "sidebyside" = split screen side by side
+#3d_mode = none
+#3d_paralax_strength = 0.025
 # In-game chat console background color (R,G,B)
 #console_color = (0,0,0)
 # In-game chat console background alpha (opaqueness, between 0 and 255)

+ 1 - 0
src/CMakeLists.txt

@@ -460,6 +460,7 @@ set(minetest_SRCS
 	guiEngine.cpp
 	guiFileSelectMenu.cpp
 	convert_json.cpp
+	drawscene.cpp
 	${minetest_SCRIPT_SRCS}
 )
 

+ 52 - 27
src/camera.cpp

@@ -82,7 +82,9 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control,
 	m_wield_change_timer(0.125),
 	m_wield_mesh_next(NULL),
 	m_previous_playeritem(-1),
-	m_previous_itemname("")
+	m_previous_itemname(""),
+
+	m_camera_mode(CAMERA_MODE_FIRST)
 {
 	//dstream<<__FUNCTION_NAME<<std::endl;
 
@@ -159,8 +161,10 @@ void Camera::step(f32 dtime)
 	if(m_wield_change_timer > 0.125)
 		m_wield_change_timer = 0.125;
 
-	if(m_wield_change_timer >= 0 && was_under_zero) {
-		if(m_wield_mesh_next) {
+	if(m_wield_change_timer >= 0 && was_under_zero)
+	{
+		if(m_wield_mesh_next)
+		{
 			m_wieldnode->setMesh(m_wield_mesh_next);
 			m_wieldnode->setVisible(true);
 		} else {
@@ -189,11 +193,14 @@ void Camera::step(f32 dtime)
 #endif
 #if 1
 			// Animation is getting turned off
-			if(m_view_bobbing_anim < 0.25){
+			if(m_view_bobbing_anim < 0.25)
+			{
 				m_view_bobbing_anim -= offset;
-			} else if(m_view_bobbing_anim > 0.75){
+			} else if(m_view_bobbing_anim > 0.75) {
 				m_view_bobbing_anim += offset;
-			} if(m_view_bobbing_anim < 0.5){
+			}
+			if(m_view_bobbing_anim < 0.5)
+			{
 				m_view_bobbing_anim += offset;
 				if(m_view_bobbing_anim > 0.5)
 					m_view_bobbing_anim = 0.5;
@@ -217,7 +224,8 @@ void Camera::step(f32 dtime)
 			bool step = (was == 0 ||
 					(was < 0.5f && m_view_bobbing_anim >= 0.5f) ||
 					(was > 0.5f && m_view_bobbing_anim <= 0.5f));
-			if(step){
+			if(step)
+			{
 				MtEvent *e = new SimpleTriggerEvent("ViewBobbingStep");
 				m_gamedef->event()->put(e);
 			}
@@ -237,10 +245,11 @@ void Camera::step(f32 dtime)
 		float lim = 0.15;
 		if(m_digging_anim_was < lim && m_digging_anim >= lim)
 		{
-			if(m_digging_button == 0){
+			if(m_digging_button == 0)
+			{
 				MtEvent *e = new SimpleTriggerEvent("CameraPunchLeft");
 				m_gamedef->event()->put(e);
-			} else if(m_digging_button == 1){
+			} else if(m_digging_button == 1) {
 				MtEvent *e = new SimpleTriggerEvent("CameraPunchRight");
 				m_gamedef->event()->put(e);
 			}
@@ -249,8 +258,7 @@ void Camera::step(f32 dtime)
 }
 
 void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime,
-		f32 tool_reload_ratio,
-		int current_camera_mode, ClientEnvironment &c_env)
+		f32 tool_reload_ratio, ClientEnvironment &c_env)
 {
 	// Get player position
 	// Smooth the movement when walking up stairs
@@ -278,7 +286,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime,
 
 	// Fall bobbing animation
 	float fall_bobbing = 0;
-	if(player->camera_impact >= 1 && current_camera_mode < CAMERA_MODE_THIRD)
+	if(player->camera_impact >= 1 && m_camera_mode < CAMERA_MODE_THIRD)
 	{
 		if(m_view_bobbing_fall == -1) // Effect took place and has finished
 			player->camera_impact = m_view_bobbing_fall = 0;
@@ -297,7 +305,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime,
 
 	// Calculate players eye offset for different camera modes
 	v3f PlayerEyeOffset = player->getEyeOffset();
-	if (current_camera_mode == CAMERA_MODE_FIRST)
+	if (m_camera_mode == CAMERA_MODE_FIRST)
 		PlayerEyeOffset += player->eye_offset_first;
 	else
 		PlayerEyeOffset += player->eye_offset_third;
@@ -312,7 +320,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime,
 	v3f rel_cam_target = v3f(0,0,1);
 	v3f rel_cam_up = v3f(0,1,0);
 
-	if (m_view_bobbing_anim != 0 && current_camera_mode < CAMERA_MODE_THIRD)
+	if (m_view_bobbing_anim != 0 && m_camera_mode < CAMERA_MODE_THIRD)
 	{
 		f32 bobfrac = my_modf(m_view_bobbing_anim * 2);
 		f32 bobdir = (m_view_bobbing_anim < 0.5) ? 1.0 : -1.0;
@@ -365,16 +373,17 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime,
 	v3f my_cp = m_camera_position;
 	
 	// Reposition the camera for third person view
-	if (current_camera_mode > CAMERA_MODE_FIRST) {
-		
-		if (current_camera_mode == CAMERA_MODE_THIRD_FRONT)
+	if (m_camera_mode > CAMERA_MODE_FIRST)
+	{
+		if (m_camera_mode == CAMERA_MODE_THIRD_FRONT)
 			m_camera_direction *= -1;
 
 		my_cp.Y += 2;
 
 		// Calculate new position
 		bool abort = false;
-		for (int i = BS; i <= BS*2; i++) {
+		for (int i = BS; i <= BS*2; i++)
+		{
 			my_cp.X = m_camera_position.X + m_camera_direction.X*-i;
 			my_cp.Z = m_camera_position.Z + m_camera_direction.Z*-i;
 			if (i > 12)
@@ -384,7 +393,8 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime,
 			INodeDefManager *nodemgr = m_gamedef->ndef();
 			MapNode n = c_env.getClientMap().getNodeNoEx(floatToInt(my_cp, BS));
 			const ContentFeatures& features = nodemgr->get(n);
-			if(features.walkable) {
+			if(features.walkable)
+			{
 				my_cp.X += m_camera_direction.X*-1*-BS/2;
 				my_cp.Z += m_camera_direction.Z*-1*-BS/2;
 				my_cp.Y += m_camera_direction.Y*-1*-BS/2;
@@ -413,7 +423,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime,
 	m_cameranode->setTarget(my_cp-intToFloat(m_camera_offset, BS) + 100 * m_camera_direction);
 
 	// update the camera position in front-view mode to render blocks behind player
-	if (current_camera_mode == CAMERA_MODE_THIRD_FRONT)
+	if (m_camera_mode == CAMERA_MODE_THIRD_FRONT)
 		m_camera_position = my_cp;
 
 	// Get FOV setting
@@ -439,7 +449,8 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime,
 		wield_position.Y -= 40 + m_wield_change_timer*320;
 	else
 		wield_position.Y -= 40 - m_wield_change_timer*320;
-	if(m_digging_anim < 0.05 || m_digging_anim > 0.5){
+	if(m_digging_anim < 0.05 || m_digging_anim > 0.5)
+	{
 		f32 frac = 1.0;
 		if(m_digging_anim > 0.5)
 			frac = 2.0 * (m_digging_anim - 0.5);
@@ -468,8 +479,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime,
 		quat_slerp.slerp(quat_begin, quat_end, sin(digfrac * M_PI));
 		quat_slerp.toEuler(wield_rotation);
 		wield_rotation *= core::RADTODEG;
-	}
-	else {
+	} else {
 		f32 bobfrac = my_modf(m_view_bobbing_anim);
 		wield_position.X -= sin(bobfrac*M_PI*2.0) * 3.0;
 		wield_position.Y += sin(my_modf(bobfrac*2.0)*M_PI) * 3.0;
@@ -654,12 +664,14 @@ void Camera::wield(const ItemStack &item, u16 playeritem)
 	std::string itemname = item.getDefinition(idef).name;
 	m_wield_mesh_next = idef->getWieldMesh(itemname, m_gamedef);
 	if(playeritem != m_previous_playeritem &&
-			!(m_previous_itemname == "" && itemname == "")) {
+			!(m_previous_itemname == "" && itemname == ""))
+	{
 		m_previous_playeritem = playeritem;
 		m_previous_itemname = itemname;
 		if(m_wield_change_timer >= 0.125)
 			m_wield_change_timer = -0.125;
-		else if(m_wield_change_timer > 0) {
+		else if(m_wield_change_timer > 0)
+		{
 			m_wield_change_timer = -m_wield_change_timer;
 		}
 	} else {
@@ -670,7 +682,8 @@ void Camera::wield(const ItemStack &item, u16 playeritem)
 			m_wieldnode->setVisible(false);
 		}
 		m_wield_mesh_next = NULL;
-		if(m_previous_itemname != itemname) {
+		if(m_previous_itemname != itemname)
+		{
 			m_previous_itemname = itemname;
 			m_wield_change_timer = 0;
 		}
@@ -679,7 +692,7 @@ void Camera::wield(const ItemStack &item, u16 playeritem)
 	}
 }
 
-void Camera::drawWieldedTool()
+void Camera::drawWieldedTool(irr::core::matrix4* translation)
 {
 	// Set vertex colors of wield mesh according to light level
 	u8 li = m_wieldlight;
@@ -695,5 +708,17 @@ void Camera::drawWieldedTool()
 	cam->setFOV(72.0*M_PI/180.0);
 	cam->setNearValue(0.1);
 	cam->setFarValue(100);
+	if (translation != NULL)
+	{
+		irr::core::matrix4 startMatrix = cam->getAbsoluteTransformation();
+		irr::core::vector3df focusPoint = (cam->getTarget()
+				- cam->getAbsolutePosition()).setLength(1)
+				+ cam->getAbsolutePosition();
+
+		irr::core::vector3df camera_pos =
+				(startMatrix * *translation).getTranslation();
+		cam->setPosition(camera_pos);
+		cam->setTarget(focusPoint);
+	}
 	m_wieldmgr->drawAll();
 }

+ 21 - 4
src/camera.h

@@ -33,7 +33,7 @@ class LocalPlayer;
 struct MapDrawControl;
 class IGameDef;
 
-enum CameraModes {CAMERA_MODE_FIRST, CAMERA_MODE_THIRD, CAMERA_MODE_THIRD_FRONT};
+enum CameraMode {CAMERA_MODE_FIRST, CAMERA_MODE_THIRD, CAMERA_MODE_THIRD_FRONT};
 
 /*
 	Client camera class, manages the player and camera scene nodes, the viewing distance
@@ -117,8 +117,7 @@ public:
 	// Update the camera from the local player's position.
 	// busytime is used to adjust the viewing range.
 	void update(LocalPlayer* player, f32 frametime, f32 busytime,
-			f32 tool_reload_ratio,
-			int current_camera_mode, ClientEnvironment &c_env);
+			f32 tool_reload_ratio, ClientEnvironment &c_env);
 
 	// Render distance feedback loop
 	void updateViewingRange(f32 frametime_in, f32 busytime_in);
@@ -133,7 +132,23 @@ public:
 	// Draw the wielded tool.
 	// This has to happen *after* the main scene is drawn.
 	// Warning: This clears the Z buffer.
-	void drawWieldedTool();
+	void drawWieldedTool(irr::core::matrix4* translation=NULL);
+
+	// Toggle the current camera mode
+	void toggleCameraMode() {
+		if (m_camera_mode == CAMERA_MODE_FIRST)
+			m_camera_mode = CAMERA_MODE_THIRD;
+		else if (m_camera_mode == CAMERA_MODE_THIRD)
+			m_camera_mode = CAMERA_MODE_THIRD_FRONT;
+		else
+			m_camera_mode = CAMERA_MODE_FIRST;
+	}
+
+	//read the current camera mode
+	inline CameraMode getCameraMode()
+	{
+		return m_camera_mode;
+	}
 
 private:
 	// Nodes
@@ -196,6 +211,8 @@ private:
 	scene::IMesh *m_wield_mesh_next;
 	u16 m_previous_playeritem;
 	std::string m_previous_itemname;
+
+	CameraMode m_camera_mode;
 };
 
 #endif

+ 5 - 6
src/client.cpp

@@ -51,6 +51,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "util/directiontables.h"
 #include "util/pointedthing.h"
 #include "version.h"
+#include "drawscene.h"
+
+extern gui::IGUIEnvironment* guienv;
 
 /*
 	QueuedMeshUpdate
@@ -2648,10 +2651,6 @@ float Client::mediaReceiveProgress()
 		return 1.0; // downloader only exists when not yet done
 }
 
-void draw_load_screen(const std::wstring &text,
-		IrrlichtDevice* device, gui::IGUIFont* font,
-		float dtime=0 ,int percent=0, bool clouds=true);
-
 void Client::afterContentReceived(IrrlichtDevice *device, gui::IGUIFont* font)
 {
 	infostream<<"Client::afterContentReceived() started"<<std::endl;
@@ -2680,7 +2679,7 @@ void Client::afterContentReceived(IrrlichtDevice *device, gui::IGUIFont* font)
 	{
 		verbosestream<<"Updating item textures and meshes"<<std::endl;
 		wchar_t* text = wgettext("Item textures...");
-		draw_load_screen(text,device,font,0,0);
+		draw_load_screen(text, device, guienv, font, 0, 0);
 		std::set<std::string> names = m_itemdef->getAll();
 		size_t size = names.size();
 		size_t count = 0;
@@ -2693,7 +2692,7 @@ void Client::afterContentReceived(IrrlichtDevice *device, gui::IGUIFont* font)
 			count++;
 			percent = count*100/size;
 			if (count%50 == 0) // only update every 50 item
-				draw_load_screen(text,device,font,0,percent);
+				draw_load_screen(text, device, guienv, font, 0, percent);
 		}
 		delete[] text;
 	}

+ 4 - 4
src/clientmap.cpp

@@ -856,7 +856,7 @@ int ClientMap::getBackgroundBrightness(float max_d, u32 daylight_factor,
 	return ret;
 }
 
-void ClientMap::renderPostFx()
+void ClientMap::renderPostFx(CameraMode cam_mode)
 {
 	INodeDefManager *nodemgr = m_gamedef->ndef();
 
@@ -867,8 +867,6 @@ void ClientMap::renderPostFx()
 	v3f camera_position = m_camera_position;
 	m_camera_mutex.Unlock();
 
-	LocalPlayer *player = m_client->getEnv().getLocalPlayer();
-
 	MapNode n = getNodeNoEx(floatToInt(camera_position, BS));
 
 	// - If the player is in a solid node, make everything black.
@@ -876,7 +874,9 @@ void ClientMap::renderPostFx()
 	// - Do not if player is in third person mode
 	const ContentFeatures& features = nodemgr->get(n);
 	video::SColor post_effect_color = features.post_effect_color;
-	if(features.solidness == 2 && !(g_settings->getBool("noclip") && m_gamedef->checkLocalPrivilege("noclip")) && player->camera_mode == CAMERA_MODE_FIRST)
+	if(features.solidness == 2 && !(g_settings->getBool("noclip") &&
+			m_gamedef->checkLocalPrivilege("noclip")) &&
+			cam_mode == CAMERA_MODE_FIRST)
 	{
 		post_effect_color = video::SColor(255, 0, 0, 0);
 	}

+ 2 - 1
src/clientmap.h

@@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #include "irrlichttypes_extrabloated.h"
 #include "map.h"
+#include "camera.h"
 #include <set>
 #include <map>
 
@@ -126,7 +127,7 @@ public:
 	int getBackgroundBrightness(float max_d, u32 daylight_factor,
 			int oldvalue, bool *sunlight_seen_result);
 
-	void renderPostFx();
+	void renderPostFx(CameraMode cam_mode);
 
 	// For debug printing
 	virtual void PrintInfo(std::ostream &out);

+ 183 - 114
src/content_cao.cpp

@@ -84,7 +84,8 @@ void SmoothTranslator::update(v3f vect_new, bool is_end_position, float update_i
 	aim_is_end = is_end_position;
 	vect_old = vect_show;
 	vect_aim = vect_new;
-	if(update_interval > 0){
+	if(update_interval > 0)
+	{
 		anim_time = update_interval;
 	} else {
 		if(anim_time < 0.001 || anim_time > 1.0)
@@ -582,8 +583,10 @@ GenericCAO::GenericCAO(IGameDef *gamedef, ClientEnvironment *env):
 		ClientActiveObject::registerType(getType(), create);
 }
 
-bool GenericCAO::getCollisionBox(aabb3f *toset) {
-	if (m_prop.physical) {
+bool GenericCAO::getCollisionBox(aabb3f *toset)
+{
+	if (m_prop.physical)
+	{
 		//update collision box
 		toset->MinEdge = m_prop.collisionbox.MinEdge * BS;
 		toset->MaxEdge = m_prop.collisionbox.MaxEdge * BS;
@@ -597,7 +600,8 @@ bool GenericCAO::getCollisionBox(aabb3f *toset) {
 	return false;
 }
 
-bool GenericCAO::collideWithObjects() {
+bool GenericCAO::collideWithObjects()
+{
 	return m_prop.collideWithObjects;
 }
 
@@ -635,7 +639,8 @@ void GenericCAO::initialize(const std::string &data)
 		return;
 	}
 
-	for(int i=0; i<num_messages; i++){
+	for(int i=0; i<num_messages; i++)
+	{
 		std::string message = deSerializeLongString(is);
 		processMessage(message);
 	}
@@ -643,10 +648,17 @@ void GenericCAO::initialize(const std::string &data)
 	pos_translator.init(m_position);
 	updateNodePos();
 
-	if(m_is_player){
+	if(m_is_player)
+	{
 		Player *player = m_env->getPlayer(m_name.c_str());
-		if(player && player->isLocal()){
+		if(player && player->isLocal())
+		{
 			m_is_local_player = true;
+			m_is_visible = false;
+			LocalPlayer* localplayer = dynamic_cast<LocalPlayer*>(player);
+
+			assert( localplayer != NULL );
+			localplayer->setCAO(this);
 		}
 		m_env->addPlayerName(m_name.c_str());
 	}
@@ -654,7 +666,8 @@ void GenericCAO::initialize(const std::string &data)
 
 GenericCAO::~GenericCAO()
 {
-	if(m_is_player){
+	if(m_is_player)
+	{
 		m_env->removePlayerName(m_name.c_str());
 	}
 }
@@ -668,7 +681,8 @@ core::aabbox3d<f32>* GenericCAO::getSelectionBox()
 
 v3f GenericCAO::getPosition()
 {
-	if(getParent() != NULL){
+	if(getParent() != NULL)
+	{
 		if(m_meshnode)
 			return m_meshnode->getAbsolutePosition();
 		if(m_animated_meshnode)
@@ -711,9 +725,12 @@ ClientActiveObject* GenericCAO::getParent()
 	ClientActiveObject *obj = NULL;
 	for(std::vector<core::vector2d<int> >::const_iterator cii = m_env->attachment_list.begin(); cii != m_env->attachment_list.end(); cii++)
 	{
-		if(cii->X == getId()){ // This ID is our child
-			if(cii->Y > 0){ // A parent ID exists for our child
-				if(cii->X != cii->Y){ // The parent and child ID are not the same
+		if(cii->X == getId()) // This ID is our child
+		{
+			if(cii->Y > 0) // A parent ID exists for our child
+			{
+				if(cii->X != cii->Y) // The parent and child ID are not the same
+				{
 					obj = m_env->getActiveObject(cii->Y);
 				}
 			}
@@ -730,18 +747,21 @@ void GenericCAO::removeFromScene(bool permanent)
 	if(permanent) // Should be true when removing the object permanently and false when refreshing (eg: updating visuals)
 	{
 		// Detach this object's children
-		for(std::vector<core::vector2d<int> >::iterator ii = m_env->attachment_list.begin(); ii != m_env->attachment_list.end(); ii++)
+		for(std::vector<core::vector2d<int> >::iterator ii = m_env->attachment_list.begin();
+				ii != m_env->attachment_list.end(); ii++)
 		{
 			if(ii->Y == getId()) // Is a child of our object
 			{
 				ii->Y = 0;
-				ClientActiveObject *obj = m_env->getActiveObject(ii->X); // Get the object of the child
+				// Get the object of the child
+				ClientActiveObject *obj = m_env->getActiveObject(ii->X);
 				if(obj)
 					obj->setAttachments();
 			}
 		}
 		// Delete this object from the attachments list
-		for(std::vector<core::vector2d<int> >::iterator ii = m_env->attachment_list.begin(); ii != m_env->attachment_list.end(); ii++)
+		for(std::vector<core::vector2d<int> >::iterator ii = m_env->attachment_list.begin();
+				ii != m_env->attachment_list.end(); ii++)
 		{
 			if(ii->X == getId()) // Is our object
 			{
@@ -751,15 +771,18 @@ void GenericCAO::removeFromScene(bool permanent)
 		}
 	}
 
-	if(m_meshnode){
+	if(m_meshnode)
+	{
 		m_meshnode->remove();
 		m_meshnode = NULL;
 	}
-	if(m_animated_meshnode){
+	if(m_animated_meshnode)
+	{
 		m_animated_meshnode->remove();
 		m_animated_meshnode = NULL;
 	}
-	if(m_spritenode){
+	if(m_spritenode)
+	{
 		m_spritenode->remove();
 		m_spritenode = NULL;
 	}
@@ -781,7 +804,8 @@ void GenericCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
 
 	//video::IVideoDriver* driver = smgr->getVideoDriver();
 
-	if(m_prop.visual == "sprite"){
+	if(m_prop.visual == "sprite")
+	{
 		infostream<<"GenericCAO::addToScene(): single_sprite"<<std::endl;
 		m_spritenode = smgr->addBillboardSceneNode(
 				NULL, v2f(1, 1), v3f(0,0,0), -1);
@@ -801,8 +825,7 @@ void GenericCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
 					txs, tys, 0, 0);
 		}
 	}
-	else if(m_prop.visual == "upright_sprite")
-	{
+	else if(m_prop.visual == "upright_sprite") {
 		scene::SMesh *mesh = new scene::SMesh();
 		double dx = BS*m_prop.visual_size.X/2;
 		double dy = BS*m_prop.visual_size.Y/2;
@@ -856,7 +879,7 @@ void GenericCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
 		// This is needed for changing the texture in the future
 		m_meshnode->setReadOnlyMaterials(true);
 	}
-	else if(m_prop.visual == "cube"){
+	else if(m_prop.visual == "cube") {
 		infostream<<"GenericCAO::addToScene(): cube"<<std::endl;
 		scene::IMesh *mesh = createCubeMesh(v3f(BS,BS,BS));
 		m_meshnode = smgr->addMeshSceneNode(mesh, NULL);
@@ -873,7 +896,7 @@ void GenericCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
 		m_meshnode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
 		m_meshnode->setMaterialFlag(video::EMF_FOG_ENABLE, true);
 	}
-	else if(m_prop.visual == "mesh"){
+	else if(m_prop.visual == "mesh") {
 		infostream<<"GenericCAO::addToScene(): mesh"<<std::endl;
 		scene::IAnimatedMesh *mesh = m_gamedef->getMesh(m_prop.mesh);
 		if(mesh)
@@ -895,7 +918,7 @@ void GenericCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
 		else
 			errorstream<<"GenericCAO::addToScene(): Could not load mesh "<<m_prop.mesh<<std::endl;
 	}
-	else if(m_prop.visual == "wielditem"){
+	else if(m_prop.visual == "wielditem") {
 		infostream<<"GenericCAO::addToScene(): node"<<std::endl;
 		infostream<<"textures: "<<m_prop.textures.size()<<std::endl;
 		if(m_prop.textures.size() >= 1){
@@ -949,7 +972,8 @@ void GenericCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
 void GenericCAO::updateLight(u8 light_at_pos)
 {
 	u8 li = decode_light(light_at_pos);
-	if(li != m_last_light){
+	if(li != m_last_light)
+	{
 		m_last_light = li;
 		video::SColor color(255,li,li,li);
 		if(m_meshnode)
@@ -972,19 +996,22 @@ void GenericCAO::updateNodePos()
 		return;
 
 	v3s16 camera_offset = m_env->getCameraOffset();
-	if(m_meshnode){
+	if(m_meshnode)
+	{
 		m_meshnode->setPosition(pos_translator.vect_show-intToFloat(camera_offset, BS));
 		v3f rot = m_meshnode->getRotation();
 		rot.Y = -m_yaw;
 		m_meshnode->setRotation(rot);
 	}
-	if(m_animated_meshnode){
+	if(m_animated_meshnode)
+	{
 		m_animated_meshnode->setPosition(pos_translator.vect_show-intToFloat(camera_offset, BS));
 		v3f rot = m_animated_meshnode->getRotation();
 		rot.Y = -m_yaw;
 		m_animated_meshnode->setRotation(rot);
 	}
-	if(m_spritenode){
+	if(m_spritenode)
+	{
 		m_spritenode->setPosition(pos_translator.vect_show-intToFloat(camera_offset, BS));
 	}
 }
@@ -992,13 +1019,14 @@ void GenericCAO::updateNodePos()
 void GenericCAO::step(float dtime, ClientEnvironment *env)
 {
 	// Handel model of local player instantly to prevent lags
-	if(m_is_local_player) {
+	if(m_is_local_player)
+	{
 		LocalPlayer *player = m_env->getLocalPlayer();
 
-		if (player->camera_mode > CAMERA_MODE_FIRST) {
+		if (m_is_visible)
+		{
 			int old_anim = player->last_animation;
 			float old_anim_speed = player->last_animation_speed;
-			m_is_visible = true;
 			m_position = player->getPosition() + v3f(0,BS,0);
 			m_velocity = v3f(0,0,0);
 			m_acceleration = v3f(0,0,0);
@@ -1026,7 +1054,8 @@ void GenericCAO::step(float dtime, ClientEnvironment *env)
 			if(controls.sneak && walking)
 				new_speed /= 2;
 
-			if(walking && (controls.LMB || controls.RMB)) {
+			if(walking && (controls.LMB || controls.RMB))
+			{
 				new_anim = player->local_animations[3];
 				player->last_animation = WD_ANIM;
 			} else if(walking) {
@@ -1039,7 +1068,8 @@ void GenericCAO::step(float dtime, ClientEnvironment *env)
 
 			// Apply animations if input detected and not attached
 			// or set idle animation
-			if ((new_anim.X + new_anim.Y) > 0 && !player->isAttached) {
+			if ((new_anim.X + new_anim.Y) > 0 && !player->isAttached)
+			{
 				allow_update = true;
 				m_animation_range = new_anim;
 				m_animation_speed = new_speed;
@@ -1047,36 +1077,42 @@ void GenericCAO::step(float dtime, ClientEnvironment *env)
 			} else {
 				player->last_animation = NO_ANIM;
 
-				if (old_anim != NO_ANIM) {
+				if (old_anim != NO_ANIM)
+				{
 					m_animation_range = player->local_animations[0];
 					updateAnimation();
 				}
 			}
 
 			// Update local player animations
-			if ((player->last_animation != old_anim || m_animation_speed != old_anim_speed) &&
+			if ((player->last_animation != old_anim ||
+				m_animation_speed != old_anim_speed) &&
 				player->last_animation != NO_ANIM && allow_update)
 					updateAnimation();
 
-		} else {
-			m_is_visible = false;
 		}
 	}
 
 	if(m_visuals_expired && m_smgr && m_irr){
 		m_visuals_expired = false;
 
-		// Attachments, part 1: All attached objects must be unparented first, or Irrlicht causes a segmentation fault
-		for(std::vector<core::vector2d<int> >::iterator ii = m_env->attachment_list.begin(); ii != m_env->attachment_list.end(); ii++)
+		// Attachments, part 1: All attached objects must be unparented first,
+		// or Irrlicht causes a segmentation fault
+		for(std::vector<core::vector2d<int> >::iterator ii = m_env->attachment_list.begin();
+				ii != m_env->attachment_list.end(); ii++)
 		{
 			if(ii->Y == getId()) // This is a child of our parent
 			{
-				ClientActiveObject *obj = m_env->getActiveObject(ii->X); // Get the object of the child
+				// Get the object of the child
+				ClientActiveObject *obj = m_env->getActiveObject(ii->X);
 				if(obj)
 				{
-					scene::IMeshSceneNode *m_child_meshnode = obj->getMeshSceneNode();
-					scene::IAnimatedMeshSceneNode *m_child_animated_meshnode = obj->getAnimatedMeshSceneNode();
-					scene::IBillboardSceneNode *m_child_spritenode = obj->getSpriteSceneNode();
+					scene::IMeshSceneNode *m_child_meshnode
+							= obj->getMeshSceneNode();
+					scene::IAnimatedMeshSceneNode *m_child_animated_meshnode
+							= obj->getAnimatedMeshSceneNode();
+					scene::IBillboardSceneNode *m_child_spritenode
+							= obj->getSpriteSceneNode();
 					if(m_child_meshnode)
 						m_child_meshnode->setParent(m_smgr->getRootSceneNode());
 					if(m_child_animated_meshnode)
@@ -1091,11 +1127,13 @@ void GenericCAO::step(float dtime, ClientEnvironment *env)
 		addToScene(m_smgr, m_gamedef->tsrc(), m_irr);
 
 		// Attachments, part 2: Now that the parent has been refreshed, put its attachments back
-		for(std::vector<core::vector2d<int> >::iterator ii = m_env->attachment_list.begin(); ii != m_env->attachment_list.end(); ii++)
+		for(std::vector<core::vector2d<int> >::iterator ii = m_env->attachment_list.begin();
+				ii != m_env->attachment_list.end(); ii++)
 		{
 			if(ii->Y == getId()) // This is a child of our parent
 			{
-				ClientActiveObject *obj = m_env->getActiveObject(ii->X); // Get the object of the child
+				// Get the object of the child
+				ClientActiveObject *obj = m_env->getActiveObject(ii->X);
 				if(obj)
 					obj->setAttachments();
 			}
@@ -1126,12 +1164,11 @@ void GenericCAO::step(float dtime, ClientEnvironment *env)
 			player->overridePosition = getParent()->getPosition();
 			m_env->getLocalPlayer()->parent = getParent();
 		}
-	}
-	else
-	{
+	} else {
 		v3f lastpos = pos_translator.vect_show;
 
-		if(m_prop.physical){
+		if(m_prop.physical)
+		{
 			core::aabbox3d<f32> box = m_prop.collisionbox;
 			box.MinEdge *= BS;
 			box.MaxEdge *= BS;
@@ -1156,16 +1193,19 @@ void GenericCAO::step(float dtime, ClientEnvironment *env)
 		} else {
 			m_position += dtime * m_velocity + 0.5 * dtime * dtime * m_acceleration;
 			m_velocity += dtime * m_acceleration;
-			pos_translator.update(m_position, pos_translator.aim_is_end, pos_translator.anim_time);
+			pos_translator.update(m_position, pos_translator.aim_is_end,
+					pos_translator.anim_time);
 			pos_translator.translate(dtime);
 			updateNodePos();
 		}
 
 		float moved = lastpos.getDistanceFrom(pos_translator.vect_show);
 		m_step_distance_counter += moved;
-		if(m_step_distance_counter > 1.5*BS){
+		if(m_step_distance_counter > 1.5*BS)
+		{
 			m_step_distance_counter = 0;
-			if(!m_is_local_player && m_prop.makes_footstep_sound){
+			if(!m_is_local_player && m_prop.makes_footstep_sound)
+			{
 				INodeDefManager *ndef = m_gamedef->ndef();
 				v3s16 p = floatToInt(getPosition() + v3f(0,
 						(m_prop.collisionbox.MinEdge.Y-0.5)*BS, 0), BS);
@@ -1177,7 +1217,8 @@ void GenericCAO::step(float dtime, ClientEnvironment *env)
 	}
 
 	m_anim_timer += dtime;
-	if(m_anim_timer >= m_anim_framelength){
+	if(m_anim_timer >= m_anim_framelength)
+	{
 		m_anim_timer -= m_anim_framelength;
 		m_anim_frame++;
 		if(m_anim_frame >= m_anim_num_frames)
@@ -1186,28 +1227,33 @@ void GenericCAO::step(float dtime, ClientEnvironment *env)
 
 	updateTexturePos();
 
-	if(m_reset_textures_timer >= 0){
+	if(m_reset_textures_timer >= 0)
+	{
 		m_reset_textures_timer -= dtime;
 		if(m_reset_textures_timer <= 0){
 			m_reset_textures_timer = -1;
 			updateTextures("");
 		}
 	}
-	if(getParent() == NULL && fabs(m_prop.automatic_rotate) > 0.001){
+	if(getParent() == NULL && fabs(m_prop.automatic_rotate) > 0.001)
+	{
 		m_yaw += dtime * m_prop.automatic_rotate * 180 / M_PI;
 		updateNodePos();
 	}
 
 	if (getParent() == NULL && m_prop.automatic_face_movement_dir &&
-			(fabs(m_velocity.Z) > 0.001 || fabs(m_velocity.X) > 0.001)){
-		m_yaw = atan2(m_velocity.Z,m_velocity.X) * 180 / M_PI + m_prop.automatic_face_movement_dir_offset;
+			(fabs(m_velocity.Z) > 0.001 || fabs(m_velocity.X) > 0.001))
+	{
+		m_yaw = atan2(m_velocity.Z,m_velocity.X) * 180 / M_PI
+				+ m_prop.automatic_face_movement_dir_offset;
 		updateNodePos();
 	}
 }
 
 void GenericCAO::updateTexturePos()
 {
-	if(m_spritenode){
+	if(m_spritenode)
+	{
 		scene::ICameraSceneNode* camera =
 				m_spritenode->getSceneManager()->getActiveCamera();
 		if(!camera)
@@ -1226,7 +1272,8 @@ void GenericCAO::updateTexturePos()
 			else if(cam_to_entity.Y < -0.75)
 				col += 4;
 			else{
-				float mob_dir = atan2(cam_to_entity.Z, cam_to_entity.X) / M_PI * 180.;
+				float mob_dir =
+						atan2(cam_to_entity.Z, cam_to_entity.X) / M_PI * 180.;
 				float dir = mob_dir - m_yaw;
 				dir = wrapDegrees_180(dir);
 				//infostream<<"id="<<m_id<<" dir="<<dir<<std::endl;
@@ -1291,7 +1338,8 @@ void GenericCAO::updateTextures(const std::string &mod)
 	{
 		if(m_prop.visual == "mesh")
 		{
-			for (u32 i = 0; i < m_prop.textures.size() && i < m_animated_meshnode->getMaterialCount(); ++i)
+			for (u32 i = 0; i < m_prop.textures.size() &&
+					i < m_animated_meshnode->getMaterialCount(); ++i)
 			{
 				std::string texturestring = m_prop.textures[i];
 				if(texturestring == "")
@@ -1310,11 +1358,15 @@ void GenericCAO::updateTextures(const std::string &mod)
 				material.setFlag(video::EMF_LIGHTING, false);
 				material.setFlag(video::EMF_BILINEAR_FILTER, false);
 
-				m_animated_meshnode->getMaterial(i).setFlag(video::EMF_TRILINEAR_FILTER, use_trilinear_filter);
-				m_animated_meshnode->getMaterial(i).setFlag(video::EMF_BILINEAR_FILTER, use_bilinear_filter);
-				m_animated_meshnode->getMaterial(i).setFlag(video::EMF_ANISOTROPIC_FILTER, use_anisotropic_filter);
+				m_animated_meshnode->getMaterial(i)
+						.setFlag(video::EMF_TRILINEAR_FILTER, use_trilinear_filter);
+				m_animated_meshnode->getMaterial(i)
+						.setFlag(video::EMF_BILINEAR_FILTER, use_bilinear_filter);
+				m_animated_meshnode->getMaterial(i)
+						.setFlag(video::EMF_ANISOTROPIC_FILTER, use_anisotropic_filter);
 			}
-			for (u32 i = 0; i < m_prop.colors.size() && i < m_animated_meshnode->getMaterialCount(); ++i)
+			for (u32 i = 0; i < m_prop.colors.size() &&
+			i < m_animated_meshnode->getMaterialCount(); ++i)
 			{
 				// This allows setting per-material colors. However, until a real lighting
 				// system is added, the code below will have no effect. Once MineTest
@@ -1436,7 +1488,10 @@ void GenericCAO::updateBonePosition()
 		return;
 
 	m_animated_meshnode->setJointMode(irr::scene::EJUOR_CONTROL); // To write positions to the mesh on render
-	for(std::map<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){
+	for(std::map<std::string,
+			core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin();
+			ii != m_bone_position.end(); ++ii)
+	{
 		std::string bone_name = (*ii).first;
 		v3f bone_pos = (*ii).second.X;
 		v3f bone_rot = (*ii).second.Y;
@@ -1451,8 +1506,14 @@ void GenericCAO::updateBonePosition()
 	
 void GenericCAO::updateAttachments()
 {
-	m_attached_to_local = getParent() != NULL && getParent()->isLocalPlayer();
-	m_is_visible = !m_attached_to_local; // Objects attached to the local player should always be hidden
+
+	// localplayer itself can't be attached to localplayer
+	if (!m_is_local_player)
+	{
+		m_attached_to_local = getParent() != NULL && getParent()->isLocalPlayer();
+		// Objects attached to the local player should always be hidden
+		m_is_visible = !m_attached_to_local;
+	}
 
 	if(getParent() == NULL || m_attached_to_local) // Detach or don't attach
 	{
@@ -1503,12 +1564,17 @@ void GenericCAO::updateAttachments()
 
 		scene::IBoneSceneNode *parent_bone = NULL;
 		if(parent_animated_mesh && m_attachment_bone != "")
-			parent_bone = parent_animated_mesh->getJointNode(m_attachment_bone.c_str());
-
-		// The spaghetti code below makes sure attaching works if either the parent or child is a spritenode, meshnode, or animatedmeshnode
+		{
+			parent_bone =
+					parent_animated_mesh->getJointNode(m_attachment_bone.c_str());
+		}
+		// The spaghetti code below makes sure attaching works if either the
+		// parent or child is a spritenode, meshnode, or animatedmeshnode
 		// TODO: Perhaps use polymorphism here to save code duplication
-		if(m_meshnode){
-			if(parent_bone){
+		if(m_meshnode)
+		{
+			if(parent_bone)
+			{
 				m_meshnode->setParent(parent_bone);
 				m_meshnode->setPosition(m_attachment_position);
 				m_meshnode->setRotation(m_attachment_rotation);
@@ -1516,19 +1582,20 @@ void GenericCAO::updateAttachments()
 			}
 			else
 			{
-				if(parent_mesh){
+				if(parent_mesh)
+				{
 					m_meshnode->setParent(parent_mesh);
 					m_meshnode->setPosition(m_attachment_position);
 					m_meshnode->setRotation(m_attachment_rotation);
 					m_meshnode->updateAbsolutePosition();
 				}
-				else if(parent_animated_mesh){
+				else if(parent_animated_mesh) {
 					m_meshnode->setParent(parent_animated_mesh);
 					m_meshnode->setPosition(m_attachment_position);
 					m_meshnode->setRotation(m_attachment_rotation);
 					m_meshnode->updateAbsolutePosition();
 				}
-				else if(parent_sprite){
+				else if(parent_sprite) {
 					m_meshnode->setParent(parent_sprite);
 					m_meshnode->setPosition(m_attachment_position);
 					m_meshnode->setRotation(m_attachment_rotation);
@@ -1536,8 +1603,10 @@ void GenericCAO::updateAttachments()
 				}
 			}
 		}
-		if(m_animated_meshnode){
-			if(parent_bone){
+		if(m_animated_meshnode)
+		{
+			if(parent_bone)
+			{
 				m_animated_meshnode->setParent(parent_bone);
 				m_animated_meshnode->setPosition(m_attachment_position);
 				m_animated_meshnode->setRotation(m_attachment_rotation);
@@ -1545,19 +1614,18 @@ void GenericCAO::updateAttachments()
 			}
 			else
 			{
-				if(parent_mesh){
+				if(parent_mesh)
+				{
 					m_animated_meshnode->setParent(parent_mesh);
 					m_animated_meshnode->setPosition(m_attachment_position);
 					m_animated_meshnode->setRotation(m_attachment_rotation);
 					m_animated_meshnode->updateAbsolutePosition();
-				}
-				else if(parent_animated_mesh){
+				} else if(parent_animated_mesh) {
 					m_animated_meshnode->setParent(parent_animated_mesh);
 					m_animated_meshnode->setPosition(m_attachment_position);
 					m_animated_meshnode->setRotation(m_attachment_rotation);
 					m_animated_meshnode->updateAbsolutePosition();
-				}
-				else if(parent_sprite){
+				} else if(parent_sprite) {
 					m_animated_meshnode->setParent(parent_sprite);
 					m_animated_meshnode->setPosition(m_attachment_position);
 					m_animated_meshnode->setRotation(m_attachment_rotation);
@@ -1565,28 +1633,29 @@ void GenericCAO::updateAttachments()
 				}
 			}
 		}
-		if(m_spritenode){
-			if(parent_bone){
+		if(m_spritenode)
+		{
+			if(parent_bone)
+			{
 				m_spritenode->setParent(parent_bone);
 				m_spritenode->setPosition(m_attachment_position);
 				m_spritenode->setRotation(m_attachment_rotation);
 				m_spritenode->updateAbsolutePosition();
-			}
-			else
-			{
-				if(parent_mesh){
+			} else {
+				if(parent_mesh)
+				{
 					m_spritenode->setParent(parent_mesh);
 					m_spritenode->setPosition(m_attachment_position);
 					m_spritenode->setRotation(m_attachment_rotation);
 					m_spritenode->updateAbsolutePosition();
 				}
-				else if(parent_animated_mesh){
+				else if(parent_animated_mesh) {
 					m_spritenode->setParent(parent_animated_mesh);
 					m_spritenode->setPosition(m_attachment_position);
 					m_spritenode->setRotation(m_attachment_rotation);
 					m_spritenode->updateAbsolutePosition();
 				}
-				else if(parent_sprite){
+				else if(parent_sprite) {
 					m_spritenode->setParent(parent_sprite);
 					m_spritenode->setPosition(m_attachment_position);
 					m_spritenode->setRotation(m_attachment_rotation);
@@ -1649,7 +1718,8 @@ void GenericCAO::processMessage(const std::string &data)
 		if(getParent() != NULL) // Just in case
 			return;
 
-		if(do_interpolate){
+		if(do_interpolate)
+		{
 			if(!m_prop.physical)
 				pos_translator.update(m_position, is_end_position, update_interval);
 		} else {
@@ -1657,13 +1727,11 @@ void GenericCAO::processMessage(const std::string &data)
 		}
 		updateNodePos();
 	}
-	else if(cmd == GENERIC_CMD_SET_TEXTURE_MOD)
-	{
+	else if(cmd == GENERIC_CMD_SET_TEXTURE_MOD) {
 		std::string mod = deSerializeString(is);
 		updateTextures(mod);
 	}
-	else if(cmd == GENERIC_CMD_SET_SPRITE)
-	{
+	else if(cmd == GENERIC_CMD_SET_SPRITE) {
 		v2s16 p = readV2S16(is);
 		int num_frames = readU16(is);
 		float framelength = readF1000(is);
@@ -1676,8 +1744,7 @@ void GenericCAO::processMessage(const std::string &data)
 
 		updateTexturePos();
 	}
-	else if(cmd == GENERIC_CMD_SET_PHYSICS_OVERRIDE)
-	{
+	else if(cmd == GENERIC_CMD_SET_PHYSICS_OVERRIDE) {
 		float override_speed = readF1000(is);
 		float override_jump = readF1000(is);
 		float override_gravity = readF1000(is);
@@ -1696,8 +1763,7 @@ void GenericCAO::processMessage(const std::string &data)
 			player->physics_override_sneak_glitch = sneak_glitch;
 		}
 	}
-	else if(cmd == GENERIC_CMD_SET_ANIMATION)
-	{
+	else if(cmd == GENERIC_CMD_SET_ANIMATION) {
 		// TODO: change frames send as v2s32 value
 		v2f range = readV2F1000(is);
 		if (!m_is_local_player) {
@@ -1707,7 +1773,8 @@ void GenericCAO::processMessage(const std::string &data)
 			updateAnimation();
 		} else {
 			LocalPlayer *player = m_env->getLocalPlayer();
-			if(player->last_animation == NO_ANIM) {
+			if(player->last_animation == NO_ANIM)
+			{
 				m_animation_range = v2s32((s32)range.X, (s32)range.Y);
 				m_animation_speed = readF1000(is);
 				m_animation_blend = readF1000(is);
@@ -1715,7 +1782,8 @@ void GenericCAO::processMessage(const std::string &data)
 			// update animation only if local animations present
 			// and received animation is unknown (except idle animation)
 			bool is_known = false;
-			for (int i = 1;i<4;i++) {
+			for (int i = 1;i<4;i++)
+			{
 				if(m_animation_range.Y == player->local_animations[i].Y)
 					is_known = true;
 			}
@@ -1726,8 +1794,7 @@ void GenericCAO::processMessage(const std::string &data)
 			}
 		}
 	}
-	else if(cmd == GENERIC_CMD_SET_BONE_POSITION)
-	{
+	else if(cmd == GENERIC_CMD_SET_BONE_POSITION) {
 		std::string bone = deSerializeString(is);
 		v3f position = readV3F1000(is);
 		v3f rotation = readV3F1000(is);
@@ -1735,8 +1802,7 @@ void GenericCAO::processMessage(const std::string &data)
 
 		updateBonePosition();
 	}
-	else if(cmd == GENERIC_CMD_SET_ATTACHMENT)
-	{
+	else if(cmd == GENERIC_CMD_SET_ATTACHMENT) {
 		// If an entry already exists for this object, delete it first to avoid duplicates
 		for(std::vector<core::vector2d<int> >::iterator ii = m_env->attachment_list.begin(); ii != m_env->attachment_list.end(); ii++)
 		{
@@ -1753,8 +1819,7 @@ void GenericCAO::processMessage(const std::string &data)
 
 		updateAttachments();
 	}
-	else if(cmd == GENERIC_CMD_PUNCHED)
-	{
+	else if(cmd == GENERIC_CMD_PUNCHED) {
 		/*s16 damage =*/ readS16(is);
 		s16 result_hp = readS16(is);
 
@@ -1763,8 +1828,10 @@ void GenericCAO::processMessage(const std::string &data)
 
 		m_hp = result_hp;
 
-		if (damage > 0) {
-			if (m_hp <= 0) {
+		if (damage > 0)
+		{
+			if (m_hp <= 0)
+			{
 				// TODO: Execute defined fast response
 				// As there is no definition, make a smoke puff
 				ClientSimpleObject *simple = createSmokePuff(
@@ -1781,11 +1848,11 @@ void GenericCAO::processMessage(const std::string &data)
 			}
 		}
 	}
-	else if(cmd == GENERIC_CMD_UPDATE_ARMOR_GROUPS)
-	{
+	else if(cmd == GENERIC_CMD_UPDATE_ARMOR_GROUPS) {
 		m_armor_groups.clear();
 		int armor_groups_size = readU16(is);
-		for(int i=0; i<armor_groups_size; i++){
+		for(int i=0; i<armor_groups_size; i++)
+		{
 			std::string name = deSerializeString(is);
 			int rating = readS16(is);
 			m_armor_groups[name] = rating;
@@ -1807,7 +1874,8 @@ bool GenericCAO::directReportPunch(v3f dir, const ItemStack *punchitem,
 
 	if(result.did_punch && result.damage != 0)
 	{
-		if(result.damage < m_hp){
+		if(result.damage < m_hp)
+		{
 			m_hp -= result.damage;
 		} else {
 			m_hp = 0;
@@ -1835,7 +1903,8 @@ std::string GenericCAO::debugInfoText()
 	os<<"GenericCAO hp="<<m_hp<<"\n";
 	os<<"armor={";
 	for(ItemGroupList::const_iterator i = m_armor_groups.begin();
-			i != m_armor_groups.end(); i++){
+			i != m_armor_groups.end(); i++)
+	{
 		os<<i->first<<"="<<i->second<<", ";
 	}
 	os<<"}";

+ 2 - 2
src/defaultsettings.cpp

@@ -56,8 +56,8 @@ void set_default_settings(Settings *settings)
 	settings->setDefault("keymap_camera_mode", "KEY_F7");
 	settings->setDefault("keymap_increase_viewing_range_min", "+");
 	settings->setDefault("keymap_decrease_viewing_range_min", "-");
-	settings->setDefault("anaglyph", "false");
-	settings->setDefault("anaglyph_strength", "0.1");
+	settings->setDefault("3d_mode", "none");
+	settings->setDefault("3d_paralax_strength", "0.025");
 	settings->setDefault("aux1_descends", "false");
 	settings->setDefault("doubletap_jump", "false");
 	settings->setDefault("always_fly_fast", "true");

+ 529 - 0
src/drawscene.cpp

@@ -0,0 +1,529 @@
+/*
+Minetest
+Copyright (C) 2010-2014 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "drawscene.h"
+#include "main.h" // for g_settings
+#include "settings.h"
+#include "clouds.h"
+#include "util/timetaker.h"
+
+typedef enum {
+	LEFT = -1,
+	RIGHT = 1,
+	EYECOUNT = 2
+} paralax_sign;
+
+void draw_selectionbox(video::IVideoDriver* driver, Hud& hud,
+		std::vector<aabb3f>& hilightboxes, bool show_hud)
+{
+	if (!show_hud)
+		return;
+
+	video::SMaterial oldmaterial = driver->getMaterial2D();
+	video::SMaterial m;
+	m.Thickness = 3;
+	m.Lighting = false;
+	driver->setMaterial(m);
+	hud.drawSelectionBoxes(hilightboxes);
+	driver->setMaterial(oldmaterial);
+}
+
+void draw_anaglyph_3d_mode(Camera& camera, bool show_hud, Hud& hud,
+		std::vector<aabb3f> hilightboxes, video::IVideoDriver* driver,
+		scene::ISceneManager* smgr, bool draw_wield_tool, Client& client,
+		gui::IGUIEnvironment* guienv )
+{
+
+	/* preserve old setup*/
+	irr::core::vector3df oldPosition = camera.getCameraNode()->getPosition();
+	irr::core::vector3df oldTarget   = camera.getCameraNode()->getTarget();
+
+	irr::core::matrix4 startMatrix =
+			camera.getCameraNode()->getAbsoluteTransformation();
+	irr::core::vector3df focusPoint = (camera.getCameraNode()->getTarget()
+			- camera.getCameraNode()->getAbsolutePosition()).setLength(1)
+			+ camera.getCameraNode()->getAbsolutePosition();
+
+
+	//Left eye...
+	irr::core::vector3df leftEye;
+	irr::core::matrix4 leftMove;
+	leftMove.setTranslation(
+			irr::core::vector3df(-g_settings->getFloat("3d_paralax_strength"),
+					0.0f, 0.0f));
+	leftEye = (startMatrix * leftMove).getTranslation();
+
+	//clear the depth buffer, and color
+	driver->beginScene( true, true, irr::video::SColor(0, 200, 200, 255));
+	driver->getOverrideMaterial().Material.ColorMask = irr::video::ECP_RED;
+	driver->getOverrideMaterial().EnableFlags = irr::video::EMF_COLOR_MASK;
+	driver->getOverrideMaterial().EnablePasses = irr::scene::ESNRP_SKY_BOX
+			+ irr::scene::ESNRP_SOLID + irr::scene::ESNRP_TRANSPARENT
+			+ irr::scene::ESNRP_TRANSPARENT_EFFECT + irr::scene::ESNRP_SHADOW;
+	camera.getCameraNode()->setPosition(leftEye);
+	camera.getCameraNode()->setTarget(focusPoint);
+	smgr->drawAll();
+	driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
+	if (show_hud)
+	{
+		draw_selectionbox(driver, hud, hilightboxes, show_hud);
+
+		if (draw_wield_tool)
+			camera.drawWieldedTool(&leftMove);
+	}
+
+	guienv->drawAll();
+
+	//Right eye...
+	irr::core::vector3df rightEye;
+	irr::core::matrix4 rightMove;
+	rightMove.setTranslation(
+			irr::core::vector3df(g_settings->getFloat("3d_paralax_strength"),
+					0.0f, 0.0f));
+	rightEye = (startMatrix * rightMove).getTranslation();
+
+	//clear the depth buffer
+	driver->clearZBuffer();
+	driver->getOverrideMaterial().Material.ColorMask = irr::video::ECP_GREEN
+			+ irr::video::ECP_BLUE;
+	driver->getOverrideMaterial().EnableFlags = irr::video::EMF_COLOR_MASK;
+	driver->getOverrideMaterial().EnablePasses = irr::scene::ESNRP_SKY_BOX
+			+ irr::scene::ESNRP_SOLID + irr::scene::ESNRP_TRANSPARENT
+			+ irr::scene::ESNRP_TRANSPARENT_EFFECT + irr::scene::ESNRP_SHADOW;
+	camera.getCameraNode()->setPosition(rightEye);
+	camera.getCameraNode()->setTarget(focusPoint);
+	smgr->drawAll();
+	driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
+	if (show_hud)
+	{
+		draw_selectionbox(driver, hud, hilightboxes, show_hud);
+
+		if (draw_wield_tool)
+			camera.drawWieldedTool(&rightMove);
+	}
+
+	guienv->drawAll();
+
+	driver->getOverrideMaterial().Material.ColorMask = irr::video::ECP_ALL;
+	driver->getOverrideMaterial().EnableFlags = 0;
+	driver->getOverrideMaterial().EnablePasses = 0;
+	camera.getCameraNode()->setPosition(oldPosition);
+	camera.getCameraNode()->setTarget(oldTarget);
+}
+
+void init_texture(video::IVideoDriver* driver, const v2u32& screensize,
+		video::ITexture** texture)
+{
+	static v2u32 last_screensize = v2u32(0,0);
+
+	if (( *texture == NULL ) || (screensize != last_screensize))
+	{
+		if (*texture != NULL)
+		{
+			driver->removeTexture(*texture);
+		}
+		*texture = driver->addRenderTargetTexture(
+				core::dimension2d<u32>(screensize.X, screensize.Y));
+		last_screensize = screensize;
+	}
+}
+
+video::ITexture* draw_image(const v2u32& screensize,
+		paralax_sign psign, const irr::core::matrix4& startMatrix,
+		const irr::core::vector3df& focusPoint, bool show_hud,
+		video::IVideoDriver* driver, Camera& camera, scene::ISceneManager* smgr,
+		Hud& hud, std::vector<aabb3f>& hilightboxes,
+		bool draw_wield_tool, Client& client, gui::IGUIEnvironment* guienv,
+		video::SColor skycolor )
+{
+	static video::ITexture* images[2] = { NULL, NULL };
+
+	video::ITexture* image = NULL;
+
+	if (psign == RIGHT)
+	{
+		init_texture(driver, screensize, &images[1]);
+		image = images[1];
+	} else {
+		init_texture(driver, screensize, &images[0]);
+		image = images[0];
+	}
+
+	driver->setRenderTarget(image, true, true,
+			irr::video::SColor(255,
+					skycolor.getRed(), skycolor.getGreen(), skycolor.getBlue()));
+
+	irr::core::vector3df eye_pos;
+	irr::core::matrix4 movement;
+	movement.setTranslation(
+			irr::core::vector3df((int) psign *
+					g_settings->getFloat("3d_paralax_strength"), 0.0f, 0.0f));
+	eye_pos = (startMatrix * movement).getTranslation();
+
+	//clear the depth buffer
+	driver->clearZBuffer();
+	camera.getCameraNode()->setPosition(eye_pos);
+	camera.getCameraNode()->setTarget(focusPoint);
+	smgr->drawAll();
+
+	driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
+
+	if (show_hud)
+	{
+		draw_selectionbox(driver, hud, hilightboxes, show_hud);
+
+		if (draw_wield_tool)
+			camera.drawWieldedTool(&movement);
+	}
+
+	guienv->drawAll();
+
+	/* switch back to real renderer */
+	driver->setRenderTarget(0, true, true,
+			irr::video::SColor(0,
+					skycolor.getRed(), skycolor.getGreen(), skycolor.getBlue()));
+
+	return image;
+}
+
+video::ITexture*  draw_hud(video::IVideoDriver* driver, const v2u32& screensize,
+		bool show_hud, Hud& hud, Client& client, bool draw_crosshair,
+		video::SColor skycolor, gui::IGUIEnvironment* guienv, Camera& camera )
+{
+	static video::ITexture* image = NULL;
+	init_texture(driver, screensize, &image);
+	driver->setRenderTarget(image, true, true,
+			irr::video::SColor(255,0,0,0));
+
+	if (show_hud)
+	{
+		if (draw_crosshair)
+			hud.drawCrosshair();
+		hud.drawHotbar(client.getPlayerItem());
+		hud.drawLuaElements(camera.getOffset());
+
+		guienv->drawAll();
+	}
+
+	driver->setRenderTarget(0, true, true,
+			irr::video::SColor(0,
+					skycolor.getRed(), skycolor.getGreen(), skycolor.getBlue()));
+
+	return image;
+}
+
+void draw_interlaced_3d_mode(Camera& camera, bool show_hud,
+		Hud& hud, std::vector<aabb3f> hilightboxes, video::IVideoDriver* driver,
+		scene::ISceneManager* smgr, const v2u32& screensize,
+		bool draw_wield_tool, Client& client, gui::IGUIEnvironment* guienv,
+		video::SColor skycolor )
+{
+	/* save current info */
+	irr::core::vector3df oldPosition = camera.getCameraNode()->getPosition();
+	irr::core::vector3df oldTarget = camera.getCameraNode()->getTarget();
+	irr::core::matrix4 startMatrix =
+			camera.getCameraNode()->getAbsoluteTransformation();
+	irr::core::vector3df focusPoint = (camera.getCameraNode()->getTarget()
+			- camera.getCameraNode()->getAbsolutePosition()).setLength(1)
+			+ camera.getCameraNode()->getAbsolutePosition();
+
+	/* create left view */
+	video::ITexture* left_image = draw_image(screensize, LEFT, startMatrix,
+			focusPoint, show_hud, driver, camera, smgr, hud, hilightboxes,
+			draw_wield_tool, client, guienv, skycolor);
+
+	//Right eye...
+	irr::core::vector3df rightEye;
+	irr::core::matrix4 rightMove;
+	rightMove.setTranslation(
+			irr::core::vector3df(g_settings->getFloat("3d_paralax_strength"),
+					0.0f, 0.0f));
+	rightEye = (startMatrix * rightMove).getTranslation();
+
+	//clear the depth buffer
+	driver->clearZBuffer();
+	camera.getCameraNode()->setPosition(rightEye);
+	camera.getCameraNode()->setTarget(focusPoint);
+	smgr->drawAll();
+
+	driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
+
+	if (show_hud)
+	{
+		draw_selectionbox(driver, hud, hilightboxes, show_hud);
+
+		if(draw_wield_tool)
+			camera.drawWieldedTool(&rightMove);
+	}
+	guienv->drawAll();
+
+	for (unsigned int i = 0; i < screensize.Y; i+=2 ) {
+		driver->draw2DImage(left_image, irr::core::position2d<s32>(0, screensize.Y-i),
+				irr::core::rect<s32>(0, i,screensize.X, i+1), 0,
+				irr::video::SColor(255, 255, 255, 255),
+				false);
+	}
+
+	/* cleanup */
+	camera.getCameraNode()->setPosition(oldPosition);
+	camera.getCameraNode()->setTarget(oldTarget);
+}
+
+void draw_sidebyside_3d_mode(Camera& camera, bool show_hud,
+		Hud& hud, std::vector<aabb3f> hilightboxes, video::IVideoDriver* driver,
+		scene::ISceneManager* smgr, const v2u32& screensize,
+		bool draw_wield_tool, Client& client, gui::IGUIEnvironment* guienv,
+		video::SColor skycolor )
+{
+	/* save current info */
+	irr::core::vector3df oldPosition = camera.getCameraNode()->getPosition();
+	irr::core::vector3df oldTarget = camera.getCameraNode()->getTarget();
+	irr::core::matrix4 startMatrix =
+			camera.getCameraNode()->getAbsoluteTransformation();
+	irr::core::vector3df focusPoint = (camera.getCameraNode()->getTarget()
+			- camera.getCameraNode()->getAbsolutePosition()).setLength(1)
+			+ camera.getCameraNode()->getAbsolutePosition();
+
+	/* create left view */
+	video::ITexture* left_image = draw_image(screensize, LEFT, startMatrix,
+			focusPoint, show_hud, driver, camera, smgr, hud, hilightboxes,
+			draw_wield_tool, client, guienv, skycolor);
+
+	/* create right view */
+	video::ITexture* right_image = draw_image(screensize, RIGHT, startMatrix,
+			focusPoint, show_hud, driver, camera, smgr, hud, hilightboxes,
+			draw_wield_tool, client, guienv, skycolor);
+
+	/* create hud overlay */
+	video::ITexture* hudtexture = draw_hud(driver, screensize, show_hud, hud, client,
+			false, skycolor, guienv, camera );
+	driver->makeColorKeyTexture(hudtexture, irr::video::SColor(255, 0, 0, 0));
+	//makeColorKeyTexture mirrors texture so we do it twice to get it right again
+	driver->makeColorKeyTexture(hudtexture, irr::video::SColor(255, 0, 0, 0));
+
+	driver->draw2DImage(left_image,
+			irr::core::rect<s32>(0, 0, screensize.X/2, screensize.Y),
+			irr::core::rect<s32>(0, 0, screensize.X, screensize.Y), 0, 0, false);
+
+	driver->draw2DImage(hudtexture,
+			irr::core::rect<s32>(0, 0, screensize.X/2, screensize.Y),
+			irr::core::rect<s32>(0, 0, screensize.X, screensize.Y), 0, 0, true);
+
+	driver->draw2DImage(right_image,
+			irr::core::rect<s32>(screensize.X/2, 0, screensize.X, screensize.Y),
+			irr::core::rect<s32>(0, 0, screensize.X, screensize.Y), 0, 0, false);
+
+	driver->draw2DImage(hudtexture,
+			irr::core::rect<s32>(screensize.X/2, 0, screensize.X, screensize.Y),
+			irr::core::rect<s32>(0, 0, screensize.X, screensize.Y), 0, 0, true);
+
+	left_image = NULL;
+	right_image = NULL;
+
+	/* cleanup */
+	camera.getCameraNode()->setPosition(oldPosition);
+	camera.getCameraNode()->setTarget(oldTarget);
+}
+
+void draw_top_bottom_3d_mode(Camera& camera, bool show_hud,
+		Hud& hud, std::vector<aabb3f> hilightboxes, video::IVideoDriver* driver,
+		scene::ISceneManager* smgr, const v2u32& screensize,
+		bool draw_wield_tool, Client& client, gui::IGUIEnvironment* guienv,
+		video::SColor skycolor )
+{
+	/* save current info */
+	irr::core::vector3df oldPosition = camera.getCameraNode()->getPosition();
+	irr::core::vector3df oldTarget = camera.getCameraNode()->getTarget();
+	irr::core::matrix4 startMatrix =
+			camera.getCameraNode()->getAbsoluteTransformation();
+	irr::core::vector3df focusPoint = (camera.getCameraNode()->getTarget()
+			- camera.getCameraNode()->getAbsolutePosition()).setLength(1)
+			+ camera.getCameraNode()->getAbsolutePosition();
+
+	/* create left view */
+	video::ITexture* left_image = draw_image(screensize, LEFT, startMatrix,
+			focusPoint, show_hud, driver, camera, smgr, hud, hilightboxes,
+			draw_wield_tool, client, guienv, skycolor);
+
+	/* create right view */
+	video::ITexture* right_image = draw_image(screensize, RIGHT, startMatrix,
+			focusPoint, show_hud, driver, camera, smgr, hud, hilightboxes,
+			draw_wield_tool, client, guienv, skycolor);
+
+	/* create hud overlay */
+	video::ITexture* hudtexture = draw_hud(driver, screensize, show_hud, hud, client,
+			false, skycolor, guienv, camera );
+	driver->makeColorKeyTexture(hudtexture, irr::video::SColor(255, 0, 0, 0));
+	//makeColorKeyTexture mirrors texture so we do it twice to get it right again
+	driver->makeColorKeyTexture(hudtexture, irr::video::SColor(255, 0, 0, 0));
+
+	driver->draw2DImage(left_image,
+			irr::core::rect<s32>(0, 0, screensize.X, screensize.Y/2),
+			irr::core::rect<s32>(0, 0, screensize.X, screensize.Y), 0, 0, false);
+
+	driver->draw2DImage(hudtexture,
+			irr::core::rect<s32>(0, 0, screensize.X, screensize.Y/2),
+			irr::core::rect<s32>(0, 0, screensize.X, screensize.Y), 0, 0, true);
+
+	driver->draw2DImage(right_image,
+			irr::core::rect<s32>(0, screensize.Y/2, screensize.X, screensize.Y),
+			irr::core::rect<s32>(0, 0, screensize.X, screensize.Y), 0, 0, false);
+
+	driver->draw2DImage(hudtexture,
+			irr::core::rect<s32>(0, screensize.Y/2, screensize.X, screensize.Y),
+			irr::core::rect<s32>(0, 0, screensize.X, screensize.Y), 0, 0, true);
+
+	left_image = NULL;
+	right_image = NULL;
+
+	/* cleanup */
+	camera.getCameraNode()->setPosition(oldPosition);
+	camera.getCameraNode()->setTarget(oldTarget);
+}
+
+void draw_plain(Camera& camera, bool show_hud, Hud& hud,
+		std::vector<aabb3f> hilightboxes, video::IVideoDriver* driver,
+		bool draw_wield_tool, Client& client, gui::IGUIEnvironment* guienv)
+{
+
+	draw_selectionbox(driver, hud, hilightboxes, show_hud);
+
+	if(draw_wield_tool)
+		camera.drawWieldedTool();
+}
+
+void draw_scene(video::IVideoDriver* driver, scene::ISceneManager* smgr,
+		Camera& camera, Client& client, LocalPlayer* player, Hud& hud,
+		gui::IGUIEnvironment* guienv, std::vector<aabb3f> hilightboxes,
+		const v2u32& screensize, video::SColor skycolor, bool show_hud)
+{
+	//TODO check if usefull
+	u32 scenetime = 0;
+	{
+		TimeTaker timer("smgr");
+
+		bool draw_wield_tool = (show_hud &&
+				(player->hud_flags & HUD_FLAG_WIELDITEM_VISIBLE) &&
+				camera.getCameraMode() < CAMERA_MODE_THIRD );
+
+		bool draw_crosshair = ((player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE) &&
+				(camera.getCameraMode() != CAMERA_MODE_THIRD_FRONT));
+
+		std::string draw_mode = g_settings->get("3d_mode");
+
+		smgr->drawAll();
+
+		if (draw_mode == "anaglyph")
+		{
+			draw_anaglyph_3d_mode(camera, show_hud, hud, hilightboxes, driver,
+					smgr, draw_wield_tool, client, guienv);
+			draw_crosshair = false;
+		}
+		else if (draw_mode == "interlaced")
+		{
+			draw_interlaced_3d_mode(camera, show_hud, hud, hilightboxes, driver,
+					smgr, screensize, draw_wield_tool, client, guienv, skycolor);
+			draw_crosshair = false;
+		}
+		else if (draw_mode == "sidebyside")
+		{
+			draw_sidebyside_3d_mode(camera, show_hud, hud, hilightboxes, driver,
+					smgr, screensize, draw_wield_tool, client, guienv, skycolor);
+			show_hud = false;
+		}
+		else if (draw_mode == "topbottom")
+		{
+			draw_top_bottom_3d_mode(camera, show_hud, hud, hilightboxes, driver,
+					smgr, screensize, draw_wield_tool, client, guienv, skycolor);
+			show_hud = false;
+		}
+		else {
+			draw_plain(camera, show_hud, hud, hilightboxes, driver,
+					draw_wield_tool, client, guienv);
+		}
+		//TODO how to make those 3d too
+		if (show_hud)
+		{
+			if (draw_crosshair)
+				hud.drawCrosshair();
+			hud.drawHotbar(client.getPlayerItem());
+			hud.drawLuaElements(camera.getOffset());
+
+			guienv->drawAll();
+		}
+
+		scenetime = timer.stop(true);
+	}
+
+}
+
+/*
+	Draws a screen with a single text on it.
+	Text will be removed when the screen is drawn the next time.
+	Additionally, a progressbar can be drawn when percent is set between 0 and 100.
+*/
+/*gui::IGUIStaticText **/
+void draw_load_screen(const std::wstring &text, IrrlichtDevice* device,
+		gui::IGUIEnvironment* guienv, gui::IGUIFont* font, float dtime,
+		int percent, bool clouds )
+{
+	video::IVideoDriver* driver = device->getVideoDriver();
+	v2u32 screensize = driver->getScreenSize();
+	const wchar_t *loadingtext = text.c_str();
+	core::vector2d<u32> textsize_u = font->getDimension(loadingtext);
+	core::vector2d<s32> textsize(textsize_u.X,textsize_u.Y);
+	core::vector2d<s32> center(screensize.X/2, screensize.Y/2);
+	core::rect<s32> textrect(center - textsize/2, center + textsize/2);
+
+	gui::IGUIStaticText *guitext = guienv->addStaticText(
+			loadingtext, textrect, false, false);
+	guitext->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+
+	bool cloud_menu_background = clouds && g_settings->getBool("menu_clouds");
+	if (cloud_menu_background)
+	{
+		g_menuclouds->step(dtime*3);
+		g_menuclouds->render();
+		driver->beginScene(true, true, video::SColor(255,140,186,250));
+		g_menucloudsmgr->drawAll();
+	}
+	else
+		driver->beginScene(true, true, video::SColor(255,0,0,0));
+
+	if (percent >= 0 && percent <= 100) // draw progress bar
+	{
+		core::vector2d<s32> barsize(256,32);
+		core::rect<s32> barrect(center-barsize/2, center+barsize/2);
+		driver->draw2DRectangle(video::SColor(255,255,255,255),barrect, NULL); // border
+		driver->draw2DRectangle(video::SColor(255,64,64,64), core::rect<s32> (
+				barrect.UpperLeftCorner+1,
+				barrect.LowerRightCorner-1), NULL); // black inside the bar
+		driver->draw2DRectangle(video::SColor(255,128,128,128), core::rect<s32> (
+				barrect.UpperLeftCorner+1,
+				core::vector2d<s32>(
+					barrect.LowerRightCorner.X-(barsize.X-1)+percent*(barsize.X-2)/100,
+					barrect.LowerRightCorner.Y-1)), NULL); // the actual progress
+	}
+	guienv->drawAll();
+	driver->endScene();
+
+	guitext->remove();
+
+	//return guitext;
+}

+ 37 - 0
src/drawscene.h

@@ -0,0 +1,37 @@
+/*
+Minetest
+Copyright (C) 2010-2014 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef DRAWSCENE_H_
+#define DRAWSCENE_H_
+
+#include "camera.h"
+#include "hud.h"
+#include "irrlichttypes_extrabloated.h"
+
+
+void draw_load_screen(const std::wstring &text, IrrlichtDevice* device,
+		gui::IGUIEnvironment* guienv, gui::IGUIFont* font, float dtime=0,
+		int percent=0, bool clouds=true);
+
+void draw_scene(video::IVideoDriver* driver, scene::ISceneManager* smgr,
+		Camera& camera, Client& client, LocalPlayer* player, Hud& hud,
+		gui::IGUIEnvironment* guienv, std::vector<aabb3f> hilightboxes,
+		const v2u32& screensize, video::SColor skycolor, bool show_hud);
+
+#endif /* DRAWSCENE_H_ */

+ 30 - 234
src/game.cpp

@@ -68,6 +68,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <list>
 #include "util/directiontables.h"
 #include "util/pointedthing.h"
+#include "drawscene.h"
+#include "content_cao.h"
 
 /*
 	Text input system
@@ -418,59 +420,6 @@ PointedThing getPointedThing(Client *client, v3f player_position,
 	return result;
 }
 
-/*
-	Draws a screen with a single text on it.
-	Text will be removed when the screen is drawn the next time.
-	Additionally, a progressbar can be drawn when percent is set between 0 and 100.
-*/
-/*gui::IGUIStaticText **/
-void draw_load_screen(const std::wstring &text, IrrlichtDevice* device,
-		gui::IGUIFont* font, float dtime=0 ,int percent=0, bool clouds=true)
-{
-	video::IVideoDriver* driver = device->getVideoDriver();
-	v2u32 screensize = driver->getScreenSize();
-	const wchar_t *loadingtext = text.c_str();
-	core::vector2d<u32> textsize_u = font->getDimension(loadingtext);
-	core::vector2d<s32> textsize(textsize_u.X,textsize_u.Y);
-	core::vector2d<s32> center(screensize.X/2, screensize.Y/2);
-	core::rect<s32> textrect(center - textsize/2, center + textsize/2);
-
-	gui::IGUIStaticText *guitext = guienv->addStaticText(
-			loadingtext, textrect, false, false);
-	guitext->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
-
-	bool cloud_menu_background = clouds && g_settings->getBool("menu_clouds");
-	if (cloud_menu_background)
-	{
-		g_menuclouds->step(dtime*3);
-		g_menuclouds->render();
-		driver->beginScene(true, true, video::SColor(255,140,186,250));
-		g_menucloudsmgr->drawAll();
-	}
-	else
-		driver->beginScene(true, true, video::SColor(255,0,0,0));
-	if (percent >= 0 && percent <= 100) // draw progress bar
-	{
-		core::vector2d<s32> barsize(256,32);
-		core::rect<s32> barrect(center-barsize/2, center+barsize/2);
-		driver->draw2DRectangle(video::SColor(255,255,255,255),barrect, NULL); // border
-		driver->draw2DRectangle(video::SColor(255,64,64,64), core::rect<s32> (
-				barrect.UpperLeftCorner+1,
-				barrect.LowerRightCorner-1), NULL); // black inside the bar
-		driver->draw2DRectangle(video::SColor(255,128,128,128), core::rect<s32> (
-				barrect.UpperLeftCorner+1,
-				core::vector2d<s32>(
-					barrect.LowerRightCorner.X-(barsize.X-1)+percent*(barsize.X-2)/100,
-					barrect.LowerRightCorner.Y-1)), NULL); // the actual progress
-	}
-	guienv->drawAll();
-	driver->endScene();
-	
-	guitext->remove();
-	
-	//return guitext;
-}
-
 /* Profiler display */
 
 void update_profiler_gui(gui::IGUIStaticText *guitext_profiler,
@@ -1113,7 +1062,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
 
 	{
 		wchar_t* text = wgettext("Loading...");
-		draw_load_screen(text, device, font,0,0);
+		draw_load_screen(text, device, guienv, font, 0, 0);
 		delete[] text;
 	}
 	
@@ -1173,7 +1122,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
 
 	if(address == ""){
 		wchar_t* text = wgettext("Creating server....");
-		draw_load_screen(text, device, font,0,25);
+		draw_load_screen(text, device, guienv, font, 0, 25);
 		delete[] text;
 		infostream<<"Creating server"<<std::endl;
 
@@ -1216,7 +1165,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
 
 	{
 		wchar_t* text = wgettext("Creating client...");
-		draw_load_screen(text, device, font,0,50);
+		draw_load_screen(text, device, guienv, font, 0, 50);
 		delete[] text;
 	}
 	infostream<<"Creating client"<<std::endl;
@@ -1225,7 +1174,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
 	
 	{
 		wchar_t* text = wgettext("Resolving address...");
-		draw_load_screen(text, device, font,0,75);
+		draw_load_screen(text, device, guienv, font, 0, 75);
 		delete[] text;
 	}
 	Address connect_address(0,0,0,0, port);
@@ -1324,7 +1273,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
 			// Display status
 			{
 				wchar_t* text = wgettext("Connecting to server...");
-				draw_load_screen(text, device, font, dtime, 100);
+				draw_load_screen(text, device, guienv, font, dtime, 100);
 				delete[] text;
 			}
 			
@@ -1428,14 +1377,14 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
 			{
 				wchar_t* text = wgettext("Item definitions...");
 				progress = 0;
-				draw_load_screen(text, device, font, dtime, progress);
+				draw_load_screen(text, device, guienv, font, dtime, progress);
 				delete[] text;
 			}
 			else if (!client.nodedefReceived())
 			{
 				wchar_t* text = wgettext("Node definitions...");
 				progress = 25;
-				draw_load_screen(text, device, font, dtime, progress);
+				draw_load_screen(text, device, guienv, font, dtime, progress);
 				delete[] text;
 			}
 			else
@@ -1457,7 +1406,8 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
 					message << " ( " << cur << cur_unit << " )";
 				}
 				progress = 50+client.mediaReceiveProgress()*50+0.5;
-				draw_load_screen(narrow_to_wide(message.str().c_str()), device, font, dtime, progress);
+				draw_load_screen(narrow_to_wide(message.str().c_str()), device,
+						guienv, font, dtime, progress);
 			}
 			
 			// On some computers framerate doesn't seem to be
@@ -1513,8 +1463,6 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
 	f32 camera_yaw = 0; // "right/left"
 	f32 camera_pitch = 0; // "up/down"
 
-	int current_camera_mode = CAMERA_MODE_FIRST; // start in first-person view
-
 	/*
 		Clouds
 	*/
@@ -1530,7 +1478,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
 	*/
 
 	Sky *sky = NULL;
-	sky = new Sky(smgr->getRootSceneNode(), smgr, -1, client.getEnv().getLocalPlayer());
+	sky = new Sky(smgr->getRootSceneNode(), smgr, -1);
 
 	scene::ISceneNode* skybox = NULL;
 	
@@ -1605,7 +1553,6 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
 	*/
 	u32 drawtime = 0;
 	u32 beginscenetime = 0;
-	u32 scenetime = 0;
 	u32 endscenetime = 0;
 	
 	float recent_turn_speed = 0.0;
@@ -2281,7 +2228,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
 			else{
 				s32 dx = input->getMousePos().X - (driver->getScreenSize().Width/2);
 				s32 dy = input->getMousePos().Y - (driver->getScreenSize().Height/2);
-				if(invert_mouse || player->camera_mode == CAMERA_MODE_THIRD_FRONT) {
+				if(invert_mouse || camera.getCameraMode() == CAMERA_MODE_THIRD_FRONT) {
 					dy = -dy;
 				}
 				//infostream<<"window active, pos difference "<<dx<<","<<dy<<std::endl;
@@ -2668,19 +2615,20 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
 		float tool_reload_ratio = time_from_last_punch / full_punch_interval;
 
 		if(input->wasKeyDown(getKeySetting("keymap_camera_mode"))) {
+			camera.toggleCameraMode();
+			GenericCAO* playercao = player->getCAO();
 
-			if (current_camera_mode == CAMERA_MODE_FIRST)
-				current_camera_mode = CAMERA_MODE_THIRD;
-			else if (current_camera_mode == CAMERA_MODE_THIRD)
-				current_camera_mode = CAMERA_MODE_THIRD_FRONT;
-			else
-				current_camera_mode = CAMERA_MODE_FIRST;
-
+			assert( playercao != NULL );
+			if (camera.getCameraMode() > CAMERA_MODE_FIRST) {
+				playercao->setVisible(true);
+			}
+			else {
+				playercao->setVisible(false);
+			}
 		}
-		player->camera_mode = current_camera_mode;
 		tool_reload_ratio = MYMIN(tool_reload_ratio, 1.0);
 		camera.update(player, dtime, busytime, tool_reload_ratio,
-				current_camera_mode, client.getEnv());
+				client.getEnv());
 		camera.step(dtime);
 
 		v3f player_position = player->getPosition();
@@ -2736,7 +2684,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
 				camera_position + camera_direction * BS * (d+1));
 
 		// prevent player pointing anything in front-view
-		if (current_camera_mode == CAMERA_MODE_THIRD_FRONT)
+		if (camera.getCameraMode() == CAMERA_MODE_THIRD_FRONT)
 			shootline = core::line3d<f32>(0,0,0,0,0,0);
 
 		ClientActiveObject *selected_object = NULL;
@@ -3148,7 +3096,8 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
 					+ time_of_day * todsm;
 			
 		sky->update(time_of_day_smooth, time_brightness, direct_brightness,
-				sunlight_seen);
+				sunlight_seen,camera.getCameraMode(), player->getYaw(),
+				player->getPitch());
 		
 		video::SColor bgcolor = sky->getBgColor();
 		video::SColor skycolor = sky->getSkyColor();
@@ -3417,141 +3366,22 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
 		/*
 			Drawing begins
 		*/
-
 		TimeTaker tt_draw("mainloop: draw");
-		
 		{
 			TimeTaker timer("beginScene");
-			//driver->beginScene(false, true, bgcolor);
-			//driver->beginScene(true, true, bgcolor);
 			driver->beginScene(true, true, skycolor);
 			beginscenetime = timer.stop(true);
 		}
-		
-		//timer3.stop();
-	
-		//infostream<<"smgr->drawAll()"<<std::endl;
-		{
-			TimeTaker timer("smgr");
-			smgr->drawAll();
-			
-			if(g_settings->getBool("anaglyph"))
-			{
-				irr::core::vector3df oldPosition = camera.getCameraNode()->getPosition();
-				irr::core::vector3df oldTarget   = camera.getCameraNode()->getTarget();
-
-				irr::core::matrix4 startMatrix   = camera.getCameraNode()->getAbsoluteTransformation();
-
-				irr::core::vector3df focusPoint  = (camera.getCameraNode()->getTarget() -
-										 camera.getCameraNode()->getAbsolutePosition()).setLength(1) +
-										 camera.getCameraNode()->getAbsolutePosition() ;
-
-				//Left eye...
-				irr::core::vector3df leftEye;
-				irr::core::matrix4   leftMove;
-
-				leftMove.setTranslation( irr::core::vector3df(-g_settings->getFloat("anaglyph_strength"),0.0f,0.0f) );
-				leftEye=(startMatrix*leftMove).getTranslation();
-
-				//clear the depth buffer, and color
-				driver->beginScene( true, true, irr::video::SColor(0,200,200,255) );
-
-				driver->getOverrideMaterial().Material.ColorMask = irr::video::ECP_RED;
-				driver->getOverrideMaterial().EnableFlags  = irr::video::EMF_COLOR_MASK;
-				driver->getOverrideMaterial().EnablePasses = irr::scene::ESNRP_SKY_BOX +
-															 irr::scene::ESNRP_SOLID +
-															 irr::scene::ESNRP_TRANSPARENT +
-															 irr::scene::ESNRP_TRANSPARENT_EFFECT +
-															 irr::scene::ESNRP_SHADOW;
-
-				camera.getCameraNode()->setPosition( leftEye );
-				camera.getCameraNode()->setTarget( focusPoint );
-
-				smgr->drawAll(); // 'smgr->drawAll();' may go here
-
-				driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
-
-				if (show_hud)
-					hud.drawSelectionBoxes(hilightboxes);
-
-
-				//Right eye...
-				irr::core::vector3df rightEye;
-				irr::core::matrix4   rightMove;
-
-				rightMove.setTranslation( irr::core::vector3df(g_settings->getFloat("anaglyph_strength"),0.0f,0.0f) );
-				rightEye=(startMatrix*rightMove).getTranslation();
-
-				//clear the depth buffer
-				driver->clearZBuffer();
 
-				driver->getOverrideMaterial().Material.ColorMask = irr::video::ECP_GREEN + irr::video::ECP_BLUE;
-				driver->getOverrideMaterial().EnableFlags  = irr::video::EMF_COLOR_MASK;
-				driver->getOverrideMaterial().EnablePasses = irr::scene::ESNRP_SKY_BOX +
-															 irr::scene::ESNRP_SOLID +
-															 irr::scene::ESNRP_TRANSPARENT +
-															 irr::scene::ESNRP_TRANSPARENT_EFFECT +
-															 irr::scene::ESNRP_SHADOW;
-
-				camera.getCameraNode()->setPosition( rightEye );
-				camera.getCameraNode()->setTarget( focusPoint );
-
-				smgr->drawAll(); // 'smgr->drawAll();' may go here
-
-				driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
-
-				if (show_hud)
-					hud.drawSelectionBoxes(hilightboxes);
-
-
-				//driver->endScene();
-
-				driver->getOverrideMaterial().Material.ColorMask=irr::video::ECP_ALL;
-				driver->getOverrideMaterial().EnableFlags=0;
-				driver->getOverrideMaterial().EnablePasses=0;
-
-				camera.getCameraNode()->setPosition( oldPosition );
-				camera.getCameraNode()->setTarget( oldTarget );
-			}
-
-			scenetime = timer.stop(true);
-		}
 		
-		{
-		//TimeTaker timer9("auxiliary drawings");
-		// 0ms
-		
-		//timer9.stop();
-		//TimeTaker //timer10("//timer10");
-		
-		video::SMaterial m;
-		//m.Thickness = 10;
-		m.Thickness = 3;
-		m.Lighting = false;
-		driver->setMaterial(m);
-
-		driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
-		if((!g_settings->getBool("anaglyph")) && (show_hud))
-		{
-			hud.drawSelectionBoxes(hilightboxes);
-		}
-
-		/*
-			Wielded tool
-		*/
-		if(show_hud &&
-			(player->hud_flags & HUD_FLAG_WIELDITEM_VISIBLE) &&
-			current_camera_mode < CAMERA_MODE_THIRD)
-		{
-			// Warning: This clears the Z buffer.
-			camera.drawWieldedTool();
-		}
+		draw_scene(driver, smgr, camera, client, player, hud, guienv,
+				hilightboxes, screensize, skycolor, show_hud);
 
 		/*
 			Post effects
 		*/
 		{
-			client.getEnv().getClientMap().renderPostFx();
+			client.getEnv().getClientMap().renderPostFx(camera.getCameraMode());
 		}
 
 		/*
@@ -3562,26 +3392,6 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
 			graph.draw(10, screensize.Y - 10, driver, font);
 		}
 
-		/*
-			Draw crosshair
-		*/
-		if (show_hud)
-			hud.drawCrosshair();
-			
-		} // timer
-
-		//timer10.stop();
-		//TimeTaker //timer11("//timer11");
-
-
-		/*
-			Draw hotbar
-		*/
-		if (show_hud)
-		{
-			hud.drawHotbar(client.getPlayerItem());
-		}
-
 		/*
 			Damage flash
 		*/
@@ -3605,18 +3415,6 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
 				player->hurt_tilt_strength = 0;
 		}
 
-		/*
-			Draw lua hud items
-		*/
-		if (show_hud)
-			hud.drawLuaElements(camera.getOffset());
-
-		/*
-			Draw gui
-		*/
-		// 0-1ms
-		guienv->drawAll();
-
 		/*
 			End scene
 		*/
@@ -3659,7 +3457,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
 	{
 		/*gui::IGUIStaticText *gui_shuttingdowntext = */
 		wchar_t* text = wgettext("Shutting down stuff...");
-		draw_load_screen(text, device, font, 0, -1, false);
+		draw_load_screen(text, device, guienv, font, 0, -1, false);
 		delete[] text;
 		/*driver->beginScene(true, true, video::SColor(255,0,0,0));
 		guienv->drawAll();
@@ -3728,5 +3526,3 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
 		<< driver-> getMaterialRendererCount ()
 		<< " (note: irrlicht doesn't support removing renderers)"<< std::endl;
 }
-
-

+ 0 - 4
src/hud.cpp

@@ -435,10 +435,6 @@ void Hud::drawHotbar(u16 playeritem) {
 
 
 void Hud::drawCrosshair() {
-	if (!(player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE) ||
-			(player->camera_mode == CAMERA_MODE_THIRD_FRONT)) {
-		return;
-	}
 		
 	if (use_crosshair_image) {
 		video::ITexture *crosshair = tsrc->getTexture("crosshair.png");

+ 3 - 3
src/localplayer.cpp

@@ -43,7 +43,6 @@ LocalPlayer::LocalPlayer(IGameDef *gamedef):
 	last_pitch(0),
 	last_yaw(0),
 	last_keyPressed(0),
-	camera_mode(0),
 	eye_offset_first(v3f(0,0,0)),
 	eye_offset_third(v3f(0,0,0)),
 	last_animation(NO_ANIM),
@@ -54,7 +53,8 @@ LocalPlayer::LocalPlayer(IGameDef *gamedef):
 	m_old_node_below(32767,32767,32767),
 	m_old_node_below_type("air"),
 	m_need_to_get_new_sneak_node(true),
-	m_can_jump(false)
+	m_can_jump(false),
+	m_cao(NULL)
 {
 	// Initialize hp to 0, so that no hearts will be shown if server
 	// doesn't support health points
@@ -505,7 +505,7 @@ void LocalPlayer::applyControl(float dtime)
 	if(control.jump)
 	{
 		if(free_move)
-		{			
+		{
 			if(g_settings->getBool("aux1_descends") || g_settings->getBool("always_fly_fast"))
 			{
 				if(fast_move)

+ 12 - 2
src/localplayer.h

@@ -24,7 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <list>
 
 class Environment;
-
+class GenericCAO;
 class ClientActiveObject;
 
 enum LocalPlayerAnimations {NO_ANIM, WALK_ANIM, DIG_ANIM, WD_ANIM};  // no local animation, walking, digging, both
@@ -62,7 +62,6 @@ public:
 	unsigned int last_keyPressed;
 
 	float camera_impact;
-	int camera_mode;
 	v3f eye_offset_first;
 	v3f eye_offset_third;
 
@@ -72,6 +71,15 @@ public:
 	std::string hotbar_image;
 	std::string hotbar_selected_image;
 
+	GenericCAO* getCAO() const {
+		return m_cao;
+	}
+
+	void setCAO(GenericCAO* toset) {
+		assert( m_cao == NULL );
+		m_cao = toset;
+	}
+
 private:
 	// This is used for determining the sneaking range
 	v3s16 m_sneak_node;
@@ -84,6 +92,8 @@ private:
 	// Whether recalculation of the sneak node is needed
 	bool m_need_to_get_new_sneak_node;
 	bool m_can_jump;
+
+	GenericCAO* m_cao;
 };
 
 #endif

+ 15 - 15
src/sky.cpp

@@ -13,7 +13,7 @@
 #include "camera.h" // CameraModes
 
 //! constructor
-Sky::Sky(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id, LocalPlayer* player):
+Sky::Sky(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id):
 		scene::ISceneNode(parent, mgr, id),
 		m_visible(true),
 		m_fallback_bg_color(255,255,255,255),
@@ -22,8 +22,7 @@ Sky::Sky(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id, LocalPlay
 		m_cloud_brightness(0.5),
 		m_bgcolor_bright_f(1,1,1,1),
 		m_skycolor_bright_f(1,1,1,1),
-		m_cloudcolor_bright_f(1,1,1,1),
-		m_player(player)
+		m_cloudcolor_bright_f(1,1,1,1)
 {
 	setAutomaticCulling(scene::EAC_OFF);
 	Box.MaxEdge.set(0,0,0);
@@ -66,14 +65,14 @@ Sky::Sky(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id, LocalPlay
 		m_materials[3].setTexture(0, m_sun_texture);
 		m_materials[3].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
 		if (m_sun_tonemap)
-			m_materials[3].Lighting = true;		
+			m_materials[3].Lighting = true;
 	}
 	if (m_moon_texture){
 		m_materials[4] = mat;
 		m_materials[4].setTexture(0, m_moon_texture);
 		m_materials[4].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
 		if (m_moon_tonemap)
-			m_materials[4].Lighting = true;		
+			m_materials[4].Lighting = true;
 	}
 
 	for(u32 i=0; i<SKY_STAR_COUNT; i++){
@@ -161,20 +160,20 @@ void Sky::render()
 		video::SColor mooncolor2 = mooncolor2_f.toSColor();
 
 		// Calculate offset normalized to the X dimension of a 512x1 px tonemap
-		float offset=(1.0-fabs(sin((m_time_of_day - 0.5)*irr::core::PI)))*511;       
+		float offset=(1.0-fabs(sin((m_time_of_day - 0.5)*irr::core::PI)))*511;
 
 		if (m_sun_tonemap){
 			u8 * texels = (u8 *)m_sun_tonemap->lock();
 			video::SColor* texel = (video::SColor *)(texels + (u32)offset * 4);
 			video::SColor texel_color (255,texel->getRed(),texel->getGreen(), texel->getBlue());
-			m_sun_tonemap->unlock();				
+			m_sun_tonemap->unlock();
 			m_materials[3].EmissiveColor = texel_color;
 		}
 		if (m_moon_tonemap){
 			u8 * texels = (u8 *)m_moon_tonemap->lock();
 			video::SColor* texel = (video::SColor *)(texels + (u32)offset * 4);
 			video::SColor texel_color (255,texel->getRed(),texel->getGreen(), texel->getBlue());
-			m_moon_tonemap->unlock();				
+			m_moon_tonemap->unlock();
 			m_materials[4].EmissiveColor = texel_color;
 		}
 
@@ -263,7 +262,7 @@ void Sky::render()
 		}
 
 		// Draw sun
-		if(wicked_time_of_day > 0.15 && wicked_time_of_day < 0.85){	
+		if(wicked_time_of_day > 0.15 && wicked_time_of_day < 0.85){
 			if (!m_sun_texture){
 				driver->setMaterial(m_materials[1]);
 				float d = sunsize * 1.7;
@@ -411,7 +410,7 @@ void Sky::render()
 					vertices[i].Pos.rotateXZBy(-90);
 					vertices[i].Pos.rotateXYBy(wicked_time_of_day * 360 - 90);
 				}
-				driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);		
+				driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
 			}
 		}
 
@@ -485,7 +484,8 @@ void Sky::render()
 }
 
 void Sky::update(float time_of_day, float time_brightness,
-		float direct_brightness, bool sunlight_seen)
+		float direct_brightness, bool sunlight_seen,
+		CameraMode cam_mode, float yaw, float pitch)
 {
 	// Stabilize initial brightness and color values by flooding updates
 	if(m_first_update){
@@ -496,7 +496,7 @@ void Sky::update(float time_of_day, float time_brightness,
 		m_first_update = false;
 		for(u32 i=0; i<100; i++){
 			update(time_of_day, time_brightness, direct_brightness,
-					sunlight_seen);
+					sunlight_seen, cam_mode, yaw, pitch);
 		}
 		return;
 	}
@@ -580,16 +580,16 @@ void Sky::update(float time_of_day, float time_brightness,
 		{
 			// calculate hemisphere value from yaw, (inverted in third person front view)
 			s8 dir_factor = 1;
-			if (m_player->camera_mode > CAMERA_MODE_THIRD)
+			if (cam_mode > CAMERA_MODE_THIRD)
 				dir_factor = -1;
-			f32 pointcolor_blend = wrapDegrees_0_360(m_player->getYaw()*dir_factor + 90);
+			f32 pointcolor_blend = wrapDegrees_0_360( yaw*dir_factor + 90);
 			if (pointcolor_blend > 180)
 				pointcolor_blend = 360 - pointcolor_blend;
 			pointcolor_blend /= 180;
 			// bound view angle to determine where transition starts and ends
 			pointcolor_blend = rangelim(1 - pointcolor_blend * 1.375, 0, 1 / 1.375) * 1.375;
 			// combine the colors when looking up or down, otherwise turning looks weird
-			pointcolor_blend += (0.5 - pointcolor_blend) * (1 - MYMIN((90 - std::abs(m_player->getPitch())) / 90 * 1.5, 1));
+			pointcolor_blend += (0.5 - pointcolor_blend) * (1 - MYMIN((90 - std::abs(pitch)) / 90 * 1.5, 1));
 			// invert direction to match where the sun and moon are rising
 			if (m_time_of_day > 0.5)
 				pointcolor_blend = 1 - pointcolor_blend;

+ 4 - 4
src/sky.h

@@ -19,7 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #include "irrlichttypes_extrabloated.h"
 #include <ISceneNode.h>
-#include "localplayer.h"
+#include "camera.h"
 
 #ifndef SKY_HEADER
 #define SKY_HEADER
@@ -32,7 +32,7 @@ class Sky : public scene::ISceneNode
 {
 public:
 	//! constructor
-	Sky(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id, LocalPlayer* player);
+	Sky(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id);
 
 	virtual void OnRegisterSceneNode();
 
@@ -50,7 +50,8 @@ public:
 	{ return SKY_MATERIAL_COUNT; }
 
 	void update(float m_time_of_day, float time_brightness,
-			float direct_brightness, bool sunlight_seen);
+			float direct_brightness, bool sunlight_seen, CameraMode cam_mode,
+			float yaw, float pitch);
 	
 	float getBrightness(){ return m_brightness; }
 
@@ -126,7 +127,6 @@ private:
 	video::SColorf m_cloudcolor_f;
 	v3f m_stars[SKY_STAR_COUNT];
 	video::S3DVertex m_star_vertices[SKY_STAR_COUNT*4];
-	LocalPlayer* m_player;
 	video::ITexture* m_sun_texture;
 	video::ITexture* m_moon_texture;
 	video::ITexture* m_sun_tonemap;