DYTSrouce/src/effects/DashedLine.cpp
2025-01-04 12:12:51 +08:00

166 lines
4.5 KiB
C++
Raw Blame History

#include "effects/DashedLine.h"
#include <osg/BlendFunc>
#include <osg/Material>
#include <osg/Texture2D>
#include <osg/ShapeDrawable>
#include <osg/Group>
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osg/Shader>
#include <osg/Program>
#include <osg/Uniform>
#include "viewer/OsgViewer.h"
DashedLine::DashedLine(const std::string& path)
: txturePath_(path) {
}
DashedLine::~DashedLine(void)
{
}
void DashedLine::Render(double dt) {
if (timeUniform_) {
timeUniform_->set(static_cast<float>(dt * 0.1));
}
}
void DashedLine::InitGeode() {
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
addChild(geode);
CreateTexturedCone(geode);
}
void DashedLine::Destory() {
OnDestroy();
}
void DashedLine::SetStart(const osg::Vec3& start) {
if (start == start_) {
return;
}
start_ = start;
UpdateRotaion();
}
void DashedLine::SetEnd(const osg::Vec3& end) {
if (end == end_) {
return;
}
end_ = end;
UpdateRotaion();
}
void DashedLine::SetForward(const osg::Vec3& start, const osg::Vec3& end) {
if (start == start_ && end == end_) {
return;
}
start_ = start;
end_ = end;
UpdateRotaion();
}
void DashedLine::SetRadius(float radius) {
if (radius == radius_) {
return;
}
radius_ = radius;
if (cylinder_) {
cylinder_->setRadius(radius);
}
UpdateRotaion();
}
void DashedLine::SetBaseColor(const osg::Vec4& color) {
baseColor_ = color;
if (baseColorUniform_) {
baseColorUniform_->set(color);
}
}
void DashedLine::CreateTexturedCone(osg::Geode* geode) {
cylinder_ = new osg::Cylinder(osg::Vec3(0.0f, 0.0f, 0.0f), radius_, 1.0f);
cylinderDrawable_ = new osg::ShapeDrawable(cylinder_);
geode->addDrawable(cylinderDrawable_);
osg::Texture2D* texture = new osg::Texture2D;
texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR);
texture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);
texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT);
texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT);
osg::Image* image = osgDB::readImageFile(txturePath_);
texture->setImage(image);
osg::ref_ptr<osg::Shader> vertexShader = new osg::Shader(osg::Shader::VERTEX);
vertexShader->setShaderSource(
"#version 330\n"
"in vec4 osg_Vertex;\n"
"in vec2 osg_MultiTexCoord0;\n"
"uniform mat4 osg_ModelViewProjectionMatrix;\n"//<2F><>ǰOSG<53><47><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĺ۲<C4B9><DBB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
"uniform float time;\n"
"out vec2 texCoord;\n"
"void main()\n"
"{\n"
" gl_Position = osg_ModelViewProjectionMatrix * osg_Vertex;\n"
" texCoord = osg_MultiTexCoord0 + vec2(0.0, time);\n"
"}\n"
);
osg::ref_ptr<osg::Shader> fragmentShader = new osg::Shader(osg::Shader::FRAGMENT);
fragmentShader->setShaderSource(
"#version 330\n"
"in vec2 texCoord;\n"
"uniform sampler2D texture;\n"
"uniform vec4 baseColor;\n"
"out vec4 fragColor;\n"
"void main()\n"
"{\n"
" vec4 color = texture2D(texture, texCoord);\n"
" fragColor = clamp(texture2D(texture, texCoord) * baseColor + vec4(0,0,0, 0.2), 0.0, 1.0);\n"
"}\n"
);
osg::StateSet* stateset = cylinderDrawable_->getOrCreateStateSet();
stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
osg::ref_ptr<osg::BlendFunc> blendFunc = new osg::BlendFunc();
stateset->setAttributeAndModes(blendFunc, osg::StateAttribute::ON);
osg::ref_ptr<osg::Program> program = new osg::Program();
program->addShader(vertexShader);
program->addShader(fragmentShader);
stateset->addUniform(new osg::Uniform("texture", 0));
baseColorUniform_ = new osg::Uniform("baseColor", baseColor_);
stateset->addUniform(baseColorUniform_);
stateset->setAttributeAndModes(program, osg::StateAttribute::ON);
timeUniform_ = new osg::Uniform("time", 0.0f);
stateset->addUniform(timeUniform_);
UpdateRotaion();
}
void DashedLine::UpdateRotaion() {
osg::Vec3 direction = end_ - start_;
float height = direction.length();
cylinder_->setHeight(height);
cylinderDrawable_->build();
osg::Vec3 center = (start_ + end_) * 0.5f;
direction.normalize();
setPosition(center);
osg::Vec3 up(0.0f, 0.0f, 1.0f);
osg::Quat rotation;
rotation.makeRotate(up, direction);
setAttitude(rotation);
}