1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
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.
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/>.
21 #include "nel/misc/types_nl.h"
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"
51 #include "mouse_listener.h"
53 #include "configuration.h"
61 using namespace NLMISC
;
71 /*******************************************************************
73 *******************************************************************/
75 vector
<UInstanceGroup
*> InstanceGroups
;
76 NLMISC::CVector SunDirection
;
78 /*******************************************************************
80 *******************************************************************/
82 static UVisualCollisionEntity
*_AimingEntity
= NULL
;
83 static ULight
*_Sun
= NULL
;
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 (),
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")
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());
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());
169 // -- -- sun or whatever light, simple use, doesn't need class yet
171 _Sun
= ULight::createLight();
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"));
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
;
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
));
226 nlwarning ("Instance group '%s' not found", igv
.asString (i
).c_str ());
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)),
260 // color of the landscape shadow
262 ConfigFile
->getVar("LandscapeDiffuseColor").asInt(0),
263 ConfigFile
->getVar("LandscapeDiffuseColor").asInt(1),
264 ConfigFile
->getVar("LandscapeDiffuseColor").asInt(2));
266 ConfigFile
->getVar("LandscapeAmbiantColor").asInt(0),
267 ConfigFile
->getVar("LandscapeAmbiantColor").asInt(1),
268 ConfigFile
->getVar("LandscapeAmbiantColor").asInt(2));
270 Landscape
->setupStaticLight(
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
);
296 InstanceGroups
.clear();
299 // -- -- release for cameralandscape
300 Scene
->deleteLandscape(Landscape
);
305 ConfigFile
->setCallback("FogStart", NULL
);
306 ConfigFile
->setCallback("FogEnd", NULL
);
307 ConfigFile
->setCallback("FogColor", NULL
);
308 ConfigFile
->setCallback("FogEnable", NULL
);
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);
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());
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
;
350 for (i
=0; i
<numSteps
; ++i
)
352 CVector snapped
= testPos
,
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
;
366 CVector
getTarget(CTrajectory
&trajectory
, TLocalTime dtSteps
, uint numSteps
)
368 TLocalTime t
= trajectory
.getStartTime();
372 for (i
=0; i
<numSteps
; ++i
)
374 testPos
= trajectory
.eval(t
);
375 CVector snapped
= testPos
,
378 // here use normal to check if we have collision
379 if (_AimingEntity
->snapToGround(snapped
, normal
) && (testPos
.z
-snapped
.z
)*normal
.z
< 0.0f
)
382 testPos
= trajectory
.eval(t
);
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;
418 for (i=0; i<numSteps; ++i)
420 // For each step, check if the snapped position is backward the normal
421 CVector snapped = testPos;
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;
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")
444 // *pointer = Landscape->getTileNear();
446 // Landscape->setTileNear(*pointer);
449 //NLMISC_DYNVARIABLE(float,threshold,"landscape threshold")
452 // *pointer = Landscape->getThreshold();
454 // Landscape->setThreshold(*pointer);
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" )
463 // ICommand::execute( "tilenear 5", CommandsLog);
464 // ICommand::execute( "threshold 1", CommandsLog);
468 // ICommand::execute( "tilenear 100", CommandsLog);
469 // ICommand::execute( "threshold 0.01", CommandsLog);
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());
482 inst
->addToScene(*Scene
);
483 InstanceGroups
.push_back(inst
);
490 } /* namespace SBCLIENT */