基于OSG的测试节点的构建
float sdSphere(osg::Vec3 p, float r)
{
return p.length() - r;
}
float sdPlane(osg::Vec3 p)
{
return 5.0 - p.z();
}
float sdEllipsoid(osg::Vec3 p, osg::Vec3 r)
{
float k0 = osg::componentDivide(p, r).length();
float k1 = osg::componentDivide(p, (osg::componentMultiply(r, r))).length();
return k0 * (k0 - 1.0) / k1;
}
float opSmoothUnion(float d1, float d2, float k)
{
float h = std::max(k - abs(d1 - d2), 0.0f);
return std::min(d1, d2) - h * h * 0.25 / k;
}
osg::Node* sdf_test()
{
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
int cnt = 161;
double size = 30.0;
double step = size / (double)cnt;
for (int i = 0; i < cnt; ++i)
{
osg::Vec3 ro = osg::Vec3(i * step - size * 0.5, 0.0, 0.0);
osg::Vec3 rd = osg::Vec3(0.0, 0.0, 1.0);
float t = 0.0;
for (int j = 0; j < 64; ++j) {
osg::Vec3 p = ro + rd * t;
float d = sdSphere(p - osg::Vec3(0.0, 0.0, 20), 12.0);
//d = opSmoothUnion(d, sdSphere(p - osg::Vec3(0, 0.0, 5), 3.0), 0.5);
//d = opSmoothUnion(d, sdPlane(p), 0.85);
//d = std::min(d, sdSphere(p - osg::Vec3(0, 0.0, 5), 3.0));
d = opSmoothUnion(d, sdEllipsoid(p - osg::Vec3(0.0, 0.0, 12.0), osg::Vec3(6.0, 6.0, sqrt(7.8 * 6.0))), 0.25);
//d = opSmoothUnion(d, sdSphere(p - osg::Vec3(0.0, 0.0, 13.0), 7.8), 0.25);
if(abs(d) < 0.001 || t > size)
break;
t += d;
}
if(t < size)
{
osg::Vec3 iPoint = ro + rd * t;
vertices->push_back(iPoint);
}
}
osg::ref_ptr<osg::Geometry> lgeom = new osg::Geometry;
{
lgeom->setVertexArray(vertices);
osg::Vec4Array* colors = new osg::Vec4Array;
{
for (int i = 0; i < vertices->size(); ++i)
{
osg::Vec3 cdir = vertices->at(i) - osg::Vec3(0.0, 0.0, 20.0); cdir.normalize();
if(cdir * osg::Vec3(0.0, 0.0, -1.0) < sqrt(3.0) / 2.0)
{
colors->push_back(osg::Vec4(1.0, 0.0, 0.0, 1.0)); continue;
}
colors->push_back(osg::Vec4(1.0, 1.0, 0.0, 1.0));
}
lgeom->setColorArray(colors, osg::Array::BIND_PER_VERTEX);
}
lgeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, 0, vertices->size()));
lgeom->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
}
return lgeom.release();
}
通过opSmoothUnion函数的第三个参数来调节平滑过渡的程度(0.0, 1.0),结果对比