Merge branch 'fixes' into main/rendor-staging
[ryzomcore.git] / snowballs2 / client / src / landscape.cpp
blob14aba0fb7612189eebf7b65fd961e6e0a8fca257
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 // Includes
21 #include "nel/misc/types_nl.h"
23 #include <string>
24 #include <deque>
25 #include <vector>
27 #include "nel/misc/variable.h"
28 #include "nel/misc/command.h"
29 #include "nel/misc/variable.h"
30 #include "nel/misc/debug.h"
31 #include "nel/misc/path.h"
32 #include "nel/misc/i18n.h"
33 #include "nel/misc/config_file.h"
35 #include <nel/3d/u_camera.h>
36 #include <nel/3d/u_driver.h>
37 #include <nel/3d/u_text_context.h>
38 #include <nel/3d/u_instance.h>
39 #include <nel/3d/u_scene.h>
40 #include <nel/3d/u_material.h>
41 #include <nel/3d/u_landscape.h>
42 #include <nel/3d/u_instance_group.h>
43 #include <nel/3d/u_light.h>
45 #include <nel/3d/u_visual_collision_entity.h>
46 #include <nel/3d/u_visual_collision_manager.h>
48 #include "snowballs_client.h"
49 #include "pacs.h"
50 #include "commands.h"
51 #include "mouse_listener.h"
52 #include "physics.h"
53 #include "configuration.h"
54 #include "entities.h"
57 // Namespaces
60 using namespace std;
61 using namespace NLMISC;
62 using namespace NL3D;
65 // Variables
69 namespace SBCLIENT {
71 /*******************************************************************
72 * GLOBALS *
73 *******************************************************************/
75 vector<UInstanceGroup*> InstanceGroups;
76 NLMISC::CVector SunDirection;
78 /*******************************************************************
79 * LANDSCAPE *
80 *******************************************************************/
82 static UVisualCollisionEntity *_AimingEntity = NULL;
83 static ULight *_Sun = NULL;
86 // Functions
89 void cbUpdateLandscape (CConfigFile::CVar &var)
91 // -- -- split this whole thing up, lol
93 if (var.Name == "FogStart")
94 Driver->setupFog (var.asFloat (),
95 ConfigFile->getVar ("FogEnd").asFloat (),
96 CRGBA(ConfigFile->getVar ("FogColor").asInt (0),
97 ConfigFile->getVar ("FogColor").asInt (1),
98 ConfigFile->getVar ("FogColor").asInt (2)));
99 else if (var.Name == "FogEnd")
100 Driver->setupFog (ConfigFile->getVar ("FogStart").asFloat (),
101 var.asFloat (),
102 CRGBA(ConfigFile->getVar ("FogColor").asInt (0),
103 ConfigFile->getVar ("FogColor").asInt (1),
104 ConfigFile->getVar ("FogColor").asInt (2)));
105 else if (var.Name == "FogColor")
106 Driver->setupFog(
107 ConfigFile->getVar ("FogStart").asFloat (),
108 ConfigFile->getVar ("FogEnd").asFloat (),
109 CRGBA(var.asInt (0), var.asInt (1), var.asInt (2)));
110 else if (var.Name == "FogEnable")
112 Driver->enableFog(var.asBool());
113 Driver->setupFog(
114 ConfigFile->getVar("FogStart").asFloat(),
115 ConfigFile->getVar("FogEnd").asFloat(),
116 CRGBA(ConfigFile->getVar("FogColor").asInt(0),
117 ConfigFile->getVar ("FogColor").asInt(1),
118 ConfigFile->getVar ("FogColor").asInt(2)));
120 else if (var.Name == "SunAmbientColor")
122 _Sun->setAmbiant (CRGBA (var.asInt(0), var.asInt(1), var.asInt(2)));
123 Driver->setLight (0, *_Sun);
125 else if (var.Name == "SunDiffuseColor")
127 _Sun->setDiffuse (CRGBA (var.asInt(0), var.asInt(1), var.asInt(2)));
128 Driver->setLight (0, *_Sun);
130 else if (var.Name == "SunSpecularColor")
132 _Sun->setSpecular (CRGBA (var.asInt(0), var.asInt(1), var.asInt(2)));
133 Driver->setLight (0, *_Sun);
135 else if (var.Name == "SunDirection")
137 SunDirection.set (var.asFloat(0), var.asFloat(1), var.asFloat(2));
138 _Sun->setDirection (SunDirection);
139 Driver->setLight (0, *_Sun);
141 else nlwarning ("Unknown variable update %s", var.Name.c_str());
144 static float _LandscapeVision;
145 static float _LandscapeVisionInitial;
147 static void cbMoreLandscapeStuff(CConfigFile::CVar &var)
149 if (var.Name == "LandscapeTileNear")
150 Landscape->setTileNear(var.asFloat());
152 else if (var.Name == "LandscapeThreshold")
153 Landscape->setThreshold(var.asFloat());
155 else if (var.Name == "LandscapeVision")
156 _LandscapeVision = var.asFloat();
158 else if (var.Name == "LandscapeVisionInitial")
159 _LandscapeVisionInitial = var.asFloat();
161 else if (var.Name == "LandscapeReceiveShadowMap")
162 Landscape->enableReceiveShadowMap(var.asBool());
164 else nlwarning("Unknown variable update %s", var.Name.c_str());
167 void initLight()
169 // -- -- sun or whatever light, simple use, doesn't need class yet
171 _Sun = ULight::createLight();
172 nlassert(_Sun);
173 _Sun->setMode(ULight::DirectionalLight);
174 Driver->enableLight(0);
176 ConfigFile->setCallback("SunAmbientColor", cbUpdateLandscape);
177 ConfigFile->setCallback("SunDiffuseColor", cbUpdateLandscape);
178 ConfigFile->setCallback("SunSpecularColor", cbUpdateLandscape);
179 ConfigFile->setCallback("SunDirection", cbUpdateLandscape);
181 cbUpdateLandscape(ConfigFile->getVar("SunAmbientColor"));
182 cbUpdateLandscape(ConfigFile->getVar("SunDiffuseColor"));
183 cbUpdateLandscape(ConfigFile->getVar("SunSpecularColor"));
184 cbUpdateLandscape(ConfigFile->getVar("SunDirection"));
187 void releaseLight()
189 // -- -- just data
191 ConfigFile->setCallback("SunAmbientColor", NULL);
192 ConfigFile->setCallback("SunDiffuseColor", NULL);
193 ConfigFile->setCallback("SunSpecularColor", NULL);
194 ConfigFile->setCallback("SunDirection", NULL);
196 delete _Sun; _Sun = NULL;
199 void initLandscape()
204 ConfigFile->setCallback ("FogStart", cbUpdateLandscape);
205 ConfigFile->setCallback ("FogEnd", cbUpdateLandscape);
206 ConfigFile->setCallback ("FogColor", cbUpdateLandscape);
207 ConfigFile->setCallback ("FogEnable", cbUpdateLandscape);
209 cbUpdateLandscape (ConfigFile->getVar ("FogStart"));
210 cbUpdateLandscape (ConfigFile->getVar ("FogEnd"));
211 cbUpdateLandscape (ConfigFile->getVar ("FogColor"));
212 cbUpdateLandscape (ConfigFile->getVar ("FogEnable"));
218 // -- -- start of init for "instance groups loaded from config"
220 CConfigFile::CVar igv = ConfigFile->getVar("InstanceGroups");
221 for (uint32 i = 0; i < igv.size (); i++)
223 UInstanceGroup *inst = UInstanceGroup::createInstanceGroup (igv.asString (i));
224 if (inst == NULL)
226 nlwarning ("Instance group '%s' not found", igv.asString (i).c_str ());
228 else
230 inst->addToScene (*Scene);
231 InstanceGroups.push_back (inst);
237 // -- -- start of init for "landscape around camera that gets data from config"
239 // create the landscape
240 nlassert(!Landscape);
241 Landscape = Scene->createLandscape();
243 // load the bank files
244 Landscape->loadBankFiles(
245 CPath::lookup(ConfigFile->getVar("LandscapeBankName").asString()),
246 CPath::lookup(ConfigFile->getVar("LandscapeFarBankName").asString()));
247 Landscape->invalidateAllTiles();
249 // -- -- this doesn't do anything useful
250 //// setup the zone path
251 //Landscape->setZonePath(ConfigFile->getVar("DataPath").asString() + "zones/");
253 // -- -- do this when character appears or does far teleport
254 //// and eventually, load the zones around the starting point.
255 //Landscape->loadAllZonesAround (CVector(ConfigFile->getVar("StartPoint").asFloat(0),
256 // ConfigFile->getVar("StartPoint").asFloat(1),
257 // ConfigFile->getVar("StartPoint").asFloat(2)),
258 // 1000.0f);
260 // color of the landscape shadow
261 CRGBA diffuse(
262 ConfigFile->getVar("LandscapeDiffuseColor").asInt(0),
263 ConfigFile->getVar("LandscapeDiffuseColor").asInt(1),
264 ConfigFile->getVar("LandscapeDiffuseColor").asInt(2));
265 CRGBA ambient(
266 ConfigFile->getVar("LandscapeAmbiantColor").asInt(0),
267 ConfigFile->getVar("LandscapeAmbiantColor").asInt(1),
268 ConfigFile->getVar("LandscapeAmbiantColor").asInt(2));
270 Landscape->setupStaticLight(
271 diffuse, ambient,
272 ConfigFile->getVar("LandscapeMultiplyFactor").asFloat());
274 CConfiguration::setAndCallback("LandscapeReceiveShadowMap", cbMoreLandscapeStuff);
275 CConfiguration::setAndCallback("LandscapeTileNear", cbMoreLandscapeStuff);
276 CConfiguration::setAndCallback("LandscapeThreshold", cbMoreLandscapeStuff);
277 CConfiguration::setAndCallback("LandscapeVision", cbMoreLandscapeStuff);
278 CConfiguration::setAndCallback("LandscapeVisionInitial", cbMoreLandscapeStuff);
281 void releaseLandscape()
283 CConfiguration::dropCallback("LandscapeReceiveShadowMap");
284 CConfiguration::dropCallback("LandscapeTileNear");
285 CConfiguration::dropCallback("LandscapeThreshold");
286 CConfiguration::dropCallback("LandscapeVision");
287 CConfiguration::dropCallback("LandscapeVisionInitial");
290 // release config'd instancegroups
291 for (vector<UInstanceGroup *>::iterator it(InstanceGroups.begin()), end(InstanceGroups.end()); it != end; ++it)
293 (*it)->removeFromScene(*Scene);
294 delete (*it);
296 InstanceGroups.clear();
299 // -- -- release for cameralandscape
300 Scene->deleteLandscape(Landscape);
301 Landscape = NULL;
305 ConfigFile->setCallback("FogStart", NULL);
306 ConfigFile->setCallback("FogEnd", NULL);
307 ConfigFile->setCallback("FogColor", NULL);
308 ConfigFile->setCallback("FogEnable", NULL);
313 void initAiming()
315 // -- -- belongs in "camera that follows entity and can be used to aim"
316 // -- -- random note: is an extension of "camera that follows entity"
318 // Create an aiming entity
319 _AimingEntity = VisualCollisionManager->createEntity();
320 _AimingEntity->setCeilMode(true);
323 void releaseAiming()
325 // -- -- belongs in CAimingEntityCamera
327 VisualCollisionManager->deleteEntity(_AimingEntity);
330 // -- -- mix with following bit of code for higher accuracy
331 //NLMISC::CVector CSceneryMouse::getLandscape()
333 // if (_LandscapeCached) return _LandscapeCache;
334 // CViewport v = _Driver->getViewport();
335 // CVector pos, dir; -- -- random note: this code gets the landscape position where the mouse is pointing at
336 // v.getRayWithPoint(_X * v.getWidth(), _Y * v.getHeight(), pos, dir, _Camera.getMatrix(), _Camera.getFrustum());
337 // dir.normalize();
338 // dir *= 50;
339 // -- -- float rc = _Landscape->getRayCollision(pos, pos + dir);
340 // -- -- _LandscapeCache = pos + (rc * dir);
341 // _LandscapeCached = true;
342 // return _LandscapeCache;
344 // -- -- if higher than 50 or something, use code below
345 CVector getTarget(const CVector &start, const CVector &step, uint numSteps)
347 CVector testPos = start;
349 uint i;
350 for (i=0; i<numSteps; ++i)
352 CVector snapped = testPos,
353 normal;
355 // here use normal to check if we have collision
356 if (_AimingEntity->snapToGround(snapped, normal) && (testPos.z-snapped.z)*normal.z < 0.0f)
358 testPos -= step*0.5f;
359 break;
361 testPos += step;
363 return testPos;
366 CVector getTarget(CTrajectory &trajectory, TLocalTime dtSteps, uint numSteps)
368 TLocalTime t = trajectory.getStartTime();
369 CVector testPos;
371 uint i;
372 for (i=0; i<numSteps; ++i)
374 testPos = trajectory.eval(t);
375 CVector snapped = testPos,
376 normal;
378 // here use normal to check if we have collision
379 if (_AimingEntity->snapToGround(snapped, normal) && (testPos.z-snapped.z)*normal.z < 0.0f)
381 t -= (dtSteps/2);
382 testPos = trajectory.eval(t);
383 break;
385 t += dtSteps;
387 return testPos;
390 void updateLandscape()
392 // -- -- update for CCameraLandscape
393 // -- -- no need to go to snowballs mouse listener, can probly get this
394 // from a NL3D::UCamera, NLPACS::UMovePrimitive or NL3D::UInstance too.
395 // -- -- random note: make a CControllableMovePrimitiveEntityInstance or something
396 // -- -- should get the player position and not the camera position,
397 // most optimal for camera rotating around player.
399 // load the zones around the viewpoint
400 Landscape->refreshZonesAround(
401 Scene->getCam().getMatrix().getPos(), _LandscapeVision);
402 //_Landscape->refreshZonesAround(MouseListener->getViewMatrix().getPos(), 1000.0f);
405 void loadAllZonesAround()
407 /*Landscape->loadAllZonesAround(
408 Scene->getCam().getMatrix().getPos(), _LandscapeVisionInitial);*/
409 Landscape->loadAllZonesAround(Self->Position, _LandscapeVisionInitial);
413 CVector getTarget(const CVector &start, const CVector &step, uint numSteps)
415 CVector testPos = start;
417 uint i;
418 for (i=0; i<numSteps; ++i)
420 // For each step, check if the snapped position is backward the normal
421 CVector snapped = testPos;
422 CVector normal;
423 // here use normal to check if we have collision
424 if (AimingEntity->snapToGround(snapped, normal) && (testPos.z-snapped.z)*normal.z < 0.0f)
426 testPos -= step*0.5f;
427 break;
429 testPos += step;
432 return testPos;
436 // -- -- snowballs specific commands, not for the landscape class itself, it assumes using
437 // one landscape, and will get actual landscape from CSnowballsClient instance
438 // -- -- random note: there will only be one instance of CSnowballsClient,
439 // which is the class that takes care of what is currently done in client.cpp
441 //NLMISC_DYNVARIABLE(float,tilenear,"landscape tile near")
443 // if (get)
444 // *pointer = Landscape->getTileNear();
445 // else
446 // Landscape->setTileNear(*pointer);
449 //NLMISC_DYNVARIABLE(float,threshold,"landscape threshold")
451 // if (get)
452 // *pointer = Landscape->getThreshold();
453 // else
454 // Landscape->setThreshold(*pointer);
457 //// boost to
458 //NLMISC_COMMAND(boost,"switch landscape parameters between high speed and high quality","0|1")
460 // if (args.size() != 1 ) return false;
461 // if ( args[0]=="1" )
462 // {
463 // ICommand::execute( "tilenear 5", CommandsLog);
464 // ICommand::execute( "threshold 1", CommandsLog);
465 // }
466 // else
467 // {
468 // ICommand::execute( "tilenear 100", CommandsLog);
469 // ICommand::execute( "threshold 0.01", CommandsLog);
470 // }
471 // return true;
475 NLMISC_COMMAND(add_ig, "add instance group", "name")
477 if (args.size() != 1 ) return false;
478 UInstanceGroup *inst = UInstanceGroup::createInstanceGroup(args[0]);
479 if (inst == NULL) nlwarning("Instance group '%s' not found", args[0].c_str());
480 else
482 inst->addToScene(*Scene);
483 InstanceGroups.push_back(inst);
485 return true;
490 } /* namespace SBCLIENT */
492 /* end of file */