303 lines
7.4 KiB
C++
303 lines
7.4 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/>.
|
|
|
|
#include "std3d.h"
|
|
|
|
#include "nel/3d/ps_dot.h"
|
|
#include "nel/3d/ps_macro.h"
|
|
#include "nel/3d/ps_iterator.h"
|
|
#include "nel/3d/driver.h"
|
|
#include "nel/3d/particle_system.h"
|
|
#include "nel/misc/fast_mem.h"
|
|
|
|
namespace NL3D
|
|
{
|
|
|
|
static const uint dotBufSize = 1024; // size used for point particles batching
|
|
|
|
|
|
///////////////////////////
|
|
// CPSDot implementation //
|
|
///////////////////////////
|
|
|
|
/// static members
|
|
CVertexBuffer CPSDot::_DotVb;
|
|
CVertexBuffer CPSDot::_DotVbColor;
|
|
|
|
|
|
///===================================================================
|
|
template <class T>
|
|
inline void DrawDot(T it,
|
|
CVertexBuffer &vb,
|
|
CPSAttribMaker<NLMISC::CRGBA> *colorScheme,
|
|
uint leftToDo,
|
|
CPSLocated *owner,
|
|
CMaterial &mat,
|
|
IDriver *driver,
|
|
uint32 srcStep
|
|
)
|
|
{
|
|
NL_PS_FUNC(DrawDot)
|
|
nlassert(leftToDo != 0);
|
|
const uint total = leftToDo;
|
|
T itEnd;
|
|
if (colorScheme)
|
|
{
|
|
// compute the colors
|
|
colorScheme->setColorType(driver->getVertexColorFormat());
|
|
}
|
|
do
|
|
{
|
|
uint toProcess = leftToDo < dotBufSize ? leftToDo : dotBufSize;
|
|
vb.setNumVertices(toProcess); // because of volatile vb copy, indicate the numebr of vertices to copy
|
|
{
|
|
CVertexBufferReadWrite vba;
|
|
vb.lock (vba);
|
|
if (colorScheme)
|
|
{
|
|
// compute the colors
|
|
colorScheme->make(owner,
|
|
total - leftToDo,
|
|
vba.getColorPointer(),
|
|
vb.getVertexSize(),
|
|
toProcess,
|
|
false,
|
|
srcStep
|
|
);
|
|
|
|
itEnd = it + toProcess;
|
|
uint8 *currPos = (uint8 *) vba.getVertexCoordPointer();
|
|
uint32 stride = vb.getVertexSize();
|
|
do
|
|
{
|
|
CHECK_VERTEX_BUFFER(vb, currPos);
|
|
*((CVector *) currPos) = *it;
|
|
++it ;
|
|
currPos += stride;
|
|
}
|
|
while (it != itEnd);
|
|
}
|
|
else if (srcStep == (1 << 16)) // make sure we haven't got auto-lod and that the step is 1.0
|
|
{
|
|
// there's no color information in the buffer, so we can copy it directly
|
|
NLMISC::CFastMem::memcpy(vba.getVertexCoordPointer(), &(*it), sizeof(NLMISC::CVector) * toProcess);
|
|
it += toProcess;
|
|
}
|
|
else
|
|
{
|
|
itEnd = it + toProcess;
|
|
uint8 *currPos = (uint8 *) vba.getVertexCoordPointer();
|
|
do
|
|
{
|
|
CHECK_VERTEX_BUFFER(vb, currPos);
|
|
*((CVector *) currPos) = *it;
|
|
++it ;
|
|
currPos += sizeof(float[3]);
|
|
}
|
|
while (it != itEnd);
|
|
}
|
|
}
|
|
driver->activeVertexBuffer(vb);
|
|
driver->renderRawPoints(mat, 0, toProcess);
|
|
|
|
leftToDo -= toProcess;
|
|
}
|
|
while (leftToDo);
|
|
}
|
|
|
|
|
|
///===================================================================
|
|
void CPSDot::draw(bool opaque)
|
|
{
|
|
// if (!FilterPS[0]) return;
|
|
NL_PS_FUNC(CPSDot_draw)
|
|
PARTICLES_CHECK_MEM;
|
|
if (!_Owner->getSize()) return;
|
|
|
|
uint32 step;
|
|
uint numToProcess;
|
|
computeSrcStep(step, numToProcess);
|
|
if (!numToProcess) return;
|
|
|
|
_Owner->incrementNbDrawnParticles(numToProcess); // for benchmark purpose
|
|
setupDriverModelMatrix();
|
|
IDriver *driver = getDriver();
|
|
CVertexBuffer &vb = _ColorScheme ? _DotVbColor : _DotVb;
|
|
|
|
|
|
|
|
/// update the material if the global color of the system is variable
|
|
CParticleSystem &ps = *(_Owner->getOwner());
|
|
if (_ColorScheme == NULL)
|
|
{
|
|
NLMISC::CRGBA col;
|
|
if (ps.getForceGlobalColorLightingFlag() || usesGlobalColorLighting())
|
|
{
|
|
col.modulateFromColor(ps.getGlobalColorLighted(), _Color);
|
|
}
|
|
else if (ps.getColorAttenuationScheme() != NULL || ps.isUserColorUsed())
|
|
{
|
|
col.modulateFromColor(ps.getGlobalColor(), _Color);
|
|
}
|
|
else
|
|
{
|
|
col = _Color;
|
|
}
|
|
_Mat.setColor(col);
|
|
forceTexturedMaterialStages(0);
|
|
}
|
|
else
|
|
{
|
|
forceTexturedMaterialStages(1);
|
|
if (ps.getForceGlobalColorLightingFlag() || usesGlobalColorLighting())
|
|
{
|
|
_Mat.texConstantColor(0, ps.getGlobalColorLighted());
|
|
}
|
|
else
|
|
{
|
|
_Mat.texConstantColor(0, ps.getGlobalColor());
|
|
}
|
|
SetupModulatedStage(_Mat, 0, CMaterial::Diffuse, CMaterial::Constant);
|
|
}
|
|
//////
|
|
|
|
|
|
|
|
// Use the right drawing routine (auto-lod and non auto-lod)
|
|
if (step == (1 << 16))
|
|
{
|
|
DrawDot(_Owner->getPos().begin(),
|
|
vb,
|
|
_ColorScheme,
|
|
numToProcess,
|
|
_Owner,
|
|
_Mat,
|
|
driver,
|
|
step
|
|
);
|
|
}
|
|
else
|
|
{
|
|
DrawDot(TIteratorVectStep1616(_Owner->getPos().begin(), 0, step),
|
|
vb,
|
|
_ColorScheme,
|
|
numToProcess,
|
|
_Owner,
|
|
_Mat,
|
|
driver,
|
|
step
|
|
);
|
|
}
|
|
|
|
PARTICLES_CHECK_MEM;
|
|
}
|
|
|
|
|
|
///===================================================================
|
|
/// init the vertex buffers
|
|
void CPSDot::initVertexBuffers()
|
|
{
|
|
NL_PS_FUNC(CPSDot_initVertexBuffers)
|
|
_DotVb.setName("CPSDot::_DotVb");
|
|
_DotVb.setPreferredMemory(CVertexBuffer::AGPVolatile, false);
|
|
_DotVb.setVertexFormat(CVertexBuffer::PositionFlag);
|
|
_DotVb.setNumVertices(dotBufSize);
|
|
_DotVbColor.setVertexFormat(CVertexBuffer::PositionFlag | CVertexBuffer::PrimaryColorFlag);
|
|
_DotVbColor.setPreferredMemory(CVertexBuffer::AGPVolatile, true); // keep local mem because of interleaved fill
|
|
_DotVbColor.setNumVertices(dotBufSize);
|
|
_DotVbColor.setName("CPSDot::_DotVbColor");
|
|
|
|
}
|
|
|
|
///===================================================================
|
|
void CPSDot::init(void)
|
|
{
|
|
NL_PS_FUNC(CPSDot_init)
|
|
_Mat.setLighting(false);
|
|
_Mat.setZFunc(CMaterial::less);
|
|
|
|
updateMatAndVbForColor();
|
|
}
|
|
|
|
///===================================================================
|
|
uint32 CPSDot::getNumWantedTris() const
|
|
{
|
|
NL_PS_FUNC(CPSDot_getNumWantedTris)
|
|
nlassert(_Owner);
|
|
//return _Owner->getMaxSize();
|
|
return _Owner->getSize();
|
|
}
|
|
|
|
///===================================================================
|
|
void CPSDot::newElement(const CPSEmitterInfo &info)
|
|
{
|
|
NL_PS_FUNC(CPSDot_newElement)
|
|
newColorElement(info);
|
|
}
|
|
|
|
///===================================================================
|
|
void CPSDot::deleteElement(uint32 index)
|
|
{
|
|
NL_PS_FUNC(CPSDot_deleteElement)
|
|
deleteColorElement(index);
|
|
}
|
|
|
|
///===================================================================
|
|
void CPSDot::updateMatAndVbForColor(void)
|
|
{
|
|
NL_PS_FUNC(CPSDot_updateMatAndVbForColor)
|
|
}
|
|
|
|
///===================================================================
|
|
bool CPSDot::hasTransparentFaces(void)
|
|
{
|
|
NL_PS_FUNC(CPSDot_hasTransparentFaces)
|
|
return getBlendingMode() != CPSMaterial::alphaTest ;
|
|
}
|
|
|
|
///===================================================================
|
|
bool CPSDot::hasOpaqueFaces(void)
|
|
{
|
|
NL_PS_FUNC(CPSDot_hasOpaqueFaces)
|
|
return !hasTransparentFaces();
|
|
}
|
|
|
|
///===================================================================
|
|
void CPSDot::resize(uint32 size)
|
|
{
|
|
NL_PS_FUNC(CPSDot_resize)
|
|
nlassert(size < (1 << 16));
|
|
resizeColor(size);
|
|
}
|
|
|
|
///===================================================================
|
|
void CPSDot::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
|
|
{
|
|
NL_PS_FUNC(CPSDot_IStream )
|
|
|
|
f.serialVersion(1);
|
|
|
|
|
|
CPSParticle::serial(f);
|
|
CPSColoredParticle::serialColorScheme(f);
|
|
serialMaterial(f);
|
|
if (f.isReading())
|
|
{
|
|
init();
|
|
}
|
|
}
|
|
|
|
} // NL3D
|