I'd love vertex colors with alpha working on the drawIndexedPrimitiveList aswell. I mean of course color works, but alpha doesn't. For segmented lines, its not so hard to program.
In fact I have a snippet. There is this node that someone made long time ago, CIndexedPrimitiveNode and you can use it with the following function to make really long lines from an array of vector3df's. Unfortunately as it looks I've removed the dottet option, but if you try, it's really not that hard
EDIT: Gradient colors work of course, aswell as antialiasing.
For an implementation with gradient colors I have another function, where velocity represents color, but you also need an HSV to RGB function, I'll post both below... Also it takes core::array< core::array<f64> > as input where the inner array is just triplets of f64's instead of vector3df's
Code: Select all
scene::ISceneNode* makeLine(core::array<core::vector3df> positions, video::SColor color, f32 thickness)
{
scene::ISceneNode* returnNode = smgr->addEmptySceneNode();
u32 originalSize = 2000;
u32 SegmentsNeeded = core::ceil32( ((f32)positions.size()/(f32)originalSize) );
u32 SegmentSize = 2000;
u32 finishedSegments = 2000;
if(SegmentsNeeded == 1)
{
SegmentSize = positions.size();
finishedSegments = positions.size();
}
for(u32 i=0; i<SegmentsNeeded; i++)
{
scene::SMeshBuffer *segmentBuffer = new scene::SMeshBuffer();
for(u32 j=0; j<SegmentSize; j++)
{
segmentBuffer->Indices.push_back(j);
if(j !=0 && j != positions.size() - 1)
segmentBuffer->Indices.push_back(j);
segmentBuffer->Vertices.push_back(video::S3DVertex(
positions[i*originalSize+j].X,
positions[i*originalSize+j].Y,
positions[i*originalSize+j].Z,
1,1,1,
color,
1,1));
}
segmentBuffer->getMaterial().Thickness = thickness;
CIndexedPrimitiveNode* segNode = new CIndexedPrimitiveNode(returnNode,smgr,-1,segmentBuffer,
segmentBuffer->Indices.size()/2,
scene::EPT_LINES);
segNode->setMaterialFlag(video::EMF_LIGHTING, false);
segNode->setMaterialFlag(video::EMF_BACK_FACE_CULLING, false);
if(finishedSegments + 2000 < positions.size())
{
finishedSegments += 2000;
}
else
{
u32 remainder = positions.size() - finishedSegments;
SegmentSize = remainder;
}
}
return returnNode;
}
Code: Select all
#include "IndexedPrimitiveNode.h"
#include "ISceneManager.h"
#include "IVideoDriver.h"
using namespace irr;
using namespace scene;
//
CIndexedPrimitiveNode::CIndexedPrimitiveNode(irr::scene::ISceneNode* parent,
irr::scene::ISceneManager* mgr,
irr::s32 id,
scene::SMeshBuffer* pMesh,
irr::u32 primitiveCount,
irr::scene::E_PRIMITIVE_TYPE primitiveType) : scene::ISceneNode(parent,
mgr,id),
m_pMesh(pMesh),
m_primitiveCount(primitiveCount),
m_primitiveType(primitiveType)
{
this->setAutomaticCulling(EAC_OFF);
//pMesh->grab();
//m_primitiveType = scene::EPT_LINES;
}
//
CIndexedPrimitiveNode::~CIndexedPrimitiveNode()
{
m_pMesh->drop();
//this->remove();
}
//
void CIndexedPrimitiveNode::OnRegisterSceneNode()
{
if (IsVisible)
SceneManager->registerNodeForRendering(this, ESNRP_SOLID);
ISceneNode::OnRegisterSceneNode();
}
//
void CIndexedPrimitiveNode::render()
{
if (!m_pMesh->getVertexCount() || !m_pMesh->getIndexCount()) return;
video::IVideoDriver* driver = SceneManager->getVideoDriver();
driver->setMaterial(m_pMesh->getMaterial());
driver->setTransform(video::ETS_WORLD,AbsoluteTransformation);
driver->drawVertexPrimitiveList(m_pMesh->getVertices(),
m_pMesh->getVertexCount(),
m_pMesh->getIndices(),
m_primitiveCount,
m_pMesh->getVertexType(),
m_primitiveType,
m_pMesh->getIndexType());
}
//
const core::aabbox3d<f32>& CIndexedPrimitiveNode::getBoundingBox() const
{
return m_pMesh->getBoundingBox();
}
//
irr::u32 CIndexedPrimitiveNode::getMaterialCount() const
{
return 1;
}
//
irr::video::SMaterial& CIndexedPrimitiveNode::getMaterial(irr::u32 i)
{
return m_pMesh->getMaterial();
}
Code: Select all
#pragma once
#include <ISceneNode.h>
#include "CMeshBuffer.h"
//////////////////////////////////////////////////////////////////////////////////
//Frei nach http://irrlicht.sourceforge.net/docu/example003.html
//
class CIndexedPrimitiveNode : public irr::scene::ISceneNode
{
public:
//
CIndexedPrimitiveNode(irr::scene::ISceneNode* parent,
irr::scene::ISceneManager* mgr,
irr::s32 id,
irr::scene::SMeshBuffer* pMesh,
irr::u32 primitiveCount,
irr::scene::E_PRIMITIVE_TYPE primitiveType);
~CIndexedPrimitiveNode();
//
void setNewMesh(irr::scene::SMeshBuffer* pMesh,irr::u32 primitiveCount)
{
m_pMesh->drop();
m_pMesh = pMesh;
m_pMesh->grab();
m_primitiveCount = primitiveCount;
}
//
void setPrimitiveType(irr::scene::E_PRIMITIVE_TYPE type) { m_primitiveType = type; }
//zu ¸berschreiben aus Basisklasse
virtual void OnRegisterSceneNode();
//zu ¸berschreiben aus Basisklasse
virtual void render();
//zu ¸berschreiben aus Basisklasse
virtual const irr::core::aabbox3d<irr::f32>& getBoundingBox() const;
//zu ¸berschreiben aus Basisklasse
virtual irr::u32 getMaterialCount() const;
//zu ¸berschreiben aus Basisklasse
virtual irr::video::SMaterial& getMaterial(irr::u32 i);
private:
//das zu rendernde Mesh samt Material
irr::scene::SMeshBuffer* m_pMesh;
//der gew‰hlte Primitiv-Typ
irr::scene::E_PRIMITIVE_TYPE m_primitiveType;
//Anzahl der zu rendernden Primitive
irr::u32 m_primitiveCount;
};
Code: Select all
scene::ISceneNode* makeLineDouble(core::array< core::array<f64> > positions, core::array< core::array<f64> > velocity, video::SColor color, f32 thickness)
{
scene::ISceneNode* returnNode = smgr->addEmptySceneNode();
u32 originalSize = 2000;
u32 SegmentsNeeded = core::ceil32( ((f32)positions.size()/(f32)originalSize) );
u32 SegmentSize = 2000;
u32 finishedSegments = 2000;
if(SegmentsNeeded == 1)
{
SegmentSize = positions.size();
finishedSegments = positions.size();
}
f64 max = 0;
for(u32 v=0; v<velocity.size(); v++)
{
f64 current = mag(velocity[v]);
if(current > max)
max = current;
}
for(u32 i=0; i<SegmentsNeeded; i++)
{
scene::SMeshBuffer *segmentBuffer = new scene::SMeshBuffer();
for(u32 j=0; j<SegmentSize; j++)
{
segmentBuffer->Indices.push_back(j);
if(j !=0 && j != positions.size() - 1)
segmentBuffer->Indices.push_back(j);
f64 currentVel = mag(velocity[i*originalSize+j]);
f64 percentVel = currentVel/max;
f32 red,green,blue;
HSVtoRGB(&red,&green,&blue,percentVel*360,1,1);
video::SColor color3 = video::SColor(255,red*255,green*255,blue*255);
segmentBuffer->Vertices.push_back(video::S3DVertex(
positions[i*originalSize+j][0]/scaleF,
positions[i*originalSize+j][1]/scaleF,
positions[i*originalSize+j][2]/scaleF,
1,1,1,
color3,
1,1));
}
segmentBuffer->getMaterial().Thickness = thickness;
CIndexedPrimitiveNode* segNode = new CIndexedPrimitiveNode(returnNode,smgr,-1,segmentBuffer,
segmentBuffer->Indices.size()/2,
scene::EPT_LINES);
segNode->setMaterialFlag(video::EMF_LIGHTING, false);
segNode->setMaterialFlag(video::EMF_BACK_FACE_CULLING, false);
if(finishedSegments + 2000 < positions.size())
{
finishedSegments += 2000;
}
else
{
u32 remainder = positions.size() - finishedSegments;
SegmentSize = remainder;
}
}
return returnNode;
}
Code: Select all
void HSVtoRGB( float *r, float *g, float *b, float h, float s, float v )
{
int i;
float f, p, q, t;
if( s == 0 ) {
// achromatic (grey)
*r = *g = *b = v;
return;
}
h /= 60; // sector 0 to 5
i = floor( h );
f = h - i; // factorial part of h
p = v * ( 1 - s );
q = v * ( 1 - s * f );
t = v * ( 1 - s * ( 1 - f ) );
switch( i ) {
case 0:
*r = v;
*g = t;
*b = p;
break;
case 1:
*r = q;
*g = v;
*b = p;
break;
case 2:
*r = p;
*g = v;
*b = t;
break;
case 3:
*r = p;
*g = q;
*b = v;
break;
case 4:
*r = t;
*g = p;
*b = v;
break;
default: // case 5:
*r = v;
*g = p;
*b = q;
break;
}
}