From f31b0a3361c0c39b9f6f6ee440b93293690bbe02 Mon Sep 17 00:00:00 2001 From: JacobF Date: Wed, 7 Sep 2011 10:56:04 -0400 Subject: [PATCH 01/26] Display which tool the player is holding And some simple animation when trying to dig... --- src/client.cpp | 8 ++++++ src/client.h | 1 + src/game.cpp | 60 ++++++++++++++++++++++++++++++++++++++- src/inventory.h | 75 ++++++++++++++++++++++++++++++------------------- src/player.cpp | 19 +++++++++++++ src/player.h | 4 +++ 6 files changed, 137 insertions(+), 30 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index a5ed6f61..d491f9d3 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -2008,6 +2008,14 @@ v3f Client::getPlayerPosition(v3f *eye_position) return player->getPosition(); } +void Client::setPlayerWield(scene::ISceneNode *wield) +{ + //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out + LocalPlayer *player = m_env.getLocalPlayer(); + assert(player != NULL); + player->wield = wield; +} + void Client::setPlayerControl(PlayerControl &control) { //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out diff --git a/src/client.h b/src/client.h index 1a7ef924..398a3b84 100644 --- a/src/client.h +++ b/src/client.h @@ -210,6 +210,7 @@ class Client : public con::PeerHandler, public InventoryManager // eye position in *eye_position v3f getPlayerPosition(v3f *eye_position=NULL); + void setPlayerWield(scene::ISceneNode *wield); void setPlayerControl(PlayerControl &control); void selectPlayerItem(u16 item); diff --git a/src/game.cpp b/src/game.cpp index dc3ed245..86f1939c 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -956,7 +956,10 @@ void the_game( v3f(BS*100, BS*2, BS*100), // Look from v3f(BS*100+1, BS*2, BS*100), // Look to -1 // Camera ID - ); + ); + + // Do this so children rotate accordingly (tool) + camera->bindTargetAndRotation(true); if(camera == NULL) { @@ -972,6 +975,44 @@ void the_game( f32 camera_yaw = 0; // "right/left" f32 camera_pitch = 0; // "up/down" + /* + Tool + */ + + v3f tool_wield_position(0.6, -0.6, 1.0); + v3f tool_wield_rotation(-25, 180, -25); + float tool_wield_animation = 0.0; + scene::IMeshSceneNode *tool_wield; + { + scene::SMesh *mesh = new scene::SMesh(); + scene::IMeshBuffer *buf = new scene::SMeshBuffer(); + video::SColor c(255,255,255,255); + video::S3DVertex vertices[4] = + { + video::S3DVertex(-0.5,0,0, 0,0,0, c, 0,1), + video::S3DVertex(0.5,0,0, 0,0,0, c, 1,1), + video::S3DVertex(0.5,0.5,0, 0,0,0, c, 1,0), + video::S3DVertex(-0.5,0.5,0, 0,0,0, c, 0,0), + }; + u16 indices[] = {0,1,2,2,3,0}; + buf->append(vertices, 4, indices, 6); + // Set material + buf->getMaterial().setFlag(video::EMF_LIGHTING, false); + buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); + buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; + // Add to mesh + mesh->addMeshBuffer(buf); + buf->drop(); + + tool_wield = smgr->addMeshSceneNode(mesh, camera); + mesh->drop(); + } + tool_wield->setVisible(false); + tool_wield->setPosition(tool_wield_position); + tool_wield->setRotation(tool_wield_rotation); + + client.setPlayerWield(tool_wield); + /* Clouds */ @@ -1920,6 +1961,7 @@ void the_game( } } + if(input->getRightClicked()) { std::cout<getLeftState()) + // Tool animation loops 0.0 - 1.0 + tool_wield_animation = fmod(tool_wield_animation + dtime * 3.0, 1.0); + else + // Return tool to holding position if not digging + tool_wield_animation /= 1.5; + } // selected_object == NULL input->resetLeftClicked(); @@ -2103,6 +2153,14 @@ void the_game( ); } + /* + Animate tool + */ + { + tool_wield->setRotation(tool_wield_rotation - sin(tool_wield_animation * PI) * 40.0); + tool_wield->setPosition(tool_wield_position - sin(tool_wield_animation * PI) / 3.0); + } + /* Update gui stuff (0ms) diff --git a/src/inventory.h b/src/inventory.h index 44ba6a5a..f70d69b6 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -53,6 +53,10 @@ class InventoryItem // Shall make an exact clone of the item virtual InventoryItem* clone() = 0; #ifndef SERVER + // Return the name of the image for this item + virtual std::string getBasename() { return ""; } + // Shall return an image of the item (or NULL) + virtual video::ITexture * getImageRaw() { return NULL; } // Shall return an image to show in the GUI (or NULL) virtual video::ITexture * getImage() { return NULL; } #endif @@ -353,40 +357,53 @@ class ToolItem : public InventoryItem return new ToolItem(m_toolname, m_wear); } #ifndef SERVER + std::string getBasename() { + if(m_toolname == "WPick") + return "tool_woodpick.png"; + else if(m_toolname == "STPick") + return "tool_stonepick.png"; + else if(m_toolname == "SteelPick") + return "tool_steelpick.png"; + else if(m_toolname == "MesePick") + return "tool_mesepick.png"; + else if(m_toolname == "WShovel") + return "tool_woodshovel.png"; + else if(m_toolname == "STShovel") + return "tool_stoneshovel.png"; + else if(m_toolname == "SteelShovel") + return "tool_steelshovel.png"; + else if(m_toolname == "WAxe") + return "tool_woodaxe.png"; + else if(m_toolname == "STAxe") + return "tool_stoneaxe.png"; + else if(m_toolname == "SteelAxe") + return "tool_steelaxe.png"; + else if(m_toolname == "WSword") + return "tool_woodsword.png"; + else if(m_toolname == "STSword") + return "tool_stonesword.png"; + else if(m_toolname == "SteelSword") + return "tool_steelsword.png"; + else + return "cloud.png"; +} + + video::ITexture * getImageRaw() + { + if(g_texturesource == NULL) + return NULL; + + return g_texturesource->getTextureRaw(getBasename()); + } + video::ITexture * getImage() { if(g_texturesource == NULL) return NULL; - std::string basename; - if(m_toolname == "WPick") - basename = "tool_woodpick.png"; - else if(m_toolname == "STPick") - basename = "tool_stonepick.png"; - else if(m_toolname == "SteelPick") - basename = "tool_steelpick.png"; - else if(m_toolname == "MesePick") - basename = "tool_mesepick.png"; - else if(m_toolname == "WShovel") - basename = "tool_woodshovel.png"; - else if(m_toolname == "STShovel") - basename = "tool_stoneshovel.png"; - else if(m_toolname == "SteelShovel") - basename = "tool_steelshovel.png"; - else if(m_toolname == "WAxe") - basename = "tool_woodaxe.png"; - else if(m_toolname == "STAxe") - basename = "tool_stoneaxe.png"; - else if(m_toolname == "SteelAxe") - basename = "tool_steelaxe.png"; - else if(m_toolname == "WSword") - basename = "tool_woodsword.png"; - else if(m_toolname == "STSword") - basename = "tool_stonesword.png"; - else if(m_toolname == "SteelSword") - basename = "tool_steelsword.png"; - else - basename = "cloud.png"; + std::string basename = getBasename(); + + return g_texturesource->getTextureRaw(basename); /* Calculate a progress value with sane amount of diff --git a/src/player.cpp b/src/player.cpp index 7cfdfebb..03ae24f4 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -309,12 +309,31 @@ LocalPlayer::LocalPlayer(): // Initialize hp to 0, so that no hearts will be shown if server // doesn't support health points hp = 0; + + // No tool wielded initially + wield = NULL; } LocalPlayer::~LocalPlayer() { } +void LocalPlayer::wieldItem(u16 item) +{ + m_selected_item = item; + + if(wield) { + InventoryItem* i = inventory.getList("main")->getItem(m_selected_item); + + if(i && strcmp(i->getName(), "ToolItem") == 0) { + wield->getMaterial(0).setTexture(0, i->getImageRaw()); + wield->setVisible(true); + } + else + wield->setVisible(false); + } +} + void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, core::list *collision_info) { diff --git a/src/player.h b/src/player.h index 13cffa20..0f2c4001 100644 --- a/src/player.h +++ b/src/player.h @@ -356,6 +356,8 @@ class LocalPlayer : public Player { return true; } + + void wieldItem(u16 item); void move(f32 dtime, Map &map, f32 pos_max_d, core::list *collision_info); @@ -365,6 +367,8 @@ class LocalPlayer : public Player PlayerControl control; + scene::ISceneNode *wield; + private: // This is used for determining the sneaking range v3s16 m_sneak_node; From c0b35fa429c68b49b2d6a5124aff6dcc31400b63 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Wed, 7 Sep 2011 19:21:28 +0200 Subject: [PATCH 02/26] Removed unused camera_position and camera_direction fields from Client. Moved ClientEnvironment::drawPostFx to ClientMap::renderPostFx -- this will make the camera management classes easier to write, as ClientMap already knows the camera position but ClientEnvironment doesn't and has to be told about it. This also eliminates the need for Client::getEnv(). Made the post effect color a content feature defined in content_mapnode.h. --- src/client.cpp | 14 ++++++++++---- src/client.h | 20 +++++--------------- src/content_mapnode.cpp | 4 ++++ src/environment.cpp | 23 ----------------------- src/environment.h | 3 --- src/game.cpp | 16 ++++++++-------- src/map.cpp | 29 +++++++++++++++++++++++++++++ src/map.h | 2 ++ src/mapnode.h | 3 +++ 9 files changed, 61 insertions(+), 53 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index a5ed6f61..df792d11 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -189,8 +189,6 @@ Client::Client( ), m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this), m_device(device), - camera_position(0,0,0), - camera_direction(0,0,1), m_server_ser_ver(SER_FMT_VER_INVALID), m_inventory_updated(false), m_time_of_day(0), @@ -1983,8 +1981,11 @@ void Client::addNode(v3s16 p, MapNode n) void Client::updateCamera(v3f pos, v3f dir) { m_env.getClientMap().updateCamera(pos, dir); - camera_position = pos; - camera_direction = dir; +} + +void Client::renderPostFx() +{ + m_env.getClientMap().renderPostFx(); } MapNode Client::getNode(v3s16 p) @@ -1998,6 +1999,11 @@ NodeMetadata* Client::getNodeMetadata(v3s16 p) return m_env.getMap().getNodeMetadata(p); } +LocalPlayer* Client::getLocalPlayer() +{ + return m_env.getLocalPlayer(); +} + v3f Client::getPlayerPosition(v3f *eye_position) { //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out diff --git a/src/client.h b/src/client.h index 1a7ef924..9c942ff9 100644 --- a/src/client.h +++ b/src/client.h @@ -201,14 +201,16 @@ class Client : public con::PeerHandler, public InventoryManager void updateCamera(v3f pos, v3f dir); + void renderPostFx(); + // Returns InvalidPositionException if not found MapNode getNode(v3s16 p); // Wrapper to Map NodeMetadata* getNodeMetadata(v3s16 p); - // Get the player position, and optionally put the - // eye position in *eye_position - v3f getPlayerPosition(v3f *eye_position=NULL); + LocalPlayer* getLocalPlayer(); + + v3f getPlayerPosition(v3f *eye_position); void setPlayerControl(PlayerControl &control); @@ -302,15 +304,6 @@ class Client : public con::PeerHandler, public InventoryManager { return m_access_denied_reason; } - - /* - This should only be used for calling the special drawing stuff in - ClientEnvironment - */ - ClientEnvironment * getEnv() - { - return &m_env; - } private: @@ -342,9 +335,6 @@ class Client : public con::PeerHandler, public InventoryManager IrrlichtDevice *m_device; - v3f camera_position; - v3f camera_direction; - // Server serialization version u8 m_server_ser_ver; diff --git a/src/content_mapnode.cpp b/src/content_mapnode.cpp index 51f2f973..89171755 100644 --- a/src/content_mapnode.cpp +++ b/src/content_mapnode.cpp @@ -385,6 +385,7 @@ void content_mapnode_init() f->liquid_alternative_source = CONTENT_WATERSOURCE; f->liquid_viscosity = WATER_VISC; f->vertex_alpha = WATER_ALPHA; + f->post_effect_color = video::SColor(64, 100, 100, 200); if(f->special_material == NULL && g_texturesource) { // Flowing water material @@ -433,6 +434,7 @@ void content_mapnode_init() f->liquid_alternative_source = CONTENT_WATERSOURCE; f->liquid_viscosity = WATER_VISC; f->vertex_alpha = WATER_ALPHA; + f->post_effect_color = video::SColor(64, 100, 100, 200); if(f->special_material == NULL && g_texturesource) { // Flowing water material @@ -465,6 +467,7 @@ void content_mapnode_init() f->liquid_alternative_source = CONTENT_LAVASOURCE; f->liquid_viscosity = LAVA_VISC; f->damage_per_second = 4*2; + f->post_effect_color = video::SColor(192, 255, 64, 0); if(f->special_material == NULL && g_texturesource) { // Flowing lava material @@ -514,6 +517,7 @@ void content_mapnode_init() f->liquid_alternative_source = CONTENT_LAVASOURCE; f->liquid_viscosity = LAVA_VISC; f->damage_per_second = 4*2; + f->post_effect_color = video::SColor(192, 255, 64, 0); if(f->special_material == NULL && g_texturesource) { // Flowing lava material diff --git a/src/environment.cpp b/src/environment.cpp index 8103b711..80f41f9f 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -1940,29 +1940,6 @@ ClientEnvEvent ClientEnvironment::getClientEvent() return m_client_event_queue.pop_front(); } -void ClientEnvironment::drawPostFx(video::IVideoDriver* driver, v3f camera_pos) -{ - /*LocalPlayer *player = getLocalPlayer(); - assert(player); - v3f pos_f = player->getPosition() + v3f(0,BS*1.625,0);*/ - v3f pos_f = camera_pos; - v3s16 p_nodes = floatToInt(pos_f, BS); - MapNode n = m_map->getNodeNoEx(p_nodes); - if(n.getContent() == CONTENT_WATER || n.getContent() == CONTENT_WATERSOURCE) - { - v2u32 ss = driver->getScreenSize(); - core::rect rect(0,0, ss.X, ss.Y); - driver->draw2DRectangle(video::SColor(64, 100, 100, 200), rect); - } - else if(content_features(n).solidness == 2 && - g_settings.getBool("free_move") == false) - { - v2u32 ss = driver->getScreenSize(); - core::rect rect(0,0, ss.X, ss.Y); - driver->draw2DRectangle(video::SColor(255, 0, 0, 0), rect); - } -} - #endif // #ifndef SERVER diff --git a/src/environment.h b/src/environment.h index d9248d2a..055e2b1f 100644 --- a/src/environment.h +++ b/src/environment.h @@ -406,9 +406,6 @@ class ClientEnvironment : public Environment // Get event from queue. CEE_NONE is returned if queue is empty. ClientEnvEvent getClientEvent(); - - // Post effects - void drawPostFx(video::IVideoDriver* driver, v3f camera_pos); private: ClientMap *m_map; diff --git a/src/game.cpp b/src/game.cpp index dc3ed245..afe1ce80 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -2032,7 +2032,7 @@ void the_game( update_skybox(driver, smgr, skybox, brightness); /* - Update coulds + Update clouds */ if(clouds) { @@ -2313,6 +2313,13 @@ void the_game( driver->draw3DBox(*i, video::SColor(255,0,0,0)); } + /* + Post effects + */ + { + client.renderPostFx(); + } + /* Frametime log */ @@ -2352,13 +2359,6 @@ void the_game( // 0-1ms guienv->drawAll(); - /* - Environment post fx - */ - { - client.getEnv()->drawPostFx(driver, camera_position); - } - /* Draw hotbar */ diff --git a/src/map.cpp b/src/map.cpp index 7de79c75..6f22498f 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -3925,6 +3925,35 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) <<", rendered "<getVideoDriver(); + v2u32 ss = driver->getScreenSize(); + core::rect rect(0,0, ss.X, ss.Y); + driver->draw2DRectangle(post_effect_color, rect); + } +} + bool ClientMap::setTempMod(v3s16 p, NodeMod mod, core::map *affected_blocks) { diff --git a/src/map.h b/src/map.h index e0b67eb6..5bea4a13 100644 --- a/src/map.h +++ b/src/map.h @@ -552,6 +552,8 @@ class ClientMap : public Map, public scene::ISceneNode void renderMap(video::IVideoDriver* driver, s32 pass); + void renderPostFx(); + /* Methods for setting temporary modifications to nodes for drawing. diff --git a/src/mapnode.h b/src/mapnode.h index 3ad67aaf..19dfb280 100644 --- a/src/mapnode.h +++ b/src/mapnode.h @@ -160,6 +160,8 @@ struct ContentFeatures u8 liquid_viscosity; // Used currently for flowing liquids u8 vertex_alpha; + // Post effect color, drawn when the camera is inside the node. + video::SColor post_effect_color; // Special irrlicht material, used sometimes video::SMaterial *special_material; AtlasPointer *special_atlas; @@ -197,6 +199,7 @@ struct ContentFeatures liquid_alternative_source = CONTENT_IGNORE; liquid_viscosity = 0; vertex_alpha = 255; + post_effect_color = video::SColor(0, 0, 0, 0); special_material = NULL; special_atlas = NULL; light_source = 0; From baf7da9d4a7fc0566840b159903999d76d99a228 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Thu, 8 Sep 2011 01:08:47 +0200 Subject: [PATCH 03/26] Collected and moved existing camera infrastructure from game.cpp to camera.cpp and camera.h. Introduced configuration settings 'fov' which chooses the camera's (vertical) field of view and 'view_bobbing' which currently does nothing. Other code refactored to not expect the FOV to be a build time constant. --- src/CMakeLists.txt | 1 + src/camera.cpp | 243 ++++++++++++++++++++++++++++++++++++++++ src/camera.h | 141 +++++++++++++++++++++++ src/client.cpp | 14 +-- src/client.h | 4 +- src/constants.h | 3 - src/defaultsettings.cpp | 2 + src/game.cpp | 205 ++++----------------------------- src/map.cpp | 7 +- src/map.h | 4 +- src/server.cpp | 2 +- src/utility.cpp | 7 +- src/utility.h | 4 +- 13 files changed, 428 insertions(+), 209 deletions(-) create mode 100644 src/camera.cpp create mode 100644 src/camera.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9c3b0960..80ee0fc6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -142,6 +142,7 @@ set(minetest_SRCS mapblock_mesh.cpp farmesh.cpp keycode.cpp + camera.cpp clouds.cpp clientobject.cpp guiMainMenu.cpp diff --git a/src/camera.cpp b/src/camera.cpp new file mode 100644 index 00000000..30df439e --- /dev/null +++ b/src/camera.cpp @@ -0,0 +1,243 @@ +/* +Minetest-c55 +Copyright (C) 2010-2011 celeron55, Perttu Ahola + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 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 General Public License for more details. + +You should have received a copy of the GNU 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 "camera.h" +#include "debug.h" +#include "main.h" // for g_settings +#include "map.h" +#include "player.h" +#include "utility.h" +#include + +Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control): + m_smgr(smgr), + m_playernode(NULL), + m_cameranode(NULL), + m_draw_control(draw_control), + m_viewing_range_min(5.0), + m_viewing_range_max(5.0), + + m_camera_position(0,0,0), + m_camera_direction(0,0,0), + + m_aspect(1.0), + m_fov_x(1.0), + m_fov_y(1.0), + + m_wanted_frametime(0.0), + m_added_frametime(0), + m_added_frames(0), + m_range_old(0), + m_frametime_old(0), + m_frametime_counter(0), + m_time_per_range(30. / 50), // a sane default of 30ms per 50 nodes of range + + m_view_bobbing_anim(0), + m_view_bobbing_anim_left(0) +{ + dstream<<__FUNCTION_NAME<addEmptySceneNode(smgr->getRootSceneNode()); + m_cameranode = smgr->addCameraSceneNode(m_playernode); + + updateSettings(); +} + +Camera::~Camera() +{ +} + +void Camera::step(f32 dtime) +{ +} + +void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize) +{ + if (m_playernode == NULL || m_cameranode == NULL) + return; + + // FOV and and aspect ratio + m_aspect = (f32)screensize.X / (f32) screensize.Y; + m_fov_x = 2 * atan(0.5 * m_aspect * tan(m_fov_y)); + m_cameranode->setAspectRatio(m_aspect); + m_cameranode->setFOV(m_fov_y); + + // Just so big a value that everything rendered is visible + // Some more allowance that m_viewing_range_max * BS because of active objects etc. + m_cameranode->setFarValue(m_viewing_range_max * BS * 10); + + m_camera_position = player->getEyePosition(); // TODO bobbing + m_cameranode->setPosition(m_camera_position); + + m_camera_direction = v3f(0,0,1); + m_camera_direction.rotateYZBy(player->getPitch()); + m_camera_direction.rotateXZBy(player->getYaw()); + // *100.0 helps in large map coordinates + m_cameranode->setTarget(m_camera_position + m_camera_direction * 100.0); + + // Render distance feedback loop + updateViewingRange(frametime); + + // Check if view bobbing is active + v3f speed = player->getSpeed(); + f32 epsilon = BS / 1000.0; + if (speed.X * speed.X + speed.Z * speed.Z > epsilon*epsilon && + speed.Y < epsilon && + g_settings.getBool("view_bobbing") == true && + g_settings.getBool("free_move") == false) + { + // The player seems to be walking on solid ground. + // Enable view bobbing. + //dstream << "View bobbing active" << std::endl; + } + else + { + //dstream << "View bobbing inactive" << std::endl; + } +} + +void Camera::updateViewingRange(f32 frametime_in) +{ + if (m_draw_control.range_all) + return; + + m_added_frametime += frametime_in; + m_added_frames += 1; + + // Actually this counter kind of sucks because frametime is busytime + m_frametime_counter -= frametime_in; + if (m_frametime_counter > 0) + return; + m_frametime_counter = 0.2; + + dstream<<__FUNCTION_NAME + <<": Collected "< + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 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 General Public License for more details. + +You should have received a copy of the GNU 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 CAMERA_HEADER +#define CAMERA_HEADER + +#include "common_irrlicht.h" +#include "utility.h" + +class LocalPlayer; +class MapDrawControl; + +/* + Client camera class, manages the player and camera scene nodes, the viewing distance + and performs view bobbing etc. +*/ +class Camera +{ +public: + Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control); + ~Camera(); + + // Get player scene node. + // This node is positioned at the player's torso (without any view bobbing), + // as given by Player::m_position, Player::m_pitch and Player::m_yaw. + // Things like wielded tools should be positioned relative to this node. + inline scene::ISceneNode* getPlayerNode() const + { + return m_playernode; + } + + // Get camera scene node. + // The camera node is a child of the player node. + // It has the eye transformation and view bobbing applied. + inline scene::ICameraSceneNode* getCameraNode() const + { + return m_cameranode; + } + + // Get the camera position (in absolute scene coordinates). + // This has view bobbing applied. + inline v3f getPosition() const + { + return m_camera_position; + } + + // Get the camera direction (in absolute camera coordinates). + // This has view bobbing applied. + inline v3f getDirection() const + { + return m_camera_direction; + } + + // Horizontal field of view + inline f32 getFovX() const + { + return m_fov_x; + } + + // Vertical field of view + inline f32 getFovY() const + { + return m_fov_y; + } + + // Get maximum of getFovX() and getFovY() + inline f32 getFovMax() const + { + return MYMAX(m_fov_x, m_fov_y); + } + + // Step the camera: updates the viewing range and view bobbing. + void step(f32 dtime); + + // Update the camera from the local player's position. + // frametime is used to adjust the viewing range. + void update(LocalPlayer* player, f32 frametime, v2u32 screensize); + + // Render distance feedback loop + void updateViewingRange(f32 frametime_in); + + // Update settings from g_settings + void updateSettings(); + +private: + // Scene manager and nodes + scene::ISceneManager* m_smgr; + scene::ISceneNode* m_playernode; + scene::ICameraSceneNode* m_cameranode; + + // draw control + MapDrawControl& m_draw_control; + + // viewing_range_min_nodes setting + f32 m_viewing_range_min; + // viewing_range_max_nodes setting + f32 m_viewing_range_max; + + // Absolute camera position + v3f m_camera_position; + // Absolute camera direction + v3f m_camera_direction; + + // Field of view and aspect ratio stuff + f32 m_aspect; + f32 m_fov_x; + f32 m_fov_y; + + // Stuff for viewing range calculations + f32 m_wanted_frametime; + f32 m_added_frametime; + s16 m_added_frames; + f32 m_range_old; + f32 m_frametime_old; + f32 m_frametime_counter; + f32 m_time_per_range; + + // View bobbing animation frame (0 <= m_view_bobbing < 0x10000) + u32 m_view_bobbing_anim; + // Number of frames to continue the view bobbing animation. + u32 m_view_bobbing_anim_left; +}; + +#endif + diff --git a/src/client.cpp b/src/client.cpp index df792d11..81dedd14 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1978,9 +1978,9 @@ void Client::addNode(v3s16 p, MapNode n) } } -void Client::updateCamera(v3f pos, v3f dir) +void Client::updateCamera(v3f pos, v3f dir, f32 fov) { - m_env.getClientMap().updateCamera(pos, dir); + m_env.getClientMap().updateCamera(pos, dir, fov); } void Client::renderPostFx() @@ -2004,16 +2004,6 @@ LocalPlayer* Client::getLocalPlayer() return m_env.getLocalPlayer(); } -v3f Client::getPlayerPosition(v3f *eye_position) -{ - //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out - LocalPlayer *player = m_env.getLocalPlayer(); - assert(player != NULL); - if (eye_position) - *eye_position = player->getEyePosition(); - return player->getPosition(); -} - void Client::setPlayerControl(PlayerControl &control) { //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out diff --git a/src/client.h b/src/client.h index 9c942ff9..930987c0 100644 --- a/src/client.h +++ b/src/client.h @@ -199,7 +199,7 @@ class Client : public con::PeerHandler, public InventoryManager // locks envlock void addNode(v3s16 p, MapNode n); - void updateCamera(v3f pos, v3f dir); + void updateCamera(v3f pos, v3f dir, f32 fov); void renderPostFx(); @@ -210,8 +210,6 @@ class Client : public con::PeerHandler, public InventoryManager LocalPlayer* getLocalPlayer(); - v3f getPlayerPosition(v3f *eye_position); - void setPlayerControl(PlayerControl &control); void selectPlayerItem(u16 item); diff --git a/src/constants.h b/src/constants.h index 1af5f1f1..9ba10b51 100644 --- a/src/constants.h +++ b/src/constants.h @@ -44,9 +44,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #define PI 3.14159 -// This is the same as in minecraft and everything else -#define FOV_ANGLE (PI/2.5) - // The absolute working limit is (2^15 - viewing_range). // I really don't want to make every algorithm to check if it's // going near the limit or not, so this is lower. diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 1e17f2f3..163ed088 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -59,6 +59,8 @@ void set_default_settings() g_settings.setDefault("random_input", "false"); g_settings.setDefault("client_unload_unused_data_timeout", "600"); g_settings.setDefault("enable_fog", "true"); + g_settings.setDefault("fov", "72"); + g_settings.setDefault("view_bobbing", "true"); g_settings.setDefault("new_style_water", "false"); g_settings.setDefault("new_style_leaves", "true"); g_settings.setDefault("smooth_lighting", "true"); diff --git a/src/game.cpp b/src/game.cpp index afe1ce80..fc1486b7 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "materials.h" #include "config.h" #include "clouds.h" +#include "camera.h" #include "farmesh.h" #include "mapblock.h" @@ -49,8 +50,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #define FIELD_OF_VIEW_TEST 0 -MapDrawControl draw_control; - // Chat data struct ChatLine { @@ -143,144 +142,6 @@ struct TextDestSignNode : public TextDest Client *m_client; }; -/* - Render distance feedback loop -*/ -void updateViewingRange(f32 frametime_in, Client *client) -{ - if(draw_control.range_all == true) - return; - - static f32 added_frametime = 0; - static s16 added_frames = 0; - - added_frametime += frametime_in; - added_frames += 1; - - // Actually this counter kind of sucks because frametime is busytime - static f32 counter = 0; - counter -= frametime_in; - if(counter > 0) - return; - //counter = 0.1; - counter = 0.2; - - /*dstream<<__FUNCTION_NAME - <<": Collected "< range_max) - new_range = range_max; - - /*dstream<<"new_range="<addCameraSceneNode( - 0, // Camera parent - v3f(BS*100, BS*2, BS*100), // Look from - v3f(BS*100+1, BS*2, BS*100), // Look to - -1 // Camera ID - ); - - if(camera == NULL) + Camera camera(smgr, draw_control); + if (camera.getPlayerNode() == NULL) + { + error_message = L"Failed to create the player node"; + return; + } + if (camera.getCameraNode() == NULL) { error_message = L"Failed to create the camera node"; return; } - camera->setFOV(FOV_ANGLE); - - // Just so big a value that everything rendered is visible - camera->setFarValue(100000*BS); - f32 camera_yaw = 0; // "right/left" f32 camera_pitch = 0; // "up/down" @@ -1168,12 +1023,6 @@ void the_game( // Necessary for device->getTimer()->getTime() device->run(); - /* - Viewing range - */ - - updateViewingRange(busytime, &client); - /* FPS limiter */ @@ -1565,10 +1414,6 @@ void the_game( } } - // Get player position - v3f camera_position; - v3f player_position = client.getPlayerPosition(&camera_position); - //TimeTaker //timer2("//timer2"); /* @@ -1621,25 +1466,25 @@ void the_game( first_loop_after_window_activation = true; } - camera_yaw = wrapDegrees(camera_yaw); - camera_pitch = wrapDegrees(camera_pitch); - - v3f camera_direction = v3f(0,0,1); - camera_direction.rotateYZBy(camera_pitch); - camera_direction.rotateXZBy(camera_yaw); + LocalPlayer* player = client.getLocalPlayer(); + camera.update(player, busytime, screensize); + camera.step(dtime); - camera->setPosition(camera_position); - // *100.0 helps in large map coordinates - camera->setTarget(camera_position + camera_direction * 100.0); + v3f player_position = player->getPosition(); + v3f camera_position = camera.getPosition(); + v3f camera_direction = camera.getDirection(); + f32 camera_fov = camera.getFovMax(); - if(FIELD_OF_VIEW_TEST){ - client.updateCamera(v3f(0,0,0), v3f(0,0,1)); + if(FIELD_OF_VIEW_TEST) + { + client.updateCamera(v3f(0,0,0), v3f(0,0,1), M_PI); } - else{ - //TimeTaker timer("client.updateCamera"); - client.updateCamera(camera_position, camera_direction); + else + { + client.updateCamera(camera_position, + camera_direction, camera_fov); } - + //timer2.stop(); //TimeTaker //timer3("//timer3"); @@ -2010,8 +1855,6 @@ void the_game( Calculate stuff for drawing */ - camera->setAspectRatio((f32)screensize.X / (f32)screensize.Y); - u32 daynight_ratio = client.getDayNightRatio(); u8 l = decode_light((daynight_ratio * LIGHT_SUN) / 1000); video::SColor bgcolor = video::SColor( diff --git a/src/map.cpp b/src/map.cpp index 6f22498f..b1908fe2 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -3604,7 +3604,8 @@ ClientMap::ClientMap( m_client(client), m_control(control), m_camera_position(0,0,0), - m_camera_direction(0,0,1) + m_camera_direction(0,0,1), + m_camera_fov(M_PI) { m_camera_mutex.Init(); assert(m_camera_mutex.IsInitialized()); @@ -3713,6 +3714,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) m_camera_mutex.Lock(); v3f camera_position = m_camera_position; v3f camera_direction = m_camera_direction; + f32 camera_fov = m_camera_fov; m_camera_mutex.Unlock(); /* @@ -3805,7 +3807,8 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) float d = 0.0; if(isBlockInSight(block->getPos(), camera_position, - camera_direction, range, &d) == false) + camera_direction, camera_fov, + range, &d) == false) { continue; } diff --git a/src/map.h b/src/map.h index 5bea4a13..cb649add 100644 --- a/src/map.h +++ b/src/map.h @@ -518,11 +518,12 @@ class ClientMap : public Map, public scene::ISceneNode ISceneNode::drop(); } - void updateCamera(v3f pos, v3f dir) + void updateCamera(v3f pos, v3f dir, f32 fov) { JMutexAutoLock lock(m_camera_mutex); m_camera_position = pos; m_camera_direction = dir; + m_camera_fov = fov; } /* @@ -603,6 +604,7 @@ class ClientMap : public Map, public scene::ISceneNode v3f m_camera_position; v3f m_camera_direction; + f32 m_camera_fov; JMutex m_camera_mutex; core::map m_last_drawn_sectors; diff --git a/src/server.cpp b/src/server.cpp index 14d8942c..fd93d752 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -584,7 +584,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, Don't generate or send if not in sight */ - if(isBlockInSight(p, camera_pos, camera_dir, 10000*BS) == false) + if(isBlockInSight(p, camera_pos, camera_dir, M_PI, 10000*BS) == false) { continue; } diff --git a/src/utility.cpp b/src/utility.cpp index 0721100c..9c1edc8a 100644 --- a/src/utility.cpp +++ b/src/utility.cpp @@ -162,8 +162,8 @@ void mysrand(unsigned seed) camera_dir: an unit vector pointing to camera direction range: viewing range */ -bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range, - f32 *distance_ptr) +bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, + f32 camera_fov, f32 range, f32 *distance_ptr) { v3s16 blockpos_nodes = blockpos_b * MAP_BLOCKSIZE; @@ -211,8 +211,7 @@ bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range, cosangle += block_max_radius / dforward; // If block is not in the field of view, skip it - //if(cosangle < cos(FOV_ANGLE/2)) - if(cosangle < cos(FOV_ANGLE/2. * 4./3.)) + if(cosangle < cos(camera_fov / 2)) return false; } diff --git a/src/utility.h b/src/utility.h index ea7c1184..d331bafb 100644 --- a/src/utility.h +++ b/src/utility.h @@ -1765,8 +1765,8 @@ inline int myrand_range(int min, int max) Miscellaneous functions */ -bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range, - f32 *distance_ptr=NULL); +bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, + f32 camera_fov, f32 range, f32 *distance_ptr=NULL); /* Queue with unique values with fast checking of value existence From 18771a39cfdfcdd0bacca8f71ee5fd3fb78bbca6 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Thu, 8 Sep 2011 01:24:47 +0200 Subject: [PATCH 04/26] Commented out debug statements again --- src/camera.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/camera.cpp b/src/camera.cpp index 30df439e..9eb8f1a6 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -51,7 +51,7 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control): m_view_bobbing_anim(0), m_view_bobbing_anim_left(0) { - dstream<<__FUNCTION_NAME<addEmptySceneNode(smgr->getRootSceneNode()); m_cameranode = smgr->addCameraSceneNode(m_playernode); @@ -126,7 +126,7 @@ void Camera::updateViewingRange(f32 frametime_in) return; m_frametime_counter = 0.2; - dstream<<__FUNCTION_NAME + /*dstream<<__FUNCTION_NAME <<": Collected "< Date: Thu, 8 Sep 2011 13:03:55 +0200 Subject: [PATCH 05/26] Implemented view bobbing (testing simple lemniscate shape) --- src/camera.cpp | 87 +++++++++++++++++++++++++++++++++++++------------- src/camera.h | 13 ++++---- src/game.cpp | 2 +- 3 files changed, 72 insertions(+), 30 deletions(-) diff --git a/src/camera.cpp b/src/camera.cpp index 9eb8f1a6..16fad613 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -49,12 +49,15 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control): m_time_per_range(30. / 50), // a sane default of 30ms per 50 nodes of range m_view_bobbing_anim(0), - m_view_bobbing_anim_left(0) + m_view_bobbing_state(0) { //dstream<<__FUNCTION_NAME<addEmptySceneNode(smgr->getRootSceneNode()); - m_cameranode = smgr->addCameraSceneNode(m_playernode); + m_cameranode = smgr->addCameraSceneNode(smgr->getRootSceneNode()); + m_cameranode->bindTargetAndRotation(true); updateSettings(); } @@ -65,6 +68,21 @@ Camera::~Camera() void Camera::step(f32 dtime) { + if (m_view_bobbing_state != 0) + { + const f32 bobspeed = 0x1000000; + s32 offset = MYMAX(dtime * bobspeed, 1); + if (m_view_bobbing_state == 2) + { + // Animation is getting turned off + s32 subanim = (m_view_bobbing_anim & 0x7fffff); + if (subanim < 0x400000) + offset = -1 * MYMIN(offset, subanim); + else + offset = MYMIN(offset, 0x800000 - subanim); + } + m_view_bobbing_anim = (m_view_bobbing_anim + offset) & 0xffffff; + } } void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize) @@ -72,43 +90,66 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize) if (m_playernode == NULL || m_cameranode == NULL) return; + // Set player node transformation + m_playernode->setPosition(player->getPosition()); + //m_playernode->setRotation(v3f(player->getPitch(), -1 * player->getYaw(), 0)); + m_playernode->setRotation(v3f(0, -1 * player->getYaw(), 0)); + m_playernode->updateAbsolutePosition(); + + // Compute relative camera position and target + v3f relative_cam_pos = player->getEyePosition() - player->getPosition(); + v3f relative_cam_target = v3f(0,0,1); + relative_cam_target.rotateYZBy(player->getPitch()); + relative_cam_target += relative_cam_pos; + + f32 bobangle = m_view_bobbing_anim * 2 * M_PI / 0x1000000; + f32 bobangle_s = sin(bobangle); + f32 bobangle_c = cos(bobangle); + f32 bobwidth = 0.03 * cos(player->getPitch() * M_PI / 180) + / (bobangle_c * bobangle_c + 1); + f32 bobheight = bobwidth; + relative_cam_pos.X += bobwidth * bobangle_s; + relative_cam_pos.Y += bobheight * bobangle_s * bobangle_c; + + // Compute absolute camera position and target + m_playernode->getAbsoluteTransformation().transformVect(m_camera_position, relative_cam_pos); + m_playernode->getAbsoluteTransformation().transformVect(m_camera_direction, relative_cam_target); + m_camera_direction -= m_camera_position; + + // Set camera node transformation + m_cameranode->setPosition(m_camera_position); + // *100.0 helps in large map coordinates + m_cameranode->setTarget(m_camera_position + 100.0 * m_camera_direction); + // FOV and and aspect ratio m_aspect = (f32)screensize.X / (f32) screensize.Y; m_fov_x = 2 * atan(0.5 * m_aspect * tan(m_fov_y)); m_cameranode->setAspectRatio(m_aspect); m_cameranode->setFOV(m_fov_y); - // Just so big a value that everything rendered is visible // Some more allowance that m_viewing_range_max * BS because of active objects etc. m_cameranode->setFarValue(m_viewing_range_max * BS * 10); - m_camera_position = player->getEyePosition(); // TODO bobbing - m_cameranode->setPosition(m_camera_position); - - m_camera_direction = v3f(0,0,1); - m_camera_direction.rotateYZBy(player->getPitch()); - m_camera_direction.rotateXZBy(player->getYaw()); - // *100.0 helps in large map coordinates - m_cameranode->setTarget(m_camera_position + m_camera_direction * 100.0); - // Render distance feedback loop updateViewingRange(frametime); - // Check if view bobbing is active + // If the player seems to be walking on solid ground, + // view bobbing is enabled and free_move is off, + // start (or continue) the view bobbing animation. v3f speed = player->getSpeed(); - f32 epsilon = BS / 1000.0; - if (speed.X * speed.X + speed.Z * speed.Z > epsilon*epsilon && - speed.Y < epsilon && - g_settings.getBool("view_bobbing") == true && - g_settings.getBool("free_move") == false) + //dstream<<"speed: ("< BS) && + (fabs(speed.Y) < BS/10) && + (g_settings.getBool("view_bobbing") == true) && + (g_settings.getBool("free_move") == false)) { - // The player seems to be walking on solid ground. - // Enable view bobbing. - //dstream << "View bobbing active" << std::endl; + // Start animation + m_view_bobbing_state = 1; } - else + else if (m_view_bobbing_state == 1) { - //dstream << "View bobbing inactive" << std::endl; + // Stop animation + m_view_bobbing_state = 2; } } diff --git a/src/camera.h b/src/camera.h index 88f03e66..500168f3 100644 --- a/src/camera.h +++ b/src/camera.h @@ -38,7 +38,7 @@ class Camera // Get player scene node. // This node is positioned at the player's torso (without any view bobbing), - // as given by Player::m_position, Player::m_pitch and Player::m_yaw. + // as given by Player::m_position. Yaw is applied but not pitch. // Things like wielded tools should be positioned relative to this node. inline scene::ISceneNode* getPlayerNode() const { @@ -46,7 +46,6 @@ class Camera } // Get camera scene node. - // The camera node is a child of the player node. // It has the eye transformation and view bobbing applied. inline scene::ICameraSceneNode* getCameraNode() const { @@ -131,10 +130,12 @@ class Camera f32 m_frametime_counter; f32 m_time_per_range; - // View bobbing animation frame (0 <= m_view_bobbing < 0x10000) - u32 m_view_bobbing_anim; - // Number of frames to continue the view bobbing animation. - u32 m_view_bobbing_anim_left; + // View bobbing animation frame (0 <= m_view_bobbing < 0x1000000) + s32 m_view_bobbing_anim; + // If 0, view bobbing is off (e.g. player is standing). + // If 1, view bobbing is on (player is walking). + // If 2, view bobbing is getting switched off. + s32 m_view_bobbing_state; }; #endif diff --git a/src/game.cpp b/src/game.cpp index fc1486b7..24f356e4 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1477,7 +1477,7 @@ void the_game( if(FIELD_OF_VIEW_TEST) { - client.updateCamera(v3f(0,0,0), v3f(0,0,1), M_PI); + client.updateCamera(v3f(0,0,0), v3f(0,0,1), camera_fov); } else { From 0931d4b7ff95dc9b51bee28851c3780b2648ffd0 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Thu, 8 Sep 2011 13:14:59 +0200 Subject: [PATCH 06/26] make it slightly less annoying :o) --- src/camera.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/camera.cpp b/src/camera.cpp index 16fad613..bdfbc88c 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -105,7 +105,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize) f32 bobangle = m_view_bobbing_anim * 2 * M_PI / 0x1000000; f32 bobangle_s = sin(bobangle); f32 bobangle_c = cos(bobangle); - f32 bobwidth = 0.03 * cos(player->getPitch() * M_PI / 180) + f32 bobwidth = 0.02 * cos(player->getPitch() * M_PI / 180) / (bobangle_c * bobangle_c + 1); f32 bobheight = bobwidth; relative_cam_pos.X += bobwidth * bobangle_s; From f2ec2265216f4621558003dcbd8974f76063576b Mon Sep 17 00:00:00 2001 From: Kahrl Date: Thu, 8 Sep 2011 13:34:28 +0200 Subject: [PATCH 07/26] minor view bobbing improvements --- src/camera.cpp | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/src/camera.cpp b/src/camera.cpp index bdfbc88c..7c3dfda3 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -25,6 +25,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "utility.h" #include +const s32 BOBFRAMES = 0x1000000; // must be a power of two + Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control): m_smgr(smgr), m_playernode(NULL), @@ -70,18 +72,17 @@ void Camera::step(f32 dtime) { if (m_view_bobbing_state != 0) { - const f32 bobspeed = 0x1000000; - s32 offset = MYMAX(dtime * bobspeed, 1); + s32 offset = MYMAX(dtime * BOBFRAMES, 1); if (m_view_bobbing_state == 2) { // Animation is getting turned off - s32 subanim = (m_view_bobbing_anim & 0x7fffff); - if (subanim < 0x400000) + s32 subanim = (m_view_bobbing_anim & (BOBFRAMES/2-1)); + if (subanim < BOBFRAMES/4) offset = -1 * MYMIN(offset, subanim); else - offset = MYMIN(offset, 0x800000 - subanim); + offset = MYMIN(offset, BOBFRAMES/2 - subanim); } - m_view_bobbing_anim = (m_view_bobbing_anim + offset) & 0xffffff; + m_view_bobbing_anim = (m_view_bobbing_anim + offset) & (BOBFRAMES-1); } } @@ -102,14 +103,20 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize) relative_cam_target.rotateYZBy(player->getPitch()); relative_cam_target += relative_cam_pos; - f32 bobangle = m_view_bobbing_anim * 2 * M_PI / 0x1000000; - f32 bobangle_s = sin(bobangle); - f32 bobangle_c = cos(bobangle); - f32 bobwidth = 0.02 * cos(player->getPitch() * M_PI / 180) - / (bobangle_c * bobangle_c + 1); - f32 bobheight = bobwidth; - relative_cam_pos.X += bobwidth * bobangle_s; - relative_cam_pos.Y += bobheight * bobangle_s * bobangle_c; + if ((m_view_bobbing_anim & (BOBFRAMES/2-1)) != 0) + { + f32 bobamount = cos(player->getPitch() * M_PI / 180); + bobamount = 2 * MYMIN(bobamount, 0.5); + + f32 bobangle = m_view_bobbing_anim * 2 * M_PI / BOBFRAMES; + f32 bobangle_s = sin(bobangle); + f32 bobangle_c = cos(bobangle); + f32 bobwidth = 0.02 * bobamount / (bobangle_c * bobangle_c + 1); + f32 bobheight = 1.5 * bobwidth; + + relative_cam_pos.X += bobwidth * bobangle_s; + relative_cam_pos.Y += bobheight * bobangle_s * bobangle_c; + } // Compute absolute camera position and target m_playernode->getAbsoluteTransformation().transformVect(m_camera_position, relative_cam_pos); From e4cb0044602f2dc5eb92c8955797b628c158a0d9 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Thu, 8 Sep 2011 16:10:44 +0200 Subject: [PATCH 08/26] trying something else... also replaced M_PI by PI everywhere --- src/camera.cpp | 6 +++--- src/game.cpp | 9 +++++---- src/map.cpp | 2 +- src/server.cpp | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/camera.cpp b/src/camera.cpp index 7c3dfda3..8dc1af02 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -105,10 +105,10 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize) if ((m_view_bobbing_anim & (BOBFRAMES/2-1)) != 0) { - f32 bobamount = cos(player->getPitch() * M_PI / 180); + f32 bobamount = cos(player->getPitch() * PI / 180); bobamount = 2 * MYMIN(bobamount, 0.5); - f32 bobangle = m_view_bobbing_anim * 2 * M_PI / BOBFRAMES; + f32 bobangle = m_view_bobbing_anim * 2 * PI / BOBFRAMES; f32 bobangle_s = sin(bobangle); f32 bobangle_c = cos(bobangle); f32 bobwidth = 0.02 * bobamount / (bobangle_c * bobangle_c + 1); @@ -282,7 +282,7 @@ void Camera::updateSettings() f32 fov_degrees = g_settings.getFloat("fov"); fov_degrees = MYMAX(fov_degrees, 10.0); fov_degrees = MYMIN(fov_degrees, 170.0); - m_fov_y = fov_degrees * M_PI / 180.0; + m_fov_y = fov_degrees * PI / 180.0; f32 wanted_fps = g_settings.getFloat("wanted_fps"); wanted_fps = MYMAX(wanted_fps, 1.0); diff --git a/src/game.cpp b/src/game.cpp index af488613..cb7594c3 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -831,7 +831,7 @@ void the_game( Tool */ - v3f tool_wield_position(0.06*BS, 1.619*BS, 0.1*BS); + v3f tool_wield_position(0.06*BS, -0.06*BS, 0.1*BS); v3f tool_wield_rotation(-25, 180, -25); float tool_wield_animation = 0.0; scene::IMeshSceneNode *tool_wield; @@ -856,7 +856,7 @@ void the_game( mesh->addMeshBuffer(buf); buf->drop(); - tool_wield = smgr->addMeshSceneNode(mesh, camera.getPlayerNode()); + tool_wield = smgr->addMeshSceneNode(mesh, camera.getCameraNode()); mesh->drop(); } tool_wield->setVisible(false); @@ -1997,8 +1997,9 @@ void the_game( Animate tool */ { - tool_wield->setRotation(tool_wield_rotation - sin(tool_wield_animation * PI) * 40.0); - tool_wield->setPosition(tool_wield_position - sin(tool_wield_animation * PI) / 3.0); + f32 tool_wield_sin = sin(tool_wield_animation * PI); + tool_wield->setRotation(tool_wield_rotation - tool_wield_sin * 40.0); + tool_wield->setPosition(tool_wield_position - tool_wield_sin * BS / 30.0); } diff --git a/src/map.cpp b/src/map.cpp index b1908fe2..ecd12bdd 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -3605,7 +3605,7 @@ ClientMap::ClientMap( m_control(control), m_camera_position(0,0,0), m_camera_direction(0,0,1), - m_camera_fov(M_PI) + m_camera_fov(PI) { m_camera_mutex.Init(); assert(m_camera_mutex.IsInitialized()); diff --git a/src/server.cpp b/src/server.cpp index fd93d752..c89e4113 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -584,7 +584,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, Don't generate or send if not in sight */ - if(isBlockInSight(p, camera_pos, camera_dir, M_PI, 10000*BS) == false) + if(isBlockInSight(p, camera_pos, camera_dir, PI, 10000*BS) == false) { continue; } From 524cf237b8ccbd233c57feb23a9e06f7ba8ff521 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Thu, 8 Sep 2011 17:45:39 +0200 Subject: [PATCH 09/26] inventory displays tool breakage bar again --- src/inventory.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/inventory.h b/src/inventory.h index f70d69b6..ef8c499b 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -403,8 +403,6 @@ class ToolItem : public InventoryItem std::string basename = getBasename(); - return g_texturesource->getTextureRaw(basename); - /* Calculate a progress value with sane amount of maximum states From fc92da432401051a8cc17618941625aec6b12d20 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Thu, 8 Sep 2011 23:31:48 +0200 Subject: [PATCH 10/26] View bobbing is slower in the water. --- src/camera.cpp | 13 +++++++------ src/camera.h | 2 ++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/camera.cpp b/src/camera.cpp index 8dc1af02..a84ee953 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -19,10 +19,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "camera.h" #include "debug.h" +#include "client.h" #include "main.h" // for g_settings #include "map.h" #include "player.h" -#include "utility.h" #include const s32 BOBFRAMES = 0x1000000; // must be a power of two @@ -51,7 +51,8 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control): m_time_per_range(30. / 50), // a sane default of 30ms per 50 nodes of range m_view_bobbing_anim(0), - m_view_bobbing_state(0) + m_view_bobbing_state(0), + m_view_bobbing_slow(false) { //dstream<<__FUNCTION_NAME<setPosition(player->getPosition()); - //m_playernode->setRotation(v3f(player->getPitch(), -1 * player->getYaw(), 0)); m_playernode->setRotation(v3f(0, -1 * player->getYaw(), 0)); m_playernode->updateAbsolutePosition(); @@ -144,9 +145,8 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize) // view bobbing is enabled and free_move is off, // start (or continue) the view bobbing animation. v3f speed = player->getSpeed(); - //dstream<<"speed: ("< BS) && - (fabs(speed.Y) < BS/10) && + (player->touching_ground) && (g_settings.getBool("view_bobbing") == true) && (g_settings.getBool("free_move") == false)) { @@ -158,6 +158,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize) // Stop animation m_view_bobbing_state = 2; } + m_view_bobbing_slow = player->in_water_stable; } void Camera::updateViewingRange(f32 frametime_in) diff --git a/src/camera.h b/src/camera.h index 500168f3..ba5d72bf 100644 --- a/src/camera.h +++ b/src/camera.h @@ -136,6 +136,8 @@ class Camera // If 1, view bobbing is on (player is walking). // If 2, view bobbing is getting switched off. s32 m_view_bobbing_state; + // If true, view bobbing is slown down (player is swimming) + bool m_view_bobbing_slow; }; #endif From 63266928a5e2b6f4b712695eb56cb1de3899ba21 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Thu, 15 Sep 2011 00:32:11 +0200 Subject: [PATCH 11/26] Made wielded tool move slightly (and smoothly) during view bobbing. Making the tool be a child node of an empty scene node instead of the camera scene node seemingly fixed the uncontrollable tool jitter, too. --- src/camera.cpp | 33 ++++++++++++++++++++++++++++----- src/camera.h | 15 +++++++++++++-- src/game.cpp | 12 ++---------- 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/src/camera.cpp b/src/camera.cpp index a84ee953..2cc27fd6 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -30,6 +30,7 @@ const s32 BOBFRAMES = 0x1000000; // must be a power of two Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control): m_smgr(smgr), m_playernode(NULL), + m_headnode(NULL), m_cameranode(NULL), m_draw_control(draw_control), m_viewing_range_min(5.0), @@ -59,6 +60,7 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control): // note: making the camera node a child of the player node // would lead to unexpected behaviour, so we don't do that. m_playernode = smgr->addEmptySceneNode(smgr->getRootSceneNode()); + m_headnode = smgr->addEmptySceneNode(m_playernode); m_cameranode = smgr->addCameraSceneNode(smgr->getRootSceneNode()); m_cameranode->bindTargetAndRotation(true); @@ -69,6 +71,26 @@ Camera::~Camera() { } +bool Camera::successfullyCreated(std::wstring& error_message) +{ + if (m_playernode == NULL) + { + error_message = L"Failed to create the player scene node"; + return false; + } + if (m_headnode == NULL) + { + error_message = L"Failed to create the head scene node"; + return false; + } + if (m_cameranode == NULL) + { + error_message = L"Failed to create the camera scene node"; + return false; + } + return true; +} + void Camera::step(f32 dtime) { if (m_view_bobbing_state != 0) @@ -90,16 +112,18 @@ void Camera::step(f32 dtime) void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize) { - if (m_playernode == NULL || m_cameranode == NULL) - return; - // Set player node transformation m_playernode->setPosition(player->getPosition()); m_playernode->setRotation(v3f(0, -1 * player->getYaw(), 0)); m_playernode->updateAbsolutePosition(); + // Set head node transformation + v3f eye_offset = player->getEyePosition() - player->getPosition(); + m_headnode->setPosition(eye_offset); + m_headnode->setRotation(v3f(player->getPitch(), 0, 0)); + // Compute relative camera position and target - v3f relative_cam_pos = player->getEyePosition() - player->getPosition(); + v3f relative_cam_pos = eye_offset; v3f relative_cam_target = v3f(0,0,1); relative_cam_target.rotateYZBy(player->getPitch()); relative_cam_target += relative_cam_pos; @@ -128,7 +152,6 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize) m_cameranode->setPosition(m_camera_position); // *100.0 helps in large map coordinates m_cameranode->setTarget(m_camera_position + 100.0 * m_camera_direction); - // FOV and and aspect ratio m_aspect = (f32)screensize.X / (f32) screensize.Y; m_fov_x = 2 * atan(0.5 * m_aspect * tan(m_fov_y)); diff --git a/src/camera.h b/src/camera.h index ba5d72bf..a6dd7476 100644 --- a/src/camera.h +++ b/src/camera.h @@ -39,14 +39,21 @@ class Camera // Get player scene node. // This node is positioned at the player's torso (without any view bobbing), // as given by Player::m_position. Yaw is applied but not pitch. - // Things like wielded tools should be positioned relative to this node. inline scene::ISceneNode* getPlayerNode() const { return m_playernode; } + // Get head scene node. + // It has the eye transformation and pitch applied, + // but no view bobbing. + inline scene::ISceneNode* getHeadNode() const + { + return m_headnode; + } + // Get camera scene node. - // It has the eye transformation and view bobbing applied. + // It has the eye transformation, pitch and view bobbing applied. inline scene::ICameraSceneNode* getCameraNode() const { return m_cameranode; @@ -84,6 +91,9 @@ class Camera return MYMAX(m_fov_x, m_fov_y); } + // Checks if the constructor was able to create the scene nodes + bool successfullyCreated(std::wstring& error_message); + // Step the camera: updates the viewing range and view bobbing. void step(f32 dtime); @@ -101,6 +111,7 @@ class Camera // Scene manager and nodes scene::ISceneManager* m_smgr; scene::ISceneNode* m_playernode; + scene::ISceneNode* m_headnode; scene::ICameraSceneNode* m_cameranode; // draw control diff --git a/src/game.cpp b/src/game.cpp index cb7594c3..a712323b 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -813,16 +813,8 @@ void the_game( Create the camera node */ Camera camera(smgr, draw_control); - if (camera.getPlayerNode() == NULL) - { - error_message = L"Failed to create the player node"; + if (!camera.successfullyCreated(error_message)) return; - } - if (camera.getCameraNode() == NULL) - { - error_message = L"Failed to create the camera node"; - return; - } f32 camera_yaw = 0; // "right/left" f32 camera_pitch = 0; // "up/down" @@ -856,7 +848,7 @@ void the_game( mesh->addMeshBuffer(buf); buf->drop(); - tool_wield = smgr->addMeshSceneNode(mesh, camera.getCameraNode()); + tool_wield = smgr->addMeshSceneNode(mesh, camera.getHeadNode()); mesh->drop(); } tool_wield->setVisible(false); From acfb2bb8bced286626fa1fc04d56c9ba9ff82d48 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Fri, 16 Sep 2011 18:03:58 +0200 Subject: [PATCH 12/26] Revert some changes that could lead to slower map transfer and increaed network load. --- src/server.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/server.cpp b/src/server.cpp index c89e4113..46993913 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -582,9 +582,12 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, /* Don't generate or send if not in sight + FIXME This only works if the client uses a small enough + FOV setting. The default of 72 degrees is fine. */ - if(isBlockInSight(p, camera_pos, camera_dir, PI, 10000*BS) == false) + float camera_fov = (72.0*PI/180) * 4./3.; + if(isBlockInSight(p, camera_pos, camera_dir, camera_fov, 10000*BS) == false) { continue; } From ae66d611f2020e0fddb45f40af2d42c13e7ba585 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Sun, 18 Sep 2011 02:17:39 +0200 Subject: [PATCH 13/26] This looks more like MC view bobbing, but still not even close --- src/camera.cpp | 50 ++++++++++++++++++++++++++++---------------------- src/camera.h | 4 ++-- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/src/camera.cpp b/src/camera.cpp index 2cc27fd6..0c6fe1df 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -53,7 +53,7 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control): m_view_bobbing_anim(0), m_view_bobbing_state(0), - m_view_bobbing_slow(false) + m_view_bobbing_speed(0) { //dstream<<__FUNCTION_NAME<setRotation(v3f(player->getPitch(), 0, 0)); // Compute relative camera position and target - v3f relative_cam_pos = eye_offset; - v3f relative_cam_target = v3f(0,0,1); - relative_cam_target.rotateYZBy(player->getPitch()); - relative_cam_target += relative_cam_pos; + v3f rel_cam_pos = v3f(0,0,0); + v3f rel_cam_target = v3f(0,0,1); - if ((m_view_bobbing_anim & (BOBFRAMES/2-1)) != 0) + s32 bobframe = m_view_bobbing_anim & (BOBFRAMES/2-1); + if (bobframe != 0) { - f32 bobamount = cos(player->getPitch() * PI / 180); - bobamount = 2 * MYMIN(bobamount, 0.5); + f32 bobfrac = (f32) bobframe / (BOBFRAMES/2); + f32 bobdir = (m_view_bobbing_anim < (BOBFRAMES/2)) ? 1.0 : -1.0; - f32 bobangle = m_view_bobbing_anim * 2 * PI / BOBFRAMES; - f32 bobangle_s = sin(bobangle); - f32 bobangle_c = cos(bobangle); - f32 bobwidth = 0.02 * bobamount / (bobangle_c * bobangle_c + 1); - f32 bobheight = 1.5 * bobwidth; + f32 bobknob = 1.2; + f32 bobtmp = sin(pow(bobfrac, bobknob) * PI); - relative_cam_pos.X += bobwidth * bobangle_s; - relative_cam_pos.Y += bobheight * bobangle_s * bobangle_c; + v3f bobvec = v3f( + 0.01 * bobdir * sin(bobfrac * PI), + 0.005 * bobtmp * bobtmp, + 0.); + + rel_cam_pos += bobvec * 3.; + rel_cam_target += bobvec * 1.5; } // Compute absolute camera position and target - m_playernode->getAbsoluteTransformation().transformVect(m_camera_position, relative_cam_pos); - m_playernode->getAbsoluteTransformation().transformVect(m_camera_direction, relative_cam_target); + m_headnode->getAbsoluteTransformation().transformVect(m_camera_position, rel_cam_pos); + m_headnode->getAbsoluteTransformation().transformVect(m_camera_direction, rel_cam_target); m_camera_direction -= m_camera_position; // Set camera node transformation m_cameranode->setPosition(m_camera_position); - // *100.0 helps in large map coordinates - m_cameranode->setTarget(m_camera_position + 100.0 * m_camera_direction); + m_cameranode->setTarget(m_camera_position + m_camera_direction); + // FOV and and aspect ratio m_aspect = (f32)screensize.X / (f32) screensize.Y; m_fov_x = 2 * atan(0.5 * m_aspect * tan(m_fov_y)); @@ -175,13 +175,19 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize) { // Start animation m_view_bobbing_state = 1; + m_view_bobbing_speed = MYMIN(speed.getLength(), 40); } else if (m_view_bobbing_state == 1) { // Stop animation m_view_bobbing_state = 2; + m_view_bobbing_speed = 100; + } + else if (m_view_bobbing_state == 2 && bobframe == 0) + { + // Stop animation completed + m_view_bobbing_state = 0; } - m_view_bobbing_slow = player->in_water_stable; } void Camera::updateViewingRange(f32 frametime_in) diff --git a/src/camera.h b/src/camera.h index a6dd7476..dd9f3055 100644 --- a/src/camera.h +++ b/src/camera.h @@ -147,8 +147,8 @@ class Camera // If 1, view bobbing is on (player is walking). // If 2, view bobbing is getting switched off. s32 m_view_bobbing_state; - // If true, view bobbing is slown down (player is swimming) - bool m_view_bobbing_slow; + // Speed of view bobbing animation + f32 m_view_bobbing_speed; }; #endif From 54f3796f9105cb220c95aa6c2e80516cdd4e4a00 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Sun, 18 Sep 2011 02:24:43 +0200 Subject: [PATCH 14/26] Oops, up vector is needed. --- src/camera.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/camera.cpp b/src/camera.cpp index 0c6fe1df..a9497152 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -120,10 +120,12 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize) v3f eye_offset = player->getEyePosition() - player->getPosition(); m_headnode->setPosition(eye_offset); m_headnode->setRotation(v3f(player->getPitch(), 0, 0)); + m_headnode->updateAbsolutePosition(); // Compute relative camera position and target v3f rel_cam_pos = v3f(0,0,0); v3f rel_cam_target = v3f(0,0,1); + v3f rel_cam_up = v3f(0,1,0); s32 bobframe = m_view_bobbing_anim & (BOBFRAMES/2-1); if (bobframe != 0) @@ -140,7 +142,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize) 0.); rel_cam_pos += bobvec * 3.; - rel_cam_target += bobvec * 1.5; + rel_cam_target += bobvec * 4.5; } // Compute absolute camera position and target @@ -148,8 +150,13 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize) m_headnode->getAbsoluteTransformation().transformVect(m_camera_direction, rel_cam_target); m_camera_direction -= m_camera_position; + v3f abs_cam_up; + m_headnode->getAbsoluteTransformation().transformVect(abs_cam_up, rel_cam_pos + rel_cam_up); + abs_cam_up -= m_camera_position; + // Set camera node transformation m_cameranode->setPosition(m_camera_position); + m_cameranode->setUpVector(abs_cam_up); m_cameranode->setTarget(m_camera_position + m_camera_direction); // FOV and and aspect ratio From 4ed837bcfa2d9601c6b5c3d2e8d37ad9f5a6e2a6 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Sun, 18 Sep 2011 17:02:30 +0200 Subject: [PATCH 15/26] trying some view bobbing changes --- src/camera.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/camera.cpp b/src/camera.cpp index a9497152..43009bd7 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -133,16 +133,31 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize) f32 bobfrac = (f32) bobframe / (BOBFRAMES/2); f32 bobdir = (m_view_bobbing_anim < (BOBFRAMES/2)) ? 1.0 : -1.0; + #if 1 f32 bobknob = 1.2; f32 bobtmp = sin(pow(bobfrac, bobknob) * PI); v3f bobvec = v3f( - 0.01 * bobdir * sin(bobfrac * PI), - 0.005 * bobtmp * bobtmp, + bobdir * sin(bobfrac * PI), + 0.8 * bobtmp * bobtmp, 0.); - rel_cam_pos += bobvec * 3.; - rel_cam_target += bobvec * 4.5; + rel_cam_pos += 0.03 * bobvec; + rel_cam_target += 0.045 * bobvec; + rel_cam_up.rotateXYBy(0.03 * bobdir * bobtmp * PI); + #else + f32 angle_deg = 1 * bobdir * sin(bobfrac * PI); + f32 angle_rad = angle_deg * PI / 180; + f32 r = 0.05; + v3f off = v3f( + r * sin(angle_rad), + r * (cos(angle_rad) - 1), + 0); + rel_cam_pos += off; + //rel_cam_target += off; + rel_cam_up.rotateXYBy(angle_deg); + #endif + } // Compute absolute camera position and target From 36bcbca9acabbc47976d3d7625ffb1c9396b8fdc Mon Sep 17 00:00:00 2001 From: Kahrl Date: Mon, 19 Sep 2011 03:01:11 +0200 Subject: [PATCH 16/26] Added sprite extruder --- src/camera.cpp | 349 ++++++++++++++++++++++++++++++++++++++++++++++++ src/camera.h | 66 ++++++++- src/client.cpp | 8 -- src/client.h | 1 - src/game.cpp | 70 ++-------- src/inventory.h | 11 -- src/player.cpp | 19 --- src/player.h | 4 - 8 files changed, 425 insertions(+), 103 deletions(-) diff --git a/src/camera.cpp b/src/camera.cpp index 43009bd7..aae36c51 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -63,6 +63,8 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control): m_headnode = smgr->addEmptySceneNode(m_playernode); m_cameranode = smgr->addCameraSceneNode(smgr->getRootSceneNode()); m_cameranode->bindTargetAndRotation(true); + m_wieldnode = new ExtrudedSpriteSceneNode(smgr->getRootSceneNode(), smgr, -1, v3f(0, 120, 10), v3f(0, 0, 0), v3f(100, 100, 100)); + //m_wieldnode = new ExtrudedSpriteSceneNode(smgr->getRootSceneNode(), smgr, -1); updateSettings(); } @@ -341,3 +343,350 @@ void Camera::updateSettings() m_wanted_frametime = 1.0 / wanted_fps; } +void Camera::wield(InventoryItem* item) +{ + if (item != NULL) + { + dstream << "wield item: " << item->getName() << std::endl; + m_wieldnode->setSprite(item->getImageRaw()); + m_wieldnode->setVisible(true); + } + else + { + dstream << "wield item: none" << std::endl; + m_wieldnode->setVisible(false); + } +} + +void Camera::setDigging(bool digging) +{ + // TODO +} + + +ExtrudedSpriteSceneNode::ExtrudedSpriteSceneNode( + scene::ISceneNode* parent, + scene::ISceneManager* mgr, + s32 id, + const v3f& position, + const v3f& rotation, + const v3f& scale +): + ISceneNode(parent, mgr, id, position, rotation, scale) +{ + m_meshnode = mgr->addMeshSceneNode(NULL, this, -1, v3f(0,0,0), v3f(0,0,0), v3f(1,1,1), true); + m_thickness = 0.1; + m_cubemesh = NULL; + m_is_cube = false; +} + +ExtrudedSpriteSceneNode::~ExtrudedSpriteSceneNode() +{ + removeChild(m_meshnode); + if (m_cubemesh) + m_cubemesh->drop(); +} + +void ExtrudedSpriteSceneNode::setSprite(video::ITexture* texture) +{ + if (texture == NULL) + { + m_meshnode->setVisible(false); + return; + } + + io::path name = getExtrudedName(texture); + scene::IMeshCache* cache = SceneManager->getMeshCache(); + scene::IAnimatedMesh* mesh = cache->getMeshByName(name); + if (mesh != NULL) + { + // Extruded texture has been found in cache. + m_meshnode->setMesh(mesh); + } + else + { + // Texture was not yet extruded, do it now and save in cache + mesh = extrude(texture); + if (mesh == NULL) + { + dstream << "Warning: failed to extrude sprite" << std::endl; + m_meshnode->setVisible(false); + return; + } + cache->addMesh(name, mesh); + m_meshnode->setMesh(mesh); + mesh->drop(); + } + + m_meshnode->setScale(v3f(1, 1, m_thickness)); + m_meshnode->getMaterial(0).setTexture(0, texture); + m_meshnode->getMaterial(0).setFlag(video::EMF_LIGHTING, false); + m_meshnode->getMaterial(0).setFlag(video::EMF_BILINEAR_FILTER, false); + m_meshnode->getMaterial(0).MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; + m_meshnode->setVisible(true); + m_is_cube = false; +} + +void ExtrudedSpriteSceneNode::setCube(video::ITexture* texture) +{ + if (texture == NULL) + { + m_meshnode->setVisible(false); + return; + } + + if (m_cubemesh == NULL) + m_cubemesh = SceneManager->getGeometryCreator()->createCubeMesh(v3f(1)); + + m_meshnode->setMesh(m_cubemesh); + m_meshnode->setScale(v3f(1)); + m_meshnode->getMaterial(0).setTexture(0, texture); + m_meshnode->getMaterial(0).setFlag(video::EMF_LIGHTING, false); + m_meshnode->getMaterial(0).setFlag(video::EMF_BILINEAR_FILTER, false); + m_meshnode->getMaterial(0).MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; + m_meshnode->setVisible(true); + m_is_cube = true; +} + +void ExtrudedSpriteSceneNode::removeSpriteFromCache(video::ITexture* texture) +{ + scene::IMeshCache* cache = SceneManager->getMeshCache(); + scene::IAnimatedMesh* mesh = cache->getMeshByName(getExtrudedName(texture)); + if (mesh != NULL) + cache->removeMesh(mesh); +} + +void ExtrudedSpriteSceneNode::setSpriteThickness(f32 thickness) +{ + m_thickness = thickness; + if (!m_is_cube) + m_meshnode->setScale(v3f(1, 1, thickness)); +} + +const core::aabbox3d& ExtrudedSpriteSceneNode::getBoundingBox() const +{ + return m_meshnode->getBoundingBox(); +} + +void ExtrudedSpriteSceneNode::OnRegisterSceneNode() +{ + if (IsVisible) + SceneManager->registerNodeForRendering(this); + ISceneNode::OnRegisterSceneNode(); +} + +void ExtrudedSpriteSceneNode::render() +{ + // do nothing +} + +io::path ExtrudedSpriteSceneNode::getExtrudedName(video::ITexture* texture) +{ + io::path path = texture->getName(); + path.append("/[extruded]"); + return path; +} + +scene::IAnimatedMesh* ExtrudedSpriteSceneNode::extrudeARGB(u32 width, u32 height, u8* data) +{ + const s32 argb_wstep = 4 * width; + const s32 alpha_threshold = 1; + + scene::IMeshBuffer* buf = new scene::SMeshBuffer(); + video::SColor c(255,255,255,255); + + // Front and back + { + video::S3DVertex vertices[8] = + { + video::S3DVertex(-0.5,-0.5,-0.5, 0,0,-1, c, 0,1), + video::S3DVertex(-0.5,0.5,-0.5, 0,0,-1, c, 0,0), + video::S3DVertex(0.5,0.5,-0.5, 0,0,-1, c, 1,0), + video::S3DVertex(0.5,-0.5,-0.5, 0,0,-1, c, 1,1), + video::S3DVertex(0.5,-0.5,0.5, 0,0,1, c, 1,1), + video::S3DVertex(0.5,0.5,0.5, 0,0,1, c, 1,0), + video::S3DVertex(-0.5,0.5,0.5, 0,0,1, c, 0,0), + video::S3DVertex(-0.5,-0.5,0.5, 0,0,1, c, 0,1), + }; + u16 indices[12] = {0,1,2,2,3,0,4,5,6,6,7,4}; + buf->append(vertices, 8, indices, 12); + } + + // "Interior" + // (add faces where a solid pixel is next to a transparent one) + u8* solidity = new u8[(width+2) * (height+2)]; + u32 wstep = width + 2; + for (u32 y = 0; y < height + 2; ++y) + { + u8* scanline = solidity + y * wstep; + if (y == 0 || y == height + 1) + { + for (u32 x = 0; x < width + 2; ++x) + scanline[x] = 0; + } + else + { + scanline[0] = 0; + u8* argb_scanline = data + (y - 1) * argb_wstep; + for (u32 x = 0; x < width; ++x) + scanline[x+1] = (argb_scanline[x*4+3] >= alpha_threshold); + scanline[width + 1] = 0; + } + } + + // without this, there would be occasional "holes" in the mesh + f32 eps = 0.01; + + for (u32 y = 0; y <= height; ++y) + { + u8* scanline = solidity + y * wstep + 1; + for (u32 x = 0; x <= width; ++x) + { + if (scanline[x] && !scanline[x + wstep]) + { + u32 xx = x + 1; + while (scanline[xx] && !scanline[xx + wstep]) + ++xx; + f32 vx1 = (x - eps) / (f32) width - 0.5; + f32 vx2 = (xx + eps) / (f32) width - 0.5; + f32 vy = 0.5 - (y - eps) / (f32) height; + f32 tx1 = x / (f32) width; + f32 tx2 = xx / (f32) width; + f32 ty = (y - 0.5) / (f32) height; + video::S3DVertex vertices[8] = + { + video::S3DVertex(vx1,vy,-0.5, 0,-1,0, c, tx1,ty), + video::S3DVertex(vx2,vy,-0.5, 0,-1,0, c, tx2,ty), + video::S3DVertex(vx2,vy,0.5, 0,-1,0, c, tx2,ty), + video::S3DVertex(vx1,vy,0.5, 0,-1,0, c, tx1,ty), + }; + u16 indices[6] = {0,1,2,2,3,0}; + buf->append(vertices, 4, indices, 6); + x = xx - 1; + } + if (!scanline[x] && scanline[x + wstep]) + { + u32 xx = x + 1; + while (!scanline[xx] && scanline[xx + wstep]) + ++xx; + f32 vx1 = (x - eps) / (f32) width - 0.5; + f32 vx2 = (xx + eps) / (f32) width - 0.5; + f32 vy = 0.5 - (y + eps) / (f32) height; + f32 tx1 = x / (f32) width; + f32 tx2 = xx / (f32) width; + f32 ty = (y + 0.5) / (f32) height; + video::S3DVertex vertices[8] = + { + video::S3DVertex(vx1,vy,-0.5, 0,1,0, c, tx1,ty), + video::S3DVertex(vx1,vy,0.5, 0,1,0, c, tx1,ty), + video::S3DVertex(vx2,vy,0.5, 0,1,0, c, tx2,ty), + video::S3DVertex(vx2,vy,-0.5, 0,1,0, c, tx2,ty), + }; + u16 indices[6] = {0,1,2,2,3,0}; + buf->append(vertices, 4, indices, 6); + x = xx - 1; + } + } + } + + for (u32 x = 0; x <= width; ++x) + { + u8* scancol = solidity + x + wstep; + for (u32 y = 0; y <= height; ++y) + { + if (scancol[y * wstep] && !scancol[y * wstep + 1]) + { + u32 yy = y + 1; + while (scancol[yy * wstep] && !scancol[yy * wstep + 1]) + ++yy; + f32 vx = (x - eps) / (f32) width - 0.5; + f32 vy1 = 0.5 - (y - eps) / (f32) height; + f32 vy2 = 0.5 - (yy + eps) / (f32) height; + f32 tx = (x - 0.5) / (f32) width; + f32 ty1 = y / (f32) height; + f32 ty2 = yy / (f32) height; + video::S3DVertex vertices[8] = + { + video::S3DVertex(vx,vy1,-0.5, 1,0,0, c, tx,ty1), + video::S3DVertex(vx,vy1,0.5, 1,0,0, c, tx,ty1), + video::S3DVertex(vx,vy2,0.5, 1,0,0, c, tx,ty2), + video::S3DVertex(vx,vy2,-0.5, 1,0,0, c, tx,ty2), + }; + u16 indices[6] = {0,1,2,2,3,0}; + buf->append(vertices, 4, indices, 6); + y = yy - 1; + } + if (!scancol[y * wstep] && scancol[y * wstep + 1]) + { + u32 yy = y + 1; + while (!scancol[yy * wstep] && scancol[yy * wstep + 1]) + ++yy; + f32 vx = (x + eps) / (f32) width - 0.5; + f32 vy1 = 0.5 - (y - eps) / (f32) height; + f32 vy2 = 0.5 - (yy + eps) / (f32) height; + f32 tx = (x + 0.5) / (f32) width; + f32 ty1 = y / (f32) height; + f32 ty2 = yy / (f32) height; + video::S3DVertex vertices[8] = + { + video::S3DVertex(vx,vy1,-0.5, -1,0,0, c, tx,ty1), + video::S3DVertex(vx,vy2,-0.5, -1,0,0, c, tx,ty2), + video::S3DVertex(vx,vy2,0.5, -1,0,0, c, tx,ty2), + video::S3DVertex(vx,vy1,0.5, -1,0,0, c, tx,ty1), + }; + u16 indices[6] = {0,1,2,2,3,0}; + buf->append(vertices, 4, indices, 6); + y = yy - 1; + } + } + } + + // Add to mesh + scene::SMesh* mesh = new scene::SMesh(); + mesh->addMeshBuffer(buf); + buf->drop(); + mesh->recalculateBoundingBox(); + scene::SAnimatedMesh* anim_mesh = new scene::SAnimatedMesh(mesh); + mesh->drop(); + return anim_mesh; +} + +scene::IAnimatedMesh* ExtrudedSpriteSceneNode::extrude(video::ITexture* texture) +{ + scene::IAnimatedMesh* mesh = NULL; + core::dimension2d size = texture->getSize(); + video::ECOLOR_FORMAT format = texture->getColorFormat(); + if (format == video::ECF_A8R8G8B8) + { + // Texture is in the correct color format, we can pass it + // to extrudeARGB right away. + void* data = texture->lock(true); + if (data == NULL) + return NULL; + mesh = extrudeARGB(size.Width, size.Height, (u8*) data); + texture->unlock(); + } + else + { + video::IVideoDriver* driver = SceneManager->getVideoDriver(); + + video::IImage* img1 = driver->createImageFromData(format, size, texture->lock(true)); + if (img1 == NULL) + return NULL; + + // img1 is in the texture's color format, convert to 8-bit ARGB + video::IImage* img2 = driver->createImage(video::ECF_A8R8G8B8, size); + if (img2 != NULL) + { + img1->copyTo(img2); + img1->drop(); + + mesh = extrudeARGB(size.Width, size.Height, (u8*) img2->lock()); + img2->unlock(); + img2->drop(); + } + img1->drop(); + } + return mesh; +} + diff --git a/src/camera.h b/src/camera.h index dd9f3055..08c03dd1 100644 --- a/src/camera.h +++ b/src/camera.h @@ -21,14 +21,17 @@ with this program; if not, write to the Free Software Foundation, Inc., #define CAMERA_HEADER #include "common_irrlicht.h" +#include "inventory.h" #include "utility.h" class LocalPlayer; class MapDrawControl; +class ExtrudedSpriteSceneNode; /* Client camera class, manages the player and camera scene nodes, the viewing distance - and performs view bobbing etc. + and performs view bobbing etc. It also displays the wielded tool in front of the + first-person camera. */ class Camera { @@ -59,6 +62,12 @@ class Camera return m_cameranode; } + // Get wielded item scene node. + inline ExtrudedSpriteSceneNode* getWieldNode() const + { + return m_wieldnode; + } + // Get the camera position (in absolute scene coordinates). // This has view bobbing applied. inline v3f getPosition() const @@ -107,12 +116,19 @@ class Camera // Update settings from g_settings void updateSettings(); + // Replace the wielded item mesh + void wield(InventoryItem* item); + + // Start or stop digging animation + void setDigging(bool digging); + private: // Scene manager and nodes scene::ISceneManager* m_smgr; scene::ISceneNode* m_playernode; scene::ISceneNode* m_headnode; scene::ICameraSceneNode* m_cameranode; + ExtrudedSpriteSceneNode* m_wieldnode; // draw control MapDrawControl& m_draw_control; @@ -151,5 +167,51 @@ class Camera f32 m_view_bobbing_speed; }; -#endif +/* + A scene node that displays a 2D mesh extruded into the third dimension, + to add an illusion of depth. + + Since this class was created to display the wielded tool of the local + player, and only tools and items are rendered like this (but not solid + content like stone and mud, which are shown as cubes), the option to + draw a textured cube instead is provided. + */ +class ExtrudedSpriteSceneNode: public scene::ISceneNode +{ +public: + ExtrudedSpriteSceneNode( + scene::ISceneNode* parent, + scene::ISceneManager* mgr, + s32 id = -1, + const v3f& position = v3f(0,0,0), + const v3f& rotation = v3f(0,0,0), + const v3f& scale = v3f(0,0,0)); + ~ExtrudedSpriteSceneNode(); + + void setSprite(video::ITexture* texture); + void setCube(const TileSpec faces[6]); + + f32 getSpriteThickness() const { return m_thickness; } + void setSpriteThickness(f32 thickness); + + void removeSpriteFromCache(video::ITexture* texture); + + virtual const core::aabbox3d& getBoundingBox() const; + virtual void OnRegisterSceneNode(); + virtual void render(); + +private: + scene::IMeshSceneNode* m_meshnode; + f32 m_thickness; + scene::IMesh* m_cubemesh; + bool m_is_cube; + + // internal extrusion helper methods + io::path getExtrudedName(video::ITexture* texture); + scene::IAnimatedMesh* extrudeARGB(u32 width, u32 height, u8* data); + scene::IAnimatedMesh* extrude(video::ITexture* texture); + scene::IMesh* createCubeMesh(); +}; + +#endif diff --git a/src/client.cpp b/src/client.cpp index 71a826a1..81dedd14 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -2004,14 +2004,6 @@ LocalPlayer* Client::getLocalPlayer() return m_env.getLocalPlayer(); } -void Client::setPlayerWield(scene::ISceneNode *wield) -{ - //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out - LocalPlayer *player = m_env.getLocalPlayer(); - assert(player != NULL); - player->wield = wield; -} - void Client::setPlayerControl(PlayerControl &control) { //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out diff --git a/src/client.h b/src/client.h index e7a81a11..930987c0 100644 --- a/src/client.h +++ b/src/client.h @@ -210,7 +210,6 @@ class Client : public con::PeerHandler, public InventoryManager LocalPlayer* getLocalPlayer(); - void setPlayerWield(scene::ISceneNode *wield); void setPlayerControl(PlayerControl &control); void selectPlayerItem(u16 item); diff --git a/src/game.cpp b/src/game.cpp index a712323b..5e8db9b1 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -819,44 +819,6 @@ void the_game( f32 camera_yaw = 0; // "right/left" f32 camera_pitch = 0; // "up/down" - /* - Tool - */ - - v3f tool_wield_position(0.06*BS, -0.06*BS, 0.1*BS); - v3f tool_wield_rotation(-25, 180, -25); - float tool_wield_animation = 0.0; - scene::IMeshSceneNode *tool_wield; - { - scene::SMesh *mesh = new scene::SMesh(); - scene::IMeshBuffer *buf = new scene::SMeshBuffer(); - video::SColor c(255,255,255,255); - video::S3DVertex vertices[4] = - { - video::S3DVertex(-0.5,0,0, 0,0,0, c, 0,1), - video::S3DVertex(0.5,0,0, 0,0,0, c, 1,1), - video::S3DVertex(0.5,0.5,0, 0,0,0, c, 1,0), - video::S3DVertex(-0.5,0.5,0, 0,0,0, c, 0,0), - }; - u16 indices[] = {0,1,2,2,3,0}; - buf->append(vertices, 4, indices, 6); - // Set material - buf->getMaterial().setFlag(video::EMF_LIGHTING, false); - buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); - buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; - // Add to mesh - mesh->addMeshBuffer(buf); - buf->drop(); - - tool_wield = smgr->addMeshSceneNode(mesh, camera.getHeadNode()); - mesh->drop(); - } - tool_wield->setVisible(false); - tool_wield->setPosition(tool_wield_position); - tool_wield->setRotation(tool_wield_rotation); - - client.setPlayerWield(tool_wield); - /* Clouds */ @@ -1552,6 +1514,7 @@ void the_game( std::cout<getBlock()->getPos(), selected_object->getId(), g_selected_item); + camera.setDigging(true); } else if(input->getRightClicked()) { @@ -1619,6 +1582,7 @@ void the_game( std::cout<getId(), g_selected_item); + camera.setDigging(true); } else if(input->getRightClicked()) { @@ -1792,6 +1756,8 @@ void the_game( } dig_time += dtime; + + camera.setDigging(true); } } @@ -1859,16 +1825,6 @@ void the_game( nodepos_old = nodepos; } - else{ - } - - - if(input->getLeftState()) - // Tool animation loops 0.0 - 1.0 - tool_wield_animation = fmod(tool_wield_animation + dtime * 3.0, 1.0); - else - // Return tool to holding position if not digging - tool_wield_animation /= 1.5; } // selected_object == NULL @@ -1880,6 +1836,7 @@ void the_game( std::cout<getRightReleased()) { @@ -1985,16 +1942,6 @@ void the_game( ); } - /* - Animate tool - */ - { - f32 tool_wield_sin = sin(tool_wield_animation * PI); - tool_wield->setRotation(tool_wield_rotation - tool_wield_sin * 40.0); - tool_wield->setPosition(tool_wield_position - tool_wield_sin * BS / 30.0); - } - - /* Update gui stuff (0ms) */ @@ -2140,6 +2087,13 @@ void the_game( old_selected_item = g_selected_item; //std::cout<<"Updating local inventory"<getItem(g_selected_item); + camera.wield(item); } /* diff --git a/src/inventory.h b/src/inventory.h index ef8c499b..4aa68d99 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -56,8 +56,6 @@ class InventoryItem // Return the name of the image for this item virtual std::string getBasename() { return ""; } // Shall return an image of the item (or NULL) - virtual video::ITexture * getImageRaw() { return NULL; } - // Shall return an image to show in the GUI (or NULL) virtual video::ITexture * getImage() { return NULL; } #endif // Shall return a text to show in the GUI @@ -156,7 +154,6 @@ class MaterialItem : public InventoryItem video::ITexture * getImage() { return content_features(m_content).inventory_texture; - return NULL; } #endif std::string getText() @@ -388,14 +385,6 @@ class ToolItem : public InventoryItem return "cloud.png"; } - video::ITexture * getImageRaw() - { - if(g_texturesource == NULL) - return NULL; - - return g_texturesource->getTextureRaw(getBasename()); - } - video::ITexture * getImage() { if(g_texturesource == NULL) diff --git a/src/player.cpp b/src/player.cpp index 03ae24f4..7cfdfebb 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -309,31 +309,12 @@ LocalPlayer::LocalPlayer(): // Initialize hp to 0, so that no hearts will be shown if server // doesn't support health points hp = 0; - - // No tool wielded initially - wield = NULL; } LocalPlayer::~LocalPlayer() { } -void LocalPlayer::wieldItem(u16 item) -{ - m_selected_item = item; - - if(wield) { - InventoryItem* i = inventory.getList("main")->getItem(m_selected_item); - - if(i && strcmp(i->getName(), "ToolItem") == 0) { - wield->getMaterial(0).setTexture(0, i->getImageRaw()); - wield->setVisible(true); - } - else - wield->setVisible(false); - } -} - void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, core::list *collision_info) { diff --git a/src/player.h b/src/player.h index 0f2c4001..ad0fb5ff 100644 --- a/src/player.h +++ b/src/player.h @@ -357,8 +357,6 @@ class LocalPlayer : public Player return true; } - void wieldItem(u16 item); - void move(f32 dtime, Map &map, f32 pos_max_d, core::list *collision_info); void move(f32 dtime, Map &map, f32 pos_max_d); @@ -367,8 +365,6 @@ class LocalPlayer : public Player PlayerControl control; - scene::ISceneNode *wield; - private: // This is used for determining the sneaking range v3s16 m_sneak_node; From 02726f00031c8ffadf5298b037b595372be202ef Mon Sep 17 00:00:00 2001 From: Kahrl Date: Mon, 19 Sep 2011 06:37:24 +0200 Subject: [PATCH 17/26] Convert any inventory item into a mesh, bring back InventoryItem::getImageRay(), some const-correctness fixes --- src/camera.cpp | 149 ++++++++++++++++++++++++++++++++++++---------- src/camera.h | 5 +- src/inventory.cpp | 4 +- src/inventory.h | 24 +++++--- src/tile.h | 2 +- 5 files changed, 141 insertions(+), 43 deletions(-) diff --git a/src/camera.cpp b/src/camera.cpp index aae36c51..e7d50617 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "main.h" // for g_settings #include "map.h" #include "player.h" +#include "tile.h" #include const s32 BOBFRAMES = 0x1000000; // must be a power of two @@ -343,17 +344,37 @@ void Camera::updateSettings() m_wanted_frametime = 1.0 / wanted_fps; } -void Camera::wield(InventoryItem* item) +void Camera::wield(const InventoryItem* item) { if (item != NULL) { - dstream << "wield item: " << item->getName() << std::endl; - m_wieldnode->setSprite(item->getImageRaw()); + bool isCube = false; + + // Try to make a MaterialItem cube. + if (std::string(item->getName()) == "MaterialItem") + { + // A block-type material + MaterialItem* mat_item = (MaterialItem*) item; + content_t content = mat_item->getMaterial(); + if (content_features(content).solidness) + { + m_wieldnode->setCube(content_features(content).tiles); + isCube = true; + } + } + + // If that failed, make an extruded sprite. + if (!isCube) + { + m_wieldnode->setSprite(item->getImageRaw()); + } + m_wieldnode->setVisible(true); } else { - dstream << "wield item: none" << std::endl; + // Bare hands + dstream << "bare hands" << std::endl; m_wieldnode->setVisible(false); } } @@ -427,23 +448,37 @@ void ExtrudedSpriteSceneNode::setSprite(video::ITexture* texture) m_is_cube = false; } -void ExtrudedSpriteSceneNode::setCube(video::ITexture* texture) +void ExtrudedSpriteSceneNode::setCube(const TileSpec tiles[6]) { - if (texture == NULL) - { - m_meshnode->setVisible(false); - return; - } - if (m_cubemesh == NULL) - m_cubemesh = SceneManager->getGeometryCreator()->createCubeMesh(v3f(1)); + m_cubemesh = createCubeMesh(); m_meshnode->setMesh(m_cubemesh); m_meshnode->setScale(v3f(1)); - m_meshnode->getMaterial(0).setTexture(0, texture); - m_meshnode->getMaterial(0).setFlag(video::EMF_LIGHTING, false); - m_meshnode->getMaterial(0).setFlag(video::EMF_BILINEAR_FILTER, false); - m_meshnode->getMaterial(0).MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; + for (int i = 0; i < 6; ++i) + { + // Get the tile texture and atlas transformation + u32 texture_id = tiles[i].texture.id; + video::ITexture* atlas = NULL; + v2f pos(0,0); + v2f size(1,1); + if (g_texturesource) + { + AtlasPointer ap = g_texturesource->getTexture(texture_id); + atlas = ap.atlas; + pos = ap.pos; + size = ap.size; + } + + // Set material flags and texture + video::SMaterial& material = m_meshnode->getMaterial(i); + material.setFlag(video::EMF_LIGHTING, false); + material.setFlag(video::EMF_BILINEAR_FILTER, false); + tiles[i].applyMaterialOptions(material); + material.setTexture(0, atlas); + material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y); + material.getTextureMatrix(0).setTextureScale(size.X, size.Y); + } m_meshnode->setVisible(true); m_is_cube = true; } @@ -500,13 +535,13 @@ scene::IAnimatedMesh* ExtrudedSpriteSceneNode::extrudeARGB(u32 width, u32 height video::S3DVertex vertices[8] = { video::S3DVertex(-0.5,-0.5,-0.5, 0,0,-1, c, 0,1), - video::S3DVertex(-0.5,0.5,-0.5, 0,0,-1, c, 0,0), - video::S3DVertex(0.5,0.5,-0.5, 0,0,-1, c, 1,0), - video::S3DVertex(0.5,-0.5,-0.5, 0,0,-1, c, 1,1), - video::S3DVertex(0.5,-0.5,0.5, 0,0,1, c, 1,1), - video::S3DVertex(0.5,0.5,0.5, 0,0,1, c, 1,0), - video::S3DVertex(-0.5,0.5,0.5, 0,0,1, c, 0,0), - video::S3DVertex(-0.5,-0.5,0.5, 0,0,1, c, 0,1), + video::S3DVertex(-0.5,+0.5,-0.5, 0,0,-1, c, 0,0), + video::S3DVertex(+0.5,+0.5,-0.5, 0,0,-1, c, 1,0), + video::S3DVertex(+0.5,-0.5,-0.5, 0,0,-1, c, 1,1), + video::S3DVertex(+0.5,-0.5,+0.5, 0,0,+1, c, 1,1), + video::S3DVertex(+0.5,+0.5,+0.5, 0,0,+1, c, 1,0), + video::S3DVertex(-0.5,+0.5,+0.5, 0,0,+1, c, 0,0), + video::S3DVertex(-0.5,-0.5,+0.5, 0,0,+1, c, 0,1), }; u16 indices[12] = {0,1,2,2,3,0,4,5,6,6,7,4}; buf->append(vertices, 8, indices, 12); @@ -557,8 +592,8 @@ scene::IAnimatedMesh* ExtrudedSpriteSceneNode::extrudeARGB(u32 width, u32 height { video::S3DVertex(vx1,vy,-0.5, 0,-1,0, c, tx1,ty), video::S3DVertex(vx2,vy,-0.5, 0,-1,0, c, tx2,ty), - video::S3DVertex(vx2,vy,0.5, 0,-1,0, c, tx2,ty), - video::S3DVertex(vx1,vy,0.5, 0,-1,0, c, tx1,ty), + video::S3DVertex(vx2,vy,+0.5, 0,-1,0, c, tx2,ty), + video::S3DVertex(vx1,vy,+0.5, 0,-1,0, c, tx1,ty), }; u16 indices[6] = {0,1,2,2,3,0}; buf->append(vertices, 4, indices, 6); @@ -578,8 +613,8 @@ scene::IAnimatedMesh* ExtrudedSpriteSceneNode::extrudeARGB(u32 width, u32 height video::S3DVertex vertices[8] = { video::S3DVertex(vx1,vy,-0.5, 0,1,0, c, tx1,ty), - video::S3DVertex(vx1,vy,0.5, 0,1,0, c, tx1,ty), - video::S3DVertex(vx2,vy,0.5, 0,1,0, c, tx2,ty), + video::S3DVertex(vx1,vy,+0.5, 0,1,0, c, tx1,ty), + video::S3DVertex(vx2,vy,+0.5, 0,1,0, c, tx2,ty), video::S3DVertex(vx2,vy,-0.5, 0,1,0, c, tx2,ty), }; u16 indices[6] = {0,1,2,2,3,0}; @@ -608,8 +643,8 @@ scene::IAnimatedMesh* ExtrudedSpriteSceneNode::extrudeARGB(u32 width, u32 height video::S3DVertex vertices[8] = { video::S3DVertex(vx,vy1,-0.5, 1,0,0, c, tx,ty1), - video::S3DVertex(vx,vy1,0.5, 1,0,0, c, tx,ty1), - video::S3DVertex(vx,vy2,0.5, 1,0,0, c, tx,ty2), + video::S3DVertex(vx,vy1,+0.5, 1,0,0, c, tx,ty1), + video::S3DVertex(vx,vy2,+0.5, 1,0,0, c, tx,ty2), video::S3DVertex(vx,vy2,-0.5, 1,0,0, c, tx,ty2), }; u16 indices[6] = {0,1,2,2,3,0}; @@ -631,8 +666,8 @@ scene::IAnimatedMesh* ExtrudedSpriteSceneNode::extrudeARGB(u32 width, u32 height { video::S3DVertex(vx,vy1,-0.5, -1,0,0, c, tx,ty1), video::S3DVertex(vx,vy2,-0.5, -1,0,0, c, tx,ty2), - video::S3DVertex(vx,vy2,0.5, -1,0,0, c, tx,ty2), - video::S3DVertex(vx,vy1,0.5, -1,0,0, c, tx,ty1), + video::S3DVertex(vx,vy2,+0.5, -1,0,0, c, tx,ty2), + video::S3DVertex(vx,vy1,+0.5, -1,0,0, c, tx,ty1), }; u16 indices[6] = {0,1,2,2,3,0}; buf->append(vertices, 4, indices, 6); @@ -643,6 +678,7 @@ scene::IAnimatedMesh* ExtrudedSpriteSceneNode::extrudeARGB(u32 width, u32 height // Add to mesh scene::SMesh* mesh = new scene::SMesh(); + buf->recalculateBoundingBox(); mesh->addMeshBuffer(buf); buf->drop(); mesh->recalculateBoundingBox(); @@ -690,3 +726,54 @@ scene::IAnimatedMesh* ExtrudedSpriteSceneNode::extrude(video::ITexture* texture) return mesh; } +scene::IMesh* ExtrudedSpriteSceneNode::createCubeMesh() +{ + video::SColor c(255,255,255,255); + video::S3DVertex vertices[24] = + { + // Up + video::S3DVertex(-0.5,+0.5,-0.5, 0,1,0, c, 0,1), + video::S3DVertex(-0.5,+0.5,+0.5, 0,1,0, c, 0,0), + video::S3DVertex(+0.5,+0.5,+0.5, 0,1,0, c, 1,0), + video::S3DVertex(+0.5,+0.5,-0.5, 0,1,0, c, 1,1), + // Down + video::S3DVertex(-0.5,-0.5,-0.5, 0,-1,0, c, 0,0), + video::S3DVertex(+0.5,-0.5,-0.5, 0,-1,0, c, 1,0), + video::S3DVertex(+0.5,-0.5,+0.5, 0,-1,0, c, 1,1), + video::S3DVertex(-0.5,-0.5,+0.5, 0,-1,0, c, 0,1), + // Right + video::S3DVertex(+0.5,-0.5,-0.5, 1,0,0, c, 0,1), + video::S3DVertex(+0.5,+0.5,-0.5, 1,0,0, c, 0,0), + video::S3DVertex(+0.5,+0.5,+0.5, 1,0,0, c, 1,0), + video::S3DVertex(+0.5,-0.5,+0.5, 1,0,0, c, 1,1), + // Left + video::S3DVertex(-0.5,-0.5,-0.5, -1,0,0, c, 1,1), + video::S3DVertex(-0.5,-0.5,+0.5, -1,0,0, c, 0,1), + video::S3DVertex(-0.5,+0.5,+0.5, -1,0,0, c, 0,0), + video::S3DVertex(-0.5,+0.5,-0.5, -1,0,0, c, 1,0), + // Back + video::S3DVertex(-0.5,-0.5,+0.5, 0,0,-1, c, 1,1), + video::S3DVertex(+0.5,-0.5,+0.5, 0,0,-1, c, 0,1), + video::S3DVertex(+0.5,+0.5,+0.5, 0,0,-1, c, 0,0), + video::S3DVertex(-0.5,+0.5,+0.5, 0,0,-1, c, 1,0), + // Front + video::S3DVertex(-0.5,-0.5,-0.5, 0,0,-1, c, 0,1), + video::S3DVertex(-0.5,+0.5,-0.5, 0,0,-1, c, 0,0), + video::S3DVertex(+0.5,+0.5,-0.5, 0,0,-1, c, 1,0), + video::S3DVertex(+0.5,-0.5,-0.5, 0,0,-1, c, 1,1), + }; + + u16 indices[6] = {0,1,2,2,3,0}; + + scene::SMesh* mesh = new scene::SMesh(); + for (u32 i=0; i<6; ++i) + { + scene::IMeshBuffer* buf = new scene::SMeshBuffer(); + buf->append(vertices + 4 * i, 4, indices, 6); + buf->recalculateBoundingBox(); + mesh->addMeshBuffer(buf); + buf->drop(); + } + mesh->recalculateBoundingBox(); + return mesh; +} diff --git a/src/camera.h b/src/camera.h index 08c03dd1..ccc224e3 100644 --- a/src/camera.h +++ b/src/camera.h @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "common_irrlicht.h" #include "inventory.h" +#include "tile.h" #include "utility.h" class LocalPlayer; @@ -117,7 +118,7 @@ class Camera void updateSettings(); // Replace the wielded item mesh - void wield(InventoryItem* item); + void wield(const InventoryItem* item); // Start or stop digging animation void setDigging(bool digging); @@ -190,7 +191,7 @@ class ExtrudedSpriteSceneNode: public scene::ISceneNode ~ExtrudedSpriteSceneNode(); void setSprite(video::ITexture* texture); - void setCube(const TileSpec faces[6]); + void setCube(const TileSpec tiles[6]); f32 getSpriteThickness() const { return m_thickness; } void setSpriteThickness(f32 thickness); diff --git a/src/inventory.cpp b/src/inventory.cpp index f31e19f7..a3e35c92 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -158,7 +158,7 @@ InventoryItem *MaterialItem::createCookResult() const */ #ifndef SERVER -video::ITexture * CraftItem::getImage() +video::ITexture * CraftItem::getImage() const { if(g_texturesource == NULL) return NULL; @@ -224,7 +224,7 @@ bool CraftItem::use(ServerEnvironment *env, Player *player) TODO: Remove */ #ifndef SERVER -video::ITexture * MapBlockObjectItem::getImage() +video::ITexture * MapBlockObjectItem::getImage() const { if(m_inventorystring.substr(0,3) == "Rat") return g_texturesource->getTextureRaw("rat.png"); diff --git a/src/inventory.h b/src/inventory.h index 4aa68d99..3e05015e 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -54,9 +54,11 @@ class InventoryItem virtual InventoryItem* clone() = 0; #ifndef SERVER // Return the name of the image for this item - virtual std::string getBasename() { return ""; } + virtual std::string getBasename() const { return ""; } // Shall return an image of the item (or NULL) - virtual video::ITexture * getImage() { return NULL; } + virtual video::ITexture * getImage() const { return NULL; } + // Shall return an image of the item without embellishments (or NULL) + virtual video::ITexture * getImageRaw() const { return getImage(); } #endif // Shall return a text to show in the GUI virtual std::string getText() { return ""; } @@ -151,7 +153,7 @@ class MaterialItem : public InventoryItem return new MaterialItem(m_content, m_count); } #ifndef SERVER - video::ITexture * getImage() + video::ITexture * getImage() const { return content_features(m_content).inventory_texture; } @@ -226,7 +228,7 @@ class MapBlockObjectItem : public InventoryItem } #ifndef SERVER - video::ITexture * getImage(); + video::ITexture * getImage() const; #endif std::string getText(); @@ -277,7 +279,7 @@ class CraftItem : public InventoryItem return new CraftItem(m_subname, m_count); } #ifndef SERVER - video::ITexture * getImage(); + video::ITexture * getImage() const; #endif std::string getText() { @@ -354,7 +356,7 @@ class ToolItem : public InventoryItem return new ToolItem(m_toolname, m_wear); } #ifndef SERVER - std::string getBasename() { + std::string getBasename() const { if(m_toolname == "WPick") return "tool_woodpick.png"; else if(m_toolname == "STPick") @@ -385,7 +387,7 @@ class ToolItem : public InventoryItem return "cloud.png"; } - video::ITexture * getImage() + video::ITexture * getImage() const { if(g_texturesource == NULL) return NULL; @@ -405,6 +407,14 @@ class ToolItem : public InventoryItem return g_texturesource->getTextureRaw(os.str()); } + + video::ITexture * getImageRaw() const + { + if(g_texturesource == NULL) + return NULL; + + return g_texturesource->getTextureRaw(getBasename()); + } #endif std::string getText() { diff --git a/src/tile.h b/src/tile.h index 216d7650..5cebb0ea 100644 --- a/src/tile.h +++ b/src/tile.h @@ -304,7 +304,7 @@ struct TileSpec } // Sets everything else except the texture in the material - void applyMaterialOptions(video::SMaterial &material) + void applyMaterialOptions(video::SMaterial &material) const { if(alpha != 255 && material_type != MATERIAL_ALPHA_VERTEX) dstream<<"WARNING: TileSpec: alpha != 255 " From ab42549b1e48ede22d96e9f4ac017bb5d1853724 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Mon, 19 Sep 2011 17:08:42 +0200 Subject: [PATCH 18/26] Wielded tool updates, leaves and glass work now --- src/camera.cpp | 26 +++++++++++--------------- src/camera.h | 7 ++++++- src/content_mapnode.cpp | 4 ++++ 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/camera.cpp b/src/camera.cpp index e7d50617..c5c40f5c 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -54,7 +54,10 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control): m_view_bobbing_anim(0), m_view_bobbing_state(0), - m_view_bobbing_speed(0) + m_view_bobbing_speed(0), + + m_digging_anim(0), + m_digging_speed(0) { //dstream<<__FUNCTION_NAME<addEmptySceneNode(m_playernode); m_cameranode = smgr->addCameraSceneNode(smgr->getRootSceneNode()); m_cameranode->bindTargetAndRotation(true); - m_wieldnode = new ExtrudedSpriteSceneNode(smgr->getRootSceneNode(), smgr, -1, v3f(0, 120, 10), v3f(0, 0, 0), v3f(100, 100, 100)); - //m_wieldnode = new ExtrudedSpriteSceneNode(smgr->getRootSceneNode(), smgr, -1); + m_wieldnode = new ExtrudedSpriteSceneNode(m_headnode, smgr, -1, v3f(1.3, -1, 2), v3f(-20, -100, 20), v3f(1)); updateSettings(); } @@ -356,9 +358,10 @@ void Camera::wield(const InventoryItem* item) // A block-type material MaterialItem* mat_item = (MaterialItem*) item; content_t content = mat_item->getMaterial(); - if (content_features(content).solidness) + if (content_features(content).solidness || content_features(content).visual_solidness) { m_wieldnode->setCube(content_features(content).tiles); + m_wieldnode->setScale(v3f(0.9)); isCube = true; } } @@ -367,6 +370,7 @@ void Camera::wield(const InventoryItem* item) if (!isCube) { m_wieldnode->setSprite(item->getImageRaw()); + m_wieldnode->setScale(v3f(1.2)); } m_wieldnode->setVisible(true); @@ -458,17 +462,9 @@ void ExtrudedSpriteSceneNode::setCube(const TileSpec tiles[6]) for (int i = 0; i < 6; ++i) { // Get the tile texture and atlas transformation - u32 texture_id = tiles[i].texture.id; - video::ITexture* atlas = NULL; - v2f pos(0,0); - v2f size(1,1); - if (g_texturesource) - { - AtlasPointer ap = g_texturesource->getTexture(texture_id); - atlas = ap.atlas; - pos = ap.pos; - size = ap.size; - } + video::ITexture* atlas = tiles[i].texture.atlas; + v2f pos = tiles[i].texture.pos; + v2f size = tiles[i].texture.size; // Set material flags and texture video::SMaterial& material = m_meshnode->getMaterial(i); diff --git a/src/camera.h b/src/camera.h index ccc224e3..f960e748 100644 --- a/src/camera.h +++ b/src/camera.h @@ -166,6 +166,11 @@ class Camera s32 m_view_bobbing_state; // Speed of view bobbing animation f32 m_view_bobbing_speed; + + // Digging animation + s32 m_digging_anim; + // Speed of digging animation + s32 m_digging_speed; }; @@ -187,7 +192,7 @@ class ExtrudedSpriteSceneNode: public scene::ISceneNode s32 id = -1, const v3f& position = v3f(0,0,0), const v3f& rotation = v3f(0,0,0), - const v3f& scale = v3f(0,0,0)); + const v3f& scale = v3f(1,1,1)); ~ExtrudedSpriteSceneNode(); void setSprite(video::ITexture* texture); diff --git a/src/content_mapnode.cpp b/src/content_mapnode.cpp index 89171755..70f46513 100644 --- a/src/content_mapnode.cpp +++ b/src/content_mapnode.cpp @@ -236,6 +236,8 @@ void content_mapnode_init() if(new_style_leaves) { f->solidness = 0; // drawn separately, makes no faces + f->visual_solidness = 1; + f->setAllTextures("leaves.png"); f->setInventoryTextureCube("leaves.png", "leaves.png", "leaves.png"); } else @@ -287,6 +289,8 @@ void content_mapnode_init() f->is_ground_content = true; f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; f->solidness = 0; // drawn separately, makes no faces + f->visual_solidness = 1; + f->setAllTextures("glass.png"); f->setInventoryTextureCube("glass.png", "glass.png", "glass.png"); setWoodLikeDiggingProperties(f->digging_properties, 0.15); From eaff4616adadf991a2bde66b9e1f1ab693c94c6d Mon Sep 17 00:00:00 2001 From: Kahrl Date: Mon, 19 Sep 2011 17:11:53 +0200 Subject: [PATCH 19/26] fix some normals --- src/camera.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/camera.cpp b/src/camera.cpp index c5c40f5c..7f5931bd 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -748,10 +748,10 @@ scene::IMesh* ExtrudedSpriteSceneNode::createCubeMesh() video::S3DVertex(-0.5,+0.5,+0.5, -1,0,0, c, 0,0), video::S3DVertex(-0.5,+0.5,-0.5, -1,0,0, c, 1,0), // Back - video::S3DVertex(-0.5,-0.5,+0.5, 0,0,-1, c, 1,1), - video::S3DVertex(+0.5,-0.5,+0.5, 0,0,-1, c, 0,1), - video::S3DVertex(+0.5,+0.5,+0.5, 0,0,-1, c, 0,0), - video::S3DVertex(-0.5,+0.5,+0.5, 0,0,-1, c, 1,0), + video::S3DVertex(-0.5,-0.5,+0.5, 0,0,1, c, 1,1), + video::S3DVertex(+0.5,-0.5,+0.5, 0,0,1, c, 0,1), + video::S3DVertex(+0.5,+0.5,+0.5, 0,0,1, c, 0,0), + video::S3DVertex(-0.5,+0.5,+0.5, 0,0,1, c, 1,0), // Front video::S3DVertex(-0.5,-0.5,-0.5, 0,0,-1, c, 0,1), video::S3DVertex(-0.5,+0.5,-0.5, 0,0,-1, c, 0,0), From 01f3ae1c5089f36f1f2a164bcaa36fb2fc8642be Mon Sep 17 00:00:00 2001 From: Kahrl Date: Tue, 20 Sep 2011 11:06:16 +0200 Subject: [PATCH 20/26] Digging animation --- src/camera.cpp | 90 +++++++++++++++++++++++++++++++++++++------------- src/camera.h | 19 ++++++----- src/game.cpp | 11 +++--- 3 files changed, 85 insertions(+), 35 deletions(-) diff --git a/src/camera.cpp b/src/camera.cpp index 7f5931bd..a1830fcf 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -26,13 +26,12 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "tile.h" #include -const s32 BOBFRAMES = 0x1000000; // must be a power of two - Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control): m_smgr(smgr), m_playernode(NULL), m_headnode(NULL), m_cameranode(NULL), + m_wieldnode(NULL), m_draw_control(draw_control), m_viewing_range_min(5.0), m_viewing_range_max(5.0), @@ -57,7 +56,7 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control): m_view_bobbing_speed(0), m_digging_anim(0), - m_digging_speed(0) + m_digging_button(-1) { //dstream<<__FUNCTION_NAME<addEmptySceneNode(m_playernode); m_cameranode = smgr->addCameraSceneNode(smgr->getRootSceneNode()); m_cameranode->bindTargetAndRotation(true); - m_wieldnode = new ExtrudedSpriteSceneNode(m_headnode, smgr, -1, v3f(1.3, -1, 2), v3f(-20, -100, 20), v3f(1)); + m_wieldnode = new ExtrudedSpriteSceneNode(m_headnode, smgr); updateSettings(); } @@ -93,24 +92,54 @@ bool Camera::successfullyCreated(std::wstring& error_message) error_message = L"Failed to create the camera scene node"; return false; } + if (m_wieldnode == NULL) + { + error_message = L"Failed to create the wielded item scene node"; + return false; + } return true; } +// Returns the fractional part of x +inline f32 my_modf(f32 x) +{ + double dummy; + return modf(x, &dummy); +} + void Camera::step(f32 dtime) { if (m_view_bobbing_state != 0) { - s32 offset = MYMAX(dtime * m_view_bobbing_speed * 0.035 * BOBFRAMES, 1); + f32 offset = dtime * m_view_bobbing_speed * 0.035; if (m_view_bobbing_state == 2) { // Animation is getting turned off - s32 subanim = (m_view_bobbing_anim & (BOBFRAMES/2-1)); - if (subanim < BOBFRAMES/4) - offset = -1 * MYMIN(offset, subanim); + if (m_view_bobbing_anim < 0.5) + m_view_bobbing_anim -= offset; else - offset = MYMIN(offset, BOBFRAMES/2 - subanim); + m_view_bobbing_anim += offset; + if (m_view_bobbing_anim <= 0 || m_view_bobbing_anim >= 1) + { + m_view_bobbing_anim = 0; + m_view_bobbing_state = 0; + } + } + else + { + m_view_bobbing_anim = my_modf(m_view_bobbing_anim + offset); + } + } + + if (m_digging_button != -1) + { + f32 offset = dtime * 3.5; + m_digging_anim += offset; + if (m_digging_anim >= 1) + { + m_digging_anim = 0; + m_digging_button = -1; } - m_view_bobbing_anim = (m_view_bobbing_anim + offset) & (BOBFRAMES-1); } } @@ -132,11 +161,10 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize) v3f rel_cam_target = v3f(0,0,1); v3f rel_cam_up = v3f(0,1,0); - s32 bobframe = m_view_bobbing_anim & (BOBFRAMES/2-1); - if (bobframe != 0) + if (m_view_bobbing_anim != 0) { - f32 bobfrac = (f32) bobframe / (BOBFRAMES/2); - f32 bobdir = (m_view_bobbing_anim < (BOBFRAMES/2)) ? 1.0 : -1.0; + f32 bobfrac = my_modf(m_view_bobbing_anim * 2); + f32 bobdir = (m_view_bobbing_anim < 0.5) ? 1.0 : -1.0; #if 1 f32 bobknob = 1.2; @@ -188,6 +216,27 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize) // Some more allowance that m_viewing_range_max * BS because of active objects etc. m_cameranode->setFarValue(m_viewing_range_max * BS * 10); + // Position the wielded item + v3f wield_position = v3f(1.3, -1.1, 2); + v3f wield_rotation = v3f(90, -90, -90); + if (m_digging_button != -1) + { + f32 digfrac = m_digging_anim; + wield_position.X -= sin(pow(digfrac, 0.8) * PI); + wield_position.Y += 0.5 * sin(digfrac * 2 * PI); + wield_position.Z += 0.2 * digfrac; + + // Euler angles are PURE EVIL, so why not use quaternions? + core::quaternion quat_begin(wield_rotation * core::DEGTORAD); + core::quaternion quat_end(v3f(90, 20, -130) * core::DEGTORAD); + core::quaternion quat_slerp; + quat_slerp.slerp(quat_begin, quat_end, sin(digfrac * PI)); + quat_slerp.toEuler(wield_rotation); + wield_rotation *= core::RADTODEG; + } + m_wieldnode->setPosition(wield_position); + m_wieldnode->setRotation(wield_rotation); + // Render distance feedback loop updateViewingRange(frametime); @@ -208,12 +257,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize) { // Stop animation m_view_bobbing_state = 2; - m_view_bobbing_speed = 100; - } - else if (m_view_bobbing_state == 2 && bobframe == 0) - { - // Stop animation completed - m_view_bobbing_state = 0; + m_view_bobbing_speed = 60; } } @@ -378,14 +422,14 @@ void Camera::wield(const InventoryItem* item) else { // Bare hands - dstream << "bare hands" << std::endl; m_wieldnode->setVisible(false); } } -void Camera::setDigging(bool digging) +void Camera::setDigging(s32 button) { - // TODO + if (m_digging_button == -1) + m_digging_button = button; } diff --git a/src/camera.h b/src/camera.h index f960e748..026f9287 100644 --- a/src/camera.h +++ b/src/camera.h @@ -120,8 +120,9 @@ class Camera // Replace the wielded item mesh void wield(const InventoryItem* item); - // Start or stop digging animation - void setDigging(bool digging); + // Start digging animation + // Pass 0 for left click, 1 for right click + void setDigging(s32 button); private: // Scene manager and nodes @@ -158,8 +159,8 @@ class Camera f32 m_frametime_counter; f32 m_time_per_range; - // View bobbing animation frame (0 <= m_view_bobbing < 0x1000000) - s32 m_view_bobbing_anim; + // View bobbing animation frame (0 <= m_view_bobbing_anim < 1) + f32 m_view_bobbing_anim; // If 0, view bobbing is off (e.g. player is standing). // If 1, view bobbing is on (player is walking). // If 2, view bobbing is getting switched off. @@ -167,10 +168,12 @@ class Camera // Speed of view bobbing animation f32 m_view_bobbing_speed; - // Digging animation - s32 m_digging_anim; - // Speed of digging animation - s32 m_digging_speed; + // Digging animation frame (0 <= m_digging_anim < 1) + f32 m_digging_anim; + // If -1, no digging animation + // If 0, left-click digging animation + // If 1, right-click digging animation + s32 m_digging_button; }; diff --git a/src/game.cpp b/src/game.cpp index 5e8db9b1..08bc6f17 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1514,7 +1514,6 @@ void the_game( std::cout<getBlock()->getPos(), selected_object->getId(), g_selected_item); - camera.setDigging(true); } else if(input->getRightClicked()) { @@ -1582,7 +1581,6 @@ void the_game( std::cout<getId(), g_selected_item); - camera.setDigging(true); } else if(input->getRightClicked()) { @@ -1757,7 +1755,7 @@ void the_game( dig_time += dtime; - camera.setDigging(true); + camera.setDigging(0); // left click animation } } @@ -1820,6 +1818,7 @@ void the_game( else { client.groundAction(1, nodepos, neighbourpos, g_selected_item); + camera.setDigging(1); // right click animation } } @@ -1828,6 +1827,11 @@ void the_game( } // selected_object == NULL + if(input->getLeftClicked()) + { + camera.setDigging(0); // left click animation + } + input->resetLeftClicked(); input->resetRightClicked(); @@ -1836,7 +1840,6 @@ void the_game( std::cout<getRightReleased()) { From cbd2bcf102bd338ba1d97ad54bd257913f4dcd36 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Tue, 20 Sep 2011 18:19:26 +0200 Subject: [PATCH 21/26] Fix jittery view bobbing at large map coordinates again. Wielded tool still has problems there --- src/camera.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/camera.cpp b/src/camera.cpp index a1830fcf..316a3f70 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -195,17 +195,16 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize) // Compute absolute camera position and target m_headnode->getAbsoluteTransformation().transformVect(m_camera_position, rel_cam_pos); - m_headnode->getAbsoluteTransformation().transformVect(m_camera_direction, rel_cam_target); - m_camera_direction -= m_camera_position; + m_headnode->getAbsoluteTransformation().rotateVect(m_camera_direction, rel_cam_target - rel_cam_pos); v3f abs_cam_up; - m_headnode->getAbsoluteTransformation().transformVect(abs_cam_up, rel_cam_pos + rel_cam_up); - abs_cam_up -= m_camera_position; + m_headnode->getAbsoluteTransformation().rotateVect(abs_cam_up, rel_cam_up); // Set camera node transformation m_cameranode->setPosition(m_camera_position); m_cameranode->setUpVector(abs_cam_up); - m_cameranode->setTarget(m_camera_position + m_camera_direction); + // *100.0 helps in large map coordinates + m_cameranode->setTarget(m_camera_position + 100 * m_camera_direction); // FOV and and aspect ratio m_aspect = (f32)screensize.X / (f32) screensize.Y; From 6599002149f58c03b807cd1378ec17278dbdc09d Mon Sep 17 00:00:00 2001 From: Kahrl Date: Tue, 20 Sep 2011 18:25:29 +0200 Subject: [PATCH 22/26] fix a numerical problem, but tool is still jittery --- src/camera.cpp | 3 +-- src/player.h | 11 ++++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/camera.cpp b/src/camera.cpp index 316a3f70..4b0f968a 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -151,8 +151,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize) m_playernode->updateAbsolutePosition(); // Set head node transformation - v3f eye_offset = player->getEyePosition() - player->getPosition(); - m_headnode->setPosition(eye_offset); + m_headnode->setPosition(player->getEyeOffset()); m_headnode->setRotation(v3f(player->getPitch(), 0, 0)); m_headnode->updateAbsolutePosition(); diff --git a/src/player.h b/src/player.h index ad0fb5ff..350b85e1 100644 --- a/src/player.h +++ b/src/player.h @@ -67,12 +67,17 @@ class Player return floatToInt(m_position + v3f(0,BS+BS/2,0), BS); } - v3f getEyePosition() + v3f getEyeOffset() { // This is at the height of the eyes of the current figure - // return m_position + v3f(0, BS+BS/2, 0); + // return v3f(0, BS+BS/2, 0); // This is more like in minecraft - return m_position + v3f(0,BS+(5*BS)/8,0); + return v3f(0,BS+(5*BS)/8,0); + } + + v3f getEyePosition() + { + return m_position + getEyeOffset(); } virtual void setPosition(const v3f &position) From 36af9bb027ed6846227282587e3414ea3d30f6c5 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Wed, 21 Sep 2011 01:42:52 +0200 Subject: [PATCH 23/26] Create a separate scene manager for the wielded tool. This fixes the glitchyness in large map coordinates and some depth buffer problems. (The tool doesn't bob anymore when walking, this will be fixed later.) Fix MSVC build (thanks to dannydark). --- src/camera.cpp | 41 ++++++++++++++++++++++++++++++++++------- src/camera.h | 13 +++++++------ src/game.cpp | 8 ++++++++ 3 files changed, 49 insertions(+), 13 deletions(-) diff --git a/src/camera.cpp b/src/camera.cpp index 4b0f968a..56028da4 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -31,7 +31,10 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control): m_playernode(NULL), m_headnode(NULL), m_cameranode(NULL), + + m_wieldmgr(NULL), m_wieldnode(NULL), + m_draw_control(draw_control), m_viewing_range_min(5.0), m_viewing_range_max(5.0), @@ -66,13 +69,20 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control): m_headnode = smgr->addEmptySceneNode(m_playernode); m_cameranode = smgr->addCameraSceneNode(smgr->getRootSceneNode()); m_cameranode->bindTargetAndRotation(true); - m_wieldnode = new ExtrudedSpriteSceneNode(m_headnode, smgr); + + // This needs to be in its own scene manager. It is drawn after + // all other 3D scene nodes and before the GUI. + m_wieldmgr = smgr->createNewSceneManager(); + m_wieldmgr->addCameraSceneNode(); + m_wieldnode = new ExtrudedSpriteSceneNode(m_wieldmgr->getRootSceneNode(), m_wieldmgr); updateSettings(); } Camera::~Camera() { + m_wieldmgr->drop(); + m_wieldnode->drop(); } bool Camera::successfullyCreated(std::wstring& error_message) @@ -92,6 +102,11 @@ bool Camera::successfullyCreated(std::wstring& error_message) error_message = L"Failed to create the camera scene node"; return false; } + if (m_wieldmgr == NULL) + { + error_message = L"Failed to create the wielded item scene manager"; + return false; + } if (m_wieldnode == NULL) { error_message = L"Failed to create the wielded item scene node"; @@ -215,14 +230,14 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize) m_cameranode->setFarValue(m_viewing_range_max * BS * 10); // Position the wielded item - v3f wield_position = v3f(1.3, -1.1, 2); + v3f wield_position = v3f(45, -35, 65); v3f wield_rotation = v3f(90, -90, -90); if (m_digging_button != -1) { f32 digfrac = m_digging_anim; - wield_position.X -= sin(pow(digfrac, 0.8) * PI); - wield_position.Y += 0.5 * sin(digfrac * 2 * PI); - wield_position.Z += 0.2 * digfrac; + wield_position.X -= 30 * sin(pow(digfrac, 0.8f) * PI); + wield_position.Y += 15 * sin(digfrac * 2 * PI); + wield_position.Z += 5 * digfrac; // Euler angles are PURE EVIL, so why not use quaternions? core::quaternion quat_begin(wield_rotation * core::DEGTORAD); @@ -403,7 +418,7 @@ void Camera::wield(const InventoryItem* item) if (content_features(content).solidness || content_features(content).visual_solidness) { m_wieldnode->setCube(content_features(content).tiles); - m_wieldnode->setScale(v3f(0.9)); + m_wieldnode->setScale(v3f(30)); isCube = true; } } @@ -412,7 +427,7 @@ void Camera::wield(const InventoryItem* item) if (!isCube) { m_wieldnode->setSprite(item->getImageRaw()); - m_wieldnode->setScale(v3f(1.2)); + m_wieldnode->setScale(v3f(40)); } m_wieldnode->setVisible(true); @@ -430,6 +445,18 @@ void Camera::setDigging(s32 button) m_digging_button = button; } +void Camera::drawWieldedTool() +{ + m_wieldmgr->getVideoDriver()->clearZBuffer(); + + scene::ICameraSceneNode* cam = m_wieldmgr->getActiveCamera(); + cam->setAspectRatio(m_cameranode->getAspectRatio()); + cam->setFOV(m_cameranode->getFOV()); + cam->setNearValue(0.1); + cam->setFarValue(100); + m_wieldmgr->drawAll(); +} + ExtrudedSpriteSceneNode::ExtrudedSpriteSceneNode( scene::ISceneNode* parent, diff --git a/src/camera.h b/src/camera.h index 026f9287..fbee4a37 100644 --- a/src/camera.h +++ b/src/camera.h @@ -63,12 +63,6 @@ class Camera return m_cameranode; } - // Get wielded item scene node. - inline ExtrudedSpriteSceneNode* getWieldNode() const - { - return m_wieldnode; - } - // Get the camera position (in absolute scene coordinates). // This has view bobbing applied. inline v3f getPosition() const @@ -124,12 +118,19 @@ class Camera // Pass 0 for left click, 1 for right click void setDigging(s32 button); + // Draw the wielded tool. + // This has to happen *after* the main scene is drawn. + // Warning: This clears the Z buffer. + void drawWieldedTool(); + private: // Scene manager and nodes scene::ISceneManager* m_smgr; scene::ISceneNode* m_playernode; scene::ISceneNode* m_headnode; scene::ICameraSceneNode* m_cameranode; + + scene::ISceneManager* m_wieldmgr; ExtrudedSpriteSceneNode* m_wieldnode; // draw control diff --git a/src/game.cpp b/src/game.cpp index 08bc6f17..a9966265 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -2161,6 +2161,14 @@ void the_game( driver->draw3DBox(*i, video::SColor(255,0,0,0)); } + /* + Wielded tool + */ + { + // Warning: This clears the Z buffer. + camera.drawWieldedTool(); + } + /* Post effects */ From a4a2c348318139ae9605cf0d7477fe93e8aa2651 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Wed, 21 Sep 2011 15:54:06 +0200 Subject: [PATCH 24/26] reduce view bobbing slightly --- src/camera.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/camera.cpp b/src/camera.cpp index 56028da4..c14d0e8b 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -189,9 +189,9 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize) 0.8 * bobtmp * bobtmp, 0.); - rel_cam_pos += 0.03 * bobvec; - rel_cam_target += 0.045 * bobvec; - rel_cam_up.rotateXYBy(0.03 * bobdir * bobtmp * PI); + rel_cam_pos += 0.02 * bobvec; + rel_cam_target += 0.03 * bobvec; + rel_cam_up.rotateXYBy(0.02 * bobdir * bobtmp * PI); #else f32 angle_deg = 1 * bobdir * sin(bobfrac * PI); f32 angle_rad = angle_deg * PI / 180; From 3e012122d1607a6269af4e4522305d8b5efcd9d4 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Wed, 21 Sep 2011 18:37:29 +0200 Subject: [PATCH 25/26] Simplistic wielded tool lighting, added setMeshVerticesColor to utility.h and refactored some other code into calls of that --- src/camera.cpp | 13 +++++++++ src/camera.h | 3 ++ src/content_cao.cpp | 68 +++----------------------------------------- src/environment.cpp | 21 +++++++------- src/mapblockobject.h | 60 +++----------------------------------- src/player.h | 24 ++++++---------- src/utility.cpp | 19 +++++++++++++ src/utility.h | 3 ++ 8 files changed, 66 insertions(+), 145 deletions(-) diff --git a/src/camera.cpp b/src/camera.cpp index c14d0e8b..a6153214 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -249,6 +249,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize) } m_wieldnode->setPosition(wield_position); m_wieldnode->setRotation(wield_rotation); + m_wieldnode->updateLight(player->light); // Render distance feedback loop updateViewingRange(frametime); @@ -472,6 +473,7 @@ ExtrudedSpriteSceneNode::ExtrudedSpriteSceneNode( m_thickness = 0.1; m_cubemesh = NULL; m_is_cube = false; + m_light = LIGHT_MAX; } ExtrudedSpriteSceneNode::~ExtrudedSpriteSceneNode() @@ -519,6 +521,7 @@ void ExtrudedSpriteSceneNode::setSprite(video::ITexture* texture) m_meshnode->getMaterial(0).MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; m_meshnode->setVisible(true); m_is_cube = false; + updateLight(m_light); } void ExtrudedSpriteSceneNode::setCube(const TileSpec tiles[6]) @@ -546,6 +549,16 @@ void ExtrudedSpriteSceneNode::setCube(const TileSpec tiles[6]) } m_meshnode->setVisible(true); m_is_cube = true; + updateLight(m_light); +} + +void ExtrudedSpriteSceneNode::updateLight(u8 light) +{ + m_light = light; + + u8 li = decode_light(light); + video::SColor color(255,li,li,li); + setMeshVerticesColor(m_meshnode->getMesh(), color); } void ExtrudedSpriteSceneNode::removeSpriteFromCache(video::ITexture* texture) diff --git a/src/camera.h b/src/camera.h index fbee4a37..66825e37 100644 --- a/src/camera.h +++ b/src/camera.h @@ -205,6 +205,8 @@ class ExtrudedSpriteSceneNode: public scene::ISceneNode f32 getSpriteThickness() const { return m_thickness; } void setSpriteThickness(f32 thickness); + void updateLight(u8 light); + void removeSpriteFromCache(video::ITexture* texture); virtual const core::aabbox3d& getBoundingBox() const; @@ -216,6 +218,7 @@ class ExtrudedSpriteSceneNode: public scene::ISceneNode f32 m_thickness; scene::IMesh* m_cubemesh; bool m_is_cube; + u8 m_light; // internal extrusion helper methods io::path getExtrudedName(video::ITexture* texture); diff --git a/src/content_cao.cpp b/src/content_cao.cpp index dfeaea85..b6543061 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -224,22 +224,7 @@ void ItemCAO::updateLight(u8 light_at_pos) u8 li = decode_light(light_at_pos); video::SColor color(255,li,li,li); - - scene::IMesh *mesh = m_node->getMesh(); - if(mesh == NULL) - return; - - u16 mc = mesh->getMeshBufferCount(); - for(u16 j=0; jgetMeshBuffer(j); - video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices(); - u16 vc = buf->getVertexCount(); - for(u16 i=0; igetMesh(), color); } v3s16 ItemCAO::getLightPosition() @@ -430,22 +415,7 @@ void RatCAO::updateLight(u8 light_at_pos) u8 li = decode_light(light_at_pos); video::SColor color(255,li,li,li); - - scene::IMesh *mesh = m_node->getMesh(); - if(mesh == NULL) - return; - - u16 mc = mesh->getMeshBufferCount(); - for(u16 j=0; jgetMeshBuffer(j); - video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices(); - u16 vc = buf->getVertexCount(); - for(u16 i=0; igetMesh(), color); } v3s16 RatCAO::getLightPosition() @@ -601,22 +571,7 @@ void Oerkki1CAO::updateLight(u8 light_at_pos) u8 li = decode_light(light_at_pos); video::SColor color(255,li,li,li); - - scene::IMesh *mesh = m_node->getMesh(); - if(mesh == NULL) - return; - - u16 mc = mesh->getMeshBufferCount(); - for(u16 j=0; jgetMeshBuffer(j); - video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices(); - u16 vc = buf->getVertexCount(); - for(u16 i=0; igetMesh(), color); } v3s16 Oerkki1CAO::getLightPosition() @@ -833,22 +788,7 @@ void FireflyCAO::updateLight(u8 light_at_pos) u8 li = 255; video::SColor color(255,li,li,li); - - scene::IMesh *mesh = m_node->getMesh(); - if(mesh == NULL) - return; - - u16 mc = mesh->getMeshBufferCount(); - for(u16 j=0; jgetMeshBuffer(j); - video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices(); - u16 vc = buf->getVertexCount(); - for(u16 i=0; igetMesh(), color); } v3s16 FireflyCAO::getLightPosition() diff --git a/src/environment.cpp b/src/environment.cpp index 80f41f9f..ea33274d 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -1686,18 +1686,19 @@ void ClientEnvironment::step(float dtime) // Move player->move(dtime, *m_map, 100*BS); - // Update lighting on remote players on client - u8 light = LIGHT_MAX; - try{ - // Get node at head - v3s16 p = player->getLightPosition(); - MapNode n = m_map->getNode(p); - light = n.getLightBlend(getDayNightRatio()); - } - catch(InvalidPositionException &e) {} - player->updateLight(light); } + // Update lighting on all players on client + u8 light = LIGHT_MAX; + try{ + // Get node at head + v3s16 p = player->getLightPosition(); + MapNode n = m_map->getNode(p); + light = n.getLightBlend(getDayNightRatio()); + } + catch(InvalidPositionException &e) {} + player->updateLight(light); + /* Add footsteps to grass */ diff --git a/src/mapblockobject.h b/src/mapblockobject.h index 80449471..b852812e 100644 --- a/src/mapblockobject.h +++ b/src/mapblockobject.h @@ -484,20 +484,7 @@ class SignObject : public MapBlockObject u8 li = decode_light(light_at_pos); video::SColor color(255,li,li,li); - - scene::IMesh *mesh = m_node->getMesh(); - - u16 mc = mesh->getMeshBufferCount(); - for(u16 j=0; jgetMeshBuffer(j); - video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices(); - u16 vc = buf->getVertexCount(); - for(u16 i=0; igetMesh(), color); } #endif @@ -676,20 +663,7 @@ class RatObject : public MovingObject u8 li = decode_light(light_at_pos); video::SColor color(255,li,li,li); - - scene::IMesh *mesh = m_node->getMesh(); - - u16 mc = mesh->getMeshBufferCount(); - for(u16 j=0; jgetMeshBuffer(j); - video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices(); - u16 vc = buf->getVertexCount(); - for(u16 i=0; igetMesh(), color); } #endif @@ -836,20 +810,7 @@ class ItemObject : public MapBlockObject u8 li = decode_light(light_at_pos); video::SColor color(255,li,li,li); - - scene::IMesh *mesh = m_node->getMesh(); - - u16 mc = mesh->getMeshBufferCount(); - for(u16 j=0; jgetMeshBuffer(j); - video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices(); - u16 vc = buf->getVertexCount(); - for(u16 i=0; igetMesh(), color); } #endif @@ -982,20 +943,7 @@ class PlayerObject : public MovingObject u8 li = decode_light(light_at_pos); video::SColor color(255,li,li,li); - - scene::IMesh *mesh = m_node->getMesh(); - - u16 mc = mesh->getMeshBufferCount(); - for(u16 j=0; jgetMeshBuffer(j); - video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices(); - u16 vc = buf->getVertexCount(); - for(u16 i=0; igetMesh(), color); } #endif diff --git a/src/player.h b/src/player.h index 350b85e1..ce100199 100644 --- a/src/player.h +++ b/src/player.h @@ -126,7 +126,10 @@ class Player virtual bool isLocal() const = 0; - virtual void updateLight(u8 light_at_pos) {}; + virtual void updateLight(u8 light_at_pos) + { + light = light_at_pos; + } // NOTE: Use peer_id == 0 for disconnected /*virtual bool isClientConnected() { return false; } @@ -149,6 +152,8 @@ class Player bool swimming_up; bool is_frozen; + u8 light; + Inventory inventory; // Actual inventory is backed up here when creative mode is used Inventory *inventory_backup; @@ -266,25 +271,14 @@ class RemotePlayer : public Player, public scene::ISceneNode virtual void updateLight(u8 light_at_pos) { + Player::updateLight(light_at_pos); + if(m_node == NULL) return; u8 li = decode_light(light_at_pos); video::SColor color(255,li,li,li); - - scene::IMesh *mesh = m_node->getMesh(); - - u16 mc = mesh->getMeshBufferCount(); - for(u16 j=0; jgetMeshBuffer(j); - video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices(); - u16 vc = buf->getVertexCount(); - for(u16 i=0; igetMesh(), color); } void move(f32 dtime, Map &map, f32 pos_max_d); diff --git a/src/utility.cpp b/src/utility.cpp index 9c1edc8a..3c6c2f28 100644 --- a/src/utility.cpp +++ b/src/utility.cpp @@ -156,6 +156,25 @@ void mysrand(unsigned seed) next = seed; } +// Sets the color of all vertices in the mesh +void setMeshVerticesColor(scene::IMesh* mesh, video::SColor& color) +{ + if(mesh == NULL) + return; + + u16 mc = mesh->getMeshBufferCount(); + for(u16 j=0; jgetMeshBuffer(j); + video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices(); + u16 vc = buf->getVertexCount(); + for(u16 i=0; i &list, u16 d) { From 2ecd53ce09d8f20a06b057c24924a010fa2eefde Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Mon, 26 Sep 2011 15:09:04 +0300 Subject: [PATCH 26/26] Fix single-frame lag in camera yaw/pitch, tune view bobbing and add wielded tool movement when walking and tweak stuff a bit --- src/camera.cpp | 55 +++++++++++++++++++++++---- src/game.cpp | 101 +++++++++++++++++++++++++------------------------ 2 files changed, 99 insertions(+), 57 deletions(-) diff --git a/src/camera.cpp b/src/camera.cpp index a6153214..1a533049 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -126,9 +126,11 @@ void Camera::step(f32 dtime) { if (m_view_bobbing_state != 0) { - f32 offset = dtime * m_view_bobbing_speed * 0.035; + //f32 offset = dtime * m_view_bobbing_speed * 0.035; + f32 offset = dtime * m_view_bobbing_speed * 0.030; if (m_view_bobbing_state == 2) { +#if 0 // Animation is getting turned off if (m_view_bobbing_anim < 0.5) m_view_bobbing_anim -= offset; @@ -139,6 +141,29 @@ void Camera::step(f32 dtime) m_view_bobbing_anim = 0; m_view_bobbing_state = 0; } +#endif +#if 1 + // Animation is getting turned off + if(m_view_bobbing_anim < 0.25){ + m_view_bobbing_anim -= offset; + } else if(m_view_bobbing_anim > 0.75){ + m_view_bobbing_anim += offset; + } 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; + } else { + m_view_bobbing_anim -= offset; + if(m_view_bobbing_anim < 0.5) + m_view_bobbing_anim = 0.5; + } + if(m_view_bobbing_anim <= 0 || m_view_bobbing_anim >= 1 || + fabs(m_view_bobbing_anim - 0.5) < 0.01) + { + m_view_bobbing_anim = 0; + m_view_bobbing_state = 0; + } +#endif } else { @@ -183,15 +208,24 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize) #if 1 f32 bobknob = 1.2; f32 bobtmp = sin(pow(bobfrac, bobknob) * PI); + f32 bobtmp2 = cos(pow(bobfrac, bobknob) * PI); v3f bobvec = v3f( - bobdir * sin(bobfrac * PI), - 0.8 * bobtmp * bobtmp, + 0.3 * bobdir * sin(bobfrac * PI), + -0.28 * bobtmp * bobtmp, 0.); - rel_cam_pos += 0.02 * bobvec; - rel_cam_target += 0.03 * bobvec; - rel_cam_up.rotateXYBy(0.02 * bobdir * bobtmp * PI); + //rel_cam_pos += 0.2 * bobvec; + //rel_cam_target += 0.03 * bobvec; + //rel_cam_up.rotateXYBy(0.02 * bobdir * bobtmp * PI); + float f = 1.0; + rel_cam_pos += bobvec * f; + //rel_cam_target += 0.995 * bobvec * f; + rel_cam_target += bobvec * f; + rel_cam_target.Z -= 0.005 * bobvec.Z * f; + //rel_cam_target.X -= 0.005 * bobvec.X * f; + //rel_cam_target.Y -= 0.005 * bobvec.Y * f; + rel_cam_up.rotateXYBy(-0.03 * bobdir * bobtmp * PI * f); #else f32 angle_deg = 1 * bobdir * sin(bobfrac * PI); f32 angle_rad = angle_deg * PI / 180; @@ -241,12 +275,17 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize) // Euler angles are PURE EVIL, so why not use quaternions? core::quaternion quat_begin(wield_rotation * core::DEGTORAD); - core::quaternion quat_end(v3f(90, 20, -130) * core::DEGTORAD); + core::quaternion quat_end(v3f(90, -10, -130) * core::DEGTORAD); core::quaternion quat_slerp; quat_slerp.slerp(quat_begin, quat_end, sin(digfrac * PI)); quat_slerp.toEuler(wield_rotation); wield_rotation *= core::RADTODEG; } + else { + f32 bobfrac = my_modf(m_view_bobbing_anim); + wield_position.X -= sin(bobfrac*PI*2.0) * 3.0; + wield_position.Y += sin(my_modf(bobfrac*2.0)*PI) * 3.0; + } m_wieldnode->setPosition(wield_position); m_wieldnode->setRotation(wield_rotation); m_wieldnode->updateLight(player->light); @@ -557,6 +596,8 @@ void ExtrudedSpriteSceneNode::updateLight(u8 light) m_light = light; u8 li = decode_light(light); + // Set brightness one lower than incoming light + diminish_light(li); video::SColor color(255,li,li,li); setMeshVerticesColor(m_meshnode->getMesh(), color); } diff --git a/src/game.cpp b/src/game.cpp index a9966265..13b06db6 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1336,6 +1336,57 @@ void the_game( debug_stacks_print(); } + /* + Mouse and camera control + NOTE: Do this before client.setPlayerControl() to not cause a camera lag of one frame + */ + + if((device->isWindowActive() && noMenuActive()) || random_input) + { + if(!random_input) + { + // Mac OSX gets upset if this is set every frame + if(device->getCursorControl()->isVisible()) + device->getCursorControl()->setVisible(false); + } + + if(first_loop_after_window_activation){ + //std::cout<<"window active, first loop"<getMousePos().X - displaycenter.X; + s32 dy = input->getMousePos().Y - displaycenter.Y; + if(invert_mouse) + dy = -dy; + //std::cout<<"window active, pos difference "<isKeyDown(irr::KEY_UP)) + dy -= dtime * keyspeed; + if(input->isKeyDown(irr::KEY_DOWN)) + dy += dtime * keyspeed; + if(input->isKeyDown(irr::KEY_LEFT)) + dx -= dtime * keyspeed; + if(input->isKeyDown(irr::KEY_RIGHT)) + dx += dtime * keyspeed;*/ + + camera_yaw -= dx*0.2; + camera_pitch += dy*0.2; + if(camera_pitch < -89.5) camera_pitch = -89.5; + if(camera_pitch > 89.5) camera_pitch = 89.5; + } + input->setMousePos(displaycenter.X, displaycenter.Y); + } + else{ + // Mac OSX gets upset if this is set every frame + if(device->getCursorControl()->isVisible() == false) + device->getCursorControl()->setVisible(true); + + //std::cout<<"window inactive"<isWindowActive() && noMenuActive()) || random_input) - { - if(!random_input) - { - // Mac OSX gets upset if this is set every frame - if(device->getCursorControl()->isVisible()) - device->getCursorControl()->setVisible(false); - } - - if(first_loop_after_window_activation){ - //std::cout<<"window active, first loop"<getMousePos().X - displaycenter.X; - s32 dy = input->getMousePos().Y - displaycenter.Y; - if(invert_mouse) - dy = -dy; - //std::cout<<"window active, pos difference "<isKeyDown(irr::KEY_UP)) - dy -= dtime * keyspeed; - if(input->isKeyDown(irr::KEY_DOWN)) - dy += dtime * keyspeed; - if(input->isKeyDown(irr::KEY_LEFT)) - dx -= dtime * keyspeed; - if(input->isKeyDown(irr::KEY_RIGHT)) - dx += dtime * keyspeed;*/ - - camera_yaw -= dx*0.2; - camera_pitch += dy*0.2; - if(camera_pitch < -89.5) camera_pitch = -89.5; - if(camera_pitch > 89.5) camera_pitch = 89.5; - } - input->setMousePos(displaycenter.X, displaycenter.Y); - } - else{ - // Mac OSX gets upset if this is set every frame - if(device->getCursorControl()->isVisible() == false) - device->getCursorControl()->setVisible(true); - - //std::cout<<"window inactive"<