khanat-opennel-code/code/nel/include/nel/3d/vegetable.h

204 lines
7.6 KiB
C++

// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef NL_VEGETABLE_H
#define NL_VEGETABLE_H
#include "nel/misc/types_nl.h"
#include "nel/misc/noise_value.h"
#include "nel/misc/vector.h"
#include "nel/misc/vector_2f.h"
#include "nel/misc/matrix.h"
#include "nel/3d/vegetable_uv8.h"
namespace NL3D
{
using NLMISC::CVector;
using NLMISC::CVector2f;
class CVegetableManager;
class CVegetableShape;
class CVegetableInstanceGroup;
class CVegetableInstanceGroupReserve;
// ***************************************************************************
/**
* A vegetable descriptor.
* \author Lionel Berenguier
* \author Nevrax France
* \date 2001
*/
class CVegetable
{
public:
/// Micro vegetation position against Water. Above water is the default.
enum TVegetableWater { AboveWater = 0, UnderWater, IntersectWater, VegetInfoLast };
public:
/// Name of the shape to use.
std::string ShapeName;
/// Density== Number of instance to create / m^2.
NLMISC::CNoiseValue Density; // floor(Density*surface)== nbShape to create.
/// the maximum density computed. if <0, no maximum. -1 by default.
float MaxDensity;
/// Random Scale.
NLMISC::CNoiseValue Sxy, Sz;
/// Random Orientation.
NLMISC::CNoiseValue Rx, Ry, Rz;
/// Random Bend factor.
NLMISC::CNoiseValue BendFactor;
/// Random Bend Phase.
NLMISC::CNoiseValue BendPhase;
/// Fixed Bend FrequencyFactor. NB: rounded during addInstance to the nearest NL3D_VEGETABLE_FREQUENCY_FACTOR_PREC
float BendFrequencyFactor;
/// The color to modulate the instance.
NLMISC::CNoiseColorGradient Color;
/** At which distance this vegetable will be rendered.
* NB: DistType is not managed by CVegetableManager, but by user (eg CLandscape).
*/
uint32 DistType;
public:
CVegetable();
/// \name Density Angle Factor
// @{
enum TAngleType {AngleGround=0, AngleCeiling, AngleWall};
/** set an Angle setup such that max density is when normal== K, and 0 density is when normalAngle= cosAngleMin.
* \param cosAngleMinLimit should be a cosinus angle between -1 and 1.
*/
void setAngleGround(float cosAngleMin);
/** set an Angle setup such that max density is when normal= -K, and 0 density is when normalAngle= cosAngleMax.
* \param cosAngleMinLimit should be a cosinus angle between -1 and 1.
*/
void setAngleCeiling(float cosAngleMax);
/** set an Angle setup such that max density is when normal is at (cosAngleMin+cosAngleMax)/2, and 0 density is
* when cosAngle= one of the cosAngleMin or cosAngleMax.
*/
void setAngleWall(float cosAngleMin, float cosAngleMax);
float getCosAngleMin() const {return _CosAngleMin;}
float getCosAngleMax() const {return _CosAngleMax;}
TAngleType getAngleType() const {return _AngleType;}
// @}
/** register the vegetable to the vegetable manager. do it first. used by generateInstance() and generateGroup*()
* Manager will load the shape needed for this vegetable.
*/
void registerToManager(CVegetableManager *manager);
/** generate a list of instance to create on a small ground element, according to density and noise.
* result is a list of instance to create, with random 2d position. 2d position are in range [0..1].
* caller should scale, or use it to compute real world position, and then use generateInstance() to really
* compute the instances.
*
* Warning! Use OptFastFloor()! So call must be enclosed with a OptFastFloorBegin()/OptFastFloorEnd().
*
* \param posInWorld center (approx) of the surface which generate group of vegetable
* \param surfaceNormal UNIT up vector of the surface to compare with (0,0,1), to modulate density
* \param area area of the surface, to know number of elements to generate for this surface
* \param vegetSeed "random" value which Should be different for all vegetables in the same area.
* useful if lot of different vegetable generated in same area: positions won't be generated at same place.
* \param instances the generated position of instances.
*/
void generateGroup(const CVector &posInWorld, const CVector &surfaceNormal, float area, uint vegetSeed, std::vector<CVector2f> &instances) const;
/** same as generateGroup, but with smoother density effects on border with desnity==0
* \name posInWorldAround 4 position on 4 edges around the center in folowing order:
* (0,0.5), (1,0.5), (0.5,0), (0.5,1) (in instance UV coordinates space (as returned in "instances").
*/
void generateGroupBiLinear(const CVector &posInWorld, const CVector posInWorldBorder[4], const CVector &surfaceNormal, float area, uint vegetSeed, std::vector<CVector2f> &instances) const;
/** Fast allocation reservation: you must call this before generating all your instances in an Ig:
* Add N instances of Vegetable to the reservation system.
* \param numInstances number of instances to generate (as "returned" by generateGroup()).
* \see CVegetableManager::reserveIgCompile().
*/
void reserveIgAddInstances(CVegetableInstanceGroupReserve &vegetIgReserve, TVegetableWater vegetWaterState, uint numInstances) const;
/** posInWorld should be a matrix of position + rotation (typically for surface alignement).
* FinalPos= posInWorld * noiseMatrix(scale/rot)
* If shape is Lighted:
* FinalAmbientColor= vegetManager->Ambient * modulateAmbientColor * randomColor.
* FinalDiffuseColor= vegetManager->Diffuse * modulateDiffuseColor * randomColor.
* else
* FinalAmbientColor= randomColor.
* FinalDiffuseColor= randomColor.
* If instance is in AlphaBlend/ZSort, blendDistMax is the distance where the instance is invisible (alpha==0).
* instance is added to the manager, under the instance group ig. This one must have been generated by the VegetableManager.
* \param dlmUV is the dynamic lightmap UV for this vegetable.
*/
void generateInstance(CVegetableInstanceGroup *ig, const NLMISC::CMatrix &posInWorld,
const NLMISC::CRGBAF &modulateAmbientColor, const NLMISC::CRGBAF &modulateDiffuseColor, float blendDistMax,
TVegetableWater vegetWaterState, CVegetableUV8 dlmUV) const;
void serial(NLMISC::IStream &f);
// *********************
private:
/** density is multiplied by a function f(cos angle with verticalVector), such that
* f(CosAngleMiddle)==1, and f(CosAngleMin)==f(CosAngleMax)== 0
*/
float _CosAngleMin, _CosAngleMax, _CosAngleMiddle, _OOCosAngleDist;
/// angle type setuped with setAngleMin etc...
TAngleType _AngleType;
/// the manager
CVegetableManager *_Manager;
/// shape in the manager
CVegetableShape *_VegetableShape;
/// Do the generateGroup, but take nbInst unmodulated by normal
void generateGroupEx(float nbInst, const CVector &posInWorld, const CVector &surfaceNormal, uint vegetSeed, std::vector<CVector2f> &instances) const;
// easineasout
static inline float easeInEaseOut(float x)
{
float y;
// cubic such that f(0)=0, f'(0)=0, f(1)=1, f'(1)=0.
float x2=x*x;
float x3=x2*x;
y= -2*x3 + 3*x2;
return y;
}
};
} // NL3D
#endif // NL_VEGETABLE_H
/* End of vegetable.h */