// NeL - MMORPG Framework
// 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 .
#ifndef NL_PLANE_BASIS_MAKER_H
#define NL_PLANE_BASIS_MAKER_H
#include "nel/misc/types_nl.h"
#include "nel/3d/ps_attrib_maker_template.h"
#include "nel/3d/ps_attrib_maker_bin_op.h"
#include "nel/3d/ps_plane_basis.h"
#include "nel/misc/fast_floor.h"
#include "nel/misc/object_vector.h"
namespace NL3D {
template <>
inline const char *CPSAttribMaker::getType() { return "CPlaneBasis";}
/** these are some attribute makers for plane_basis
* This is a plane basis class. It just blend between 2 plane by linearly interpolating the normal
* (non sampled version)
*/
class CPSPlaneBasisBlender : public CPSValueBlender
{
public:
NLMISC_DECLARE_CLASS(CPSPlaneBasisBlender);
CPSPlaneBasisBlender(const CPlaneBasis &startBasis = CPlaneBasis(NLMISC::CVector::I), const CPlaneBasis &endBasis = CPlaneBasis(NLMISC::CVector::J), float nbCycles = 1.0f) : CPSValueBlender(nbCycles)
{
_F.setValues(startBasis, endBasis);
}
CPSAttribMakerBase *clone() const { return new CPSPlaneBasisBlender(*this); }
};
/// This is a PlaneBasis gradient class
class CPSPlaneBasisGradient : public CPSValueGradient
{
public:
NLMISC_DECLARE_CLASS(CPSPlaneBasisGradient);
/**
* Construct the value gradient blender by passing a pointer to a float table.
* \param nbStages The result is sampled into a table by linearly interpolating values. This give the number of step between each value
* \param nbCycles : The nb of time the pattern is repeated during particle life. see ps_attrib_maker.h
*/
CPSPlaneBasisGradient(const CPlaneBasis *basisTab = CPSPlaneBasisGradient::DefaultPlaneBasisTab
, uint32 nbValues = 2, uint32 nbStages = 16, float nbCycles = 1.0f) : CPSValueGradient(nbCycles)
{
_F.setValues(basisTab, nbValues, nbStages);
}
CPSAttribMakerBase *clone() const { return new CPSPlaneBasisGradient(*this); }
static CPlaneBasis DefaultPlaneBasisTab[];
};
/** this is a 'follow direction' plane basis maker
* It set the plane basis to have its normal in the same direction than speed of the located
* The cycle param has no effect o the direction
*/
class CPSPlaneBasisFollowSpeed : public CPSAttribMaker
{
public:
enum TProjectionPlane { NoProjection = 0, XY, XZ, YZ, ProjectionPlaneLast /* enum counter */ };
public:
CPSPlaneBasisFollowSpeed() : CPSAttribMaker(1), _ProjectionPlane(NoProjection) {}
/// compute one value of the attribute for the given index
virtual CPlaneBasis get(CPSLocated *loc, uint32 index);
virtual CPlaneBasis get(const CPSEmitterInfo &infos);
/** Fill tab with an attribute by using the given stride. It fills numAttrib attributes.
* \param loc the 'located' that hold the 'located bindable' that need an attribute to be filled
* \param startIndex usually 0, it gives the index of the first element in the located
*/
virtual void *make(CPSLocated *loc,
uint32 startIndex,
void *tab,
uint32 stride,
uint32 numAttrib,
bool enableNoCopy = false,
uint32 srcStep = (1 << 16),
bool forceClampEntry = false
) const;
/** The same as make, but it replicate each attribute 4 times, thus filling 4*numAttrib. Useful for facelookat and the like
* \see make()
*/
virtual void make4(CPSLocated *loc,
uint32 startIndex,
void *tab,
uint32 stride,
uint32 numAttrib,
uint32 srcStep = (1 << 16)
) const;
/** the same as make4, but with nbReplicate replication isntead of 4
* \see make4
*/
virtual void makeN(CPSLocated *loc,
uint32 startIndex,
void *tab,
uint32 stride,
uint32 numAttrib,
uint32 nbReplicate,
uint32 srcStep = (1 << 16)
) const;
NLMISC_DECLARE_CLASS(CPSPlaneBasisFollowSpeed);
/// serialization
virtual void serial(NLMISC::IStream &f) throw(NLMISC::EStream)
{
// version 2 : added projection plane
// version 1 : nothing to save here
sint ver = f.serialVersion(2);
if (ver >= 2)
{
f.serialEnum(_ProjectionPlane);
}
else
{
_ProjectionPlane = NoProjection;
}
}
CPSAttribMakerBase *clone() const { return new CPSPlaneBasisFollowSpeed(*this); }
//
TProjectionPlane getProjectionPlane() const { return _ProjectionPlane; }
void setProjectionPlane(TProjectionPlane pp) { _ProjectionPlane = pp; }
private:
TProjectionPlane _ProjectionPlane;
};
/** this memorize value by applying some function based on the emitter. For a particle's attribute, each particle has its
* own value memorized
* You MUST called setScheme (from CPSAttribMakerMemory) to tell how the value will be generated
*/
class CPSPlaneBasisMemory : public CPSAttribMakerMemory
{
public:
CPSPlaneBasisMemory() { setDefaultValue(CPlaneBasis(NLMISC::CVector::K)); }
NLMISC_DECLARE_CLASS(CPSPlaneBasisMemory);
CPSAttribMakerBase *clone() const { return new CPSPlaneBasisMemory(*this); }
};
/** An attribute maker whose output if the result of a binary op on plane basis
*
*/
class CPSPlaneBasisBinOp : public CPSAttribMakerBinOp
{
public:
NLMISC_DECLARE_CLASS(CPSPlaneBasisBinOp);
CPSAttribMakerBase *clone() const { return new CPSPlaneBasisBinOp(*this); }
};
// a functor object that produce basis by applying a rotation over a fixed axis
class CSpinnerFunctor
{
public:
CSpinnerFunctor();
const CPlaneBasis &operator()(float date) const { return _PBTab[NLMISC::OptFastFloor(date * _NbSamples)]; }
/// set the rotation axis
void setAxis(const NLMISC::CVector &axis);
/// get the rotation axis
const NLMISC::CVector getAxis(void) const { return _Axis;}
/// set the number of samples for the rotation
void setNumSamples(uint32 nbSamples);
/// get the number of samples for the rotation
uint32 getNumSamples(void) const;
/// serial this object
void serial(NLMISC::IStream &f) throw(NLMISC::EStream);
protected:
CPSVector::V _PBTab;
uint32 _NbSamples;
NLMISC::CVector _Axis;
/// update the samples tab
void updateSamples(void);
};
/// this is a spinner : this compute a basis by applying a rotation over the given axis
// nb : default init is done with nb samples = 0, so must set a number of samples that is > 0 before use
class CPSBasisSpinner : public CPSAttribMakerT
{
public:
CPSBasisSpinner() : CPSAttribMakerT(1) {}
NLMISC_DECLARE_CLASS(CPSBasisSpinner);
CPSAttribMakerBase *clone() const { return new CPSBasisSpinner(*this); }
};
} // NL3D
#endif // NL_PLANE_BASIS_MAKER_H
/* End of plane_basis_maker.h */