osg实例绘制

#include <osg/Geometry>
#include <osg/Geode>
#include <osg/Program>
#include <osg/VertexAttribDivisor>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <random>
// 创建单个立方体几何体(共享基础形状)
osg::ref_ptr<osg::Geometry> createCubeGeometry(int vtx) {
    osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;

    // 立方体8个顶点(单位立方体,中心在原点)
    osg::Vec3Array* vertices = new osg::Vec3Array;
    vertices->push_back(osg::Vec3(-0.5, -0.5, -0.5)); // 0 左前下
    vertices->push_back(osg::Vec3(0.5, -0.5, -0.5)); // 1 右前下
    vertices->push_back(osg::Vec3(0.5, 0.5, -0.5)); // 2 右后下
    vertices->push_back(osg::Vec3(-0.5, 0.5, -0.5)); // 3 左后下
    vertices->push_back(osg::Vec3(-0.5, -0.5, 0.5)); // 4 左前上
    vertices->push_back(osg::Vec3(0.5, -0.5, 0.5)); // 5 右前上
    vertices->push_back(osg::Vec3(0.5, 0.5, 0.5)); // 6 右后上
    vertices->push_back(osg::Vec3(-0.5, 0.5, 0.5)); // 7 左后上
    geom->setVertexArray(vertices);

    // 立方体6个面的法线(用于光照计算)
    osg::Vec3Array* normals = new osg::Vec3Array;
    normals->push_back(osg::Vec3(0, 0, -1)); // 前面
    normals->push_back(osg::Vec3(0, 0, 1)); // 后面
    normals->push_back(osg::Vec3(-1, 0, 0)); // 左面
    normals->push_back(osg::Vec3(1, 0, 0)); // 右面
    normals->push_back(osg::Vec3(0, -1, 0)); // 底面
    normals->push_back(osg::Vec3(0, 1, 0)); // 顶面
    geom->setNormalArray(normals, osg::Array::BIND_PER_PRIMITIVE_SET);

    std::vector<GLuint> idxbuffer;

    // 前面
    idxbuffer.push_back(0); idxbuffer.push_back(1); idxbuffer.push_back(2);
    idxbuffer.push_back(2); idxbuffer.push_back(3); idxbuffer.push_back(0);
    // 后面
    idxbuffer.push_back(4); idxbuffer.push_back(7); idxbuffer.push_back(6);
    idxbuffer.push_back(6); idxbuffer.push_back(5); idxbuffer.push_back(4);
    // 左面
    idxbuffer.push_back(0); idxbuffer.push_back(3); idxbuffer.push_back(7);
    idxbuffer.push_back(7); idxbuffer.push_back(4); idxbuffer.push_back(0);
    // 右面
    idxbuffer.push_back(1); idxbuffer.push_back(5); idxbuffer.push_back(6);
    idxbuffer.push_back(6); idxbuffer.push_back(2); idxbuffer.push_back(1);
    // 底面
    idxbuffer.push_back(0); idxbuffer.push_back(4); idxbuffer.push_back(5);
    idxbuffer.push_back(5); idxbuffer.push_back(1); idxbuffer.push_back(0);
    // 顶面
    idxbuffer.push_back(3); idxbuffer.push_back(2); idxbuffer.push_back(6);
    idxbuffer.push_back(6); idxbuffer.push_back(7); idxbuffer.push_back(3);

    // 定义12个三角形(每个面2个三角形)
    osg::DrawElementsUInt* indices = new osg::DrawElementsUInt(GL_TRIANGLES, 36, idxbuffer.data(), vtx);

    geom->addPrimitiveSet(indices);

    geom->setUseDisplayList(false);
    geom->setUseVertexBufferObjects(true);
    return geom;
}

// 创建实例化变换矩阵数组
osg::ref_ptr<osg::Vec3Array> createInstancePositions(int count) {
    osg::ref_ptr<osg::Vec3Array> positions = new osg::Vec3Array;
    std::random_device rd;
    std::mt19937 gen(rd());
    const auto len = sqrt(count);
    std::uniform_real_distribution<float> dis(-len, len);

    for (int i = 0; i < count; ++i) {
        positions->push_back(osg::Vec3(dis(gen), dis(gen), dis(gen)));
    }
    return positions;
}
///gl_InstanceID
const std::string  vertex_shader = R"(
                    #version 430 compatibility
                    layout(location = 0) in vec3 vertexPosition;
                    layout(location = 6) in vec3 instancePosition;
                    uniform mat4 osg_ModelViewProjectionMatrix;
                    void main() {
                        vec4 pos = vec4(vertexPosition + instancePosition, 1.0);
                        gl_Position =  gl_ModelViewProjectionMatrix * pos;
                    }
)";
const std::string  frag_shader = R"(
                    #version 430 core
                    out vec4 fragColor;
                    void main() {
                        fragColor = vec4(0.8, 0.3, 0.2, 1.0); 
                    }
)";
int main() {
    // 创建场景根节点
    osg::ref_ptr<osg::Group> root = new osg::Group;

    constexpr int instanceCount = 100; // 实例数量

    // 创建共享几何体
    osg::ref_ptr<osg::Geometry> cube = createCubeGeometry(instanceCount);

    // 设置实例化属性(位置)
    osg::ref_ptr<osg::Vec3Array> instancePositions = createInstancePositions(instanceCount);

    instancePositions->setBinding(osg::Array::Binding::BIND_PER_VERTEX);
    cube->setVertexAttribArray(6, instancePositions); // 绑定到属性索引6

    cube->getOrCreateStateSet()->setAttribute(new osg::VertexAttribDivisor(6, 1));//(顶点属性索引,*实例使用相同的顶点属)

    // 创建几何节点并添加到场景
    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
    geode->addDrawable(cube);
    root->addChild(geode);

    // 配置实例化着色器
    osg::ref_ptr<osg::Program> program = new osg::Program;

    program->addShader(new osg::Shader(osg::Shader::VERTEX, vertex_shader.c_str()));
    program->addShader(new osg::Shader(osg::Shader::FRAGMENT, frag_shader.c_str()));
    geode->getOrCreateStateSet()->setAttribute(program);
    
    // 启动查看器
    osgViewer::Viewer viewer;
    viewer.setUpViewInWindow(100, 100, 800, 600);
    viewer.setSceneData(root);
    viewer.addEventHandler(new osgViewer::StatsHandler());
    viewer.getCamera()->setNearFarRatio(1e-5);
    viewer.getCamera()->setProjectionMatrixAsPerspective(60, 800 / (float)600, 1, 100);
    viewer.getCamera()->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
    return viewer.run();
}
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/86192.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/86192.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qt面试题汇总

目录 1. 简单说一下Qt 2. 用过QT中的哪些模块&#xff1f; 3. 说一些你常用的Qt控件&#xff1f; 4. Qt中如何创建一个窗口&#xff1f; 5. 说一下QT中创建控件的方式? 6. 说一下Qt中信号和槽机制是什么&#xff1f; 7. 说一下QT信号与槽机制原理&#xff1f; 8. 如何自…

【stm32】标准库学习——USART串口

目录 一、USART串口 1.串口参数及时序 2.USART简介 3.配置USART基本结构 4.初始化模板 (1) 接收一个数据 (2) 发送一个数据 一、USART串口 1.串口参数及时序 波特率:串口通信的速率起始位:标志一个数据帧的开始&#xff0c;固定为低电平数据位:数据帧的有效载荷&#…

黑马Day01-03集开始

03集 JSX jsx里面可以写 表达式,表达式里面会返回一个值js语法的扩展,需要babel解析才能够在浏览器运行 语法 使用花括号 {} ,在里面进行编写jsx代码04集 高频场景 使用引号传递字符串 使用js变量 函数调用和方法调用 使用js对象.js自带的一些对象或new出来的对象{&quo…

vue 路由学习

params 不能传递对象类型如 [ ]和{ } query传参 总结&#xff1a; query传参既可以通过name 和path 找到路由规则里的组件&#xff0c;所以为了统一避免非必要麻烦 无论是使用query传参还是 params传参 映射路由建议统一使用 name 进阶 props的使用 备注&#xff1a;资料来自…

JDK安装全攻略:开启Java编程大门

目录 一、安装前准备1.1 确认系统类型1.2 检查系统要求1.3 下载 JDK 安装包 二、Windows 系统下 JDK 安装步骤2.1 双击安装包2.2 选择安装目录2.3 完成安装 三、Windows 系统环境变量配置3.1 打开环境变量设置3.2 配置 JAVA_HOME 变量3.3 配置 Path 变量3.4 验证配置 四、Linux…

《P1253 扶苏的问题》

题目描述 给定一个长度为 n 的序列 a&#xff0c;要求支持如下三个操作&#xff1a; 给定区间 [l,r]&#xff0c;将区间内每个数都修改为 x。给定区间 [l,r]&#xff0c;将区间内每个数都加上 x。给定区间 [l,r]&#xff0c;求区间内的最大值。 输入格式 第一行是两个整数&…

09.【C语言学习笔记】指针(一)

目录 1. 内存和地址 1.1 内存 1.2 究竟该如何理解编址 2. 指针变量和地址 2.1 取地址操作符&#xff08;&&#xff09; 2.2 指针变量和解引用操作符&#xff08;*&#xff09; 2.2.1 指针变量 2.2.2 如何拆解指针类型 2.2.3 解引用操作符 * 2.3 指针变量的大小…

Java中static关键字的作用与使用详解

static是Java中一个非常重要的关键字&#xff0c;它可以用来修饰变量、方法、代码块和嵌套类。下面将从多个方面详细解释static的作用和使用方法。 一、static变量&#xff08;类变量&#xff09; 作用 static变量属于类&#xff0c;而不是类的某个实例。所有实例共享同一个s…

HMLDM-UD100A 型工业激光测距仪通过modbusRTU 转 profinet 网关轻松接入到西门子1200plc

HMLDM-UD100A 型工业激光测距仪通过modbusRTU 转 profinet 网关轻松接入到西门子1200plc 在现代工业生产与自动化控制领域&#xff0c;精准的测量设备与高效的通信技术至关重要。HMLDM-UD100A 型工业激光测距仪凭借其高精度、稳定性强等优势&#xff0c;广泛应用于各类工业场景…

数据结构与算法:图论——深度优先搜索dfs

深度优先搜索dfs 提到深度优先搜索&#xff08;dfs&#xff09;&#xff0c;就不得不说和广度优先搜索&#xff08;bfs&#xff09;有什么区别 根据搜索方式的不同&#xff0c;可以将图的遍历分为「深度优先搜索」和「广度优先搜索」。 深度优先搜索&#xff1a;从某一顶点出…

数组题解——​合并区间【LeetCode】

56. 合并区间 排序&#xff1a; 将所有区间按起始位置 start 从小到大排序。这样&#xff0c;重叠的区间会相邻排列&#xff0c;方便后续合并。 合并&#xff1a; 初始化一个空列表 merged&#xff0c;用于存储合并后的区间。遍历排序后的区间列表&#xff1a; 如果 merged 为…

关于高精度和链表的详细讲解(从属于GESP五级)

本章内容 高精度 链表 位数再多&#xff0c;只管稳稳进位&#xff0c;终会把答案写满。 一、高精度 1. 什么是高精度 • 定义 “高精度整数”指不受 C 原生整型 (int / long long) 位宽限制&#xff0c;而用数组模拟任意位数的大整数。 • 必要性 64 位 long long 仅能…

Python自动化框架选型指南:Selenium/Airflow/Celery该选谁?

在Python自动化领域,Selenium、Airflow和Celery是三个高频出现的工具,但它们的定位和适用场景截然不同。许多开发者在技术选型时容易混淆它们的边界,导致项目架构臃肿或功能不匹配。本文将通过对比分析,帮你明确不同场景下的最佳选择。 一、框架定位与核心功能对比 框架核…

50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | DrinkWater(喝水记录组件)

&#x1f4c5; 我们继续 50 个小项目挑战&#xff01;—— DrinkWater组件 仓库地址&#xff1a;https://github.com/SunACong/50-vue-projects 项目预览地址&#xff1a;https://50-vue-projects.vercel.app/ 使用 Vue 3 的 Composition API 和 <script setup> 语法结…

UAVAI-YOLO:无人机航拍图像的小目标检测模型

摘要 针对无人机航拍图像目标检测效果差的问题&#xff0c;提出改进的UAVAI-YOLO模型。首先&#xff0c;为使模型获得更加丰富的语义信息&#xff0c;使用改进可变形卷积网络&#xff08;deformable convolutional networks&#xff0c;DCN&#xff09;替换原骨干&#xff08…

Solidity 入门教程(一):Hello Web3,从一个字符串开始!

学习 Solidity 最好的方式&#xff0c;就是写出你的第一个合约&#xff01;在本篇文章中&#xff0c;我们将用极简的代码&#xff0c;通过 Remix 平台快速实现并运行一个 “Hello Web3!” 合约&#xff0c;正式迈入智能合约开发的大门。 一、什么是 Solidity&#xff1f; Sol…

串扰与包地

串扰与包地&#xff1a; 串扰与包地一直是业界非常关心的一个问题&#xff0c;围绕着它们的争论非常多&#xff0c;那到底是包地好 还是不包地好呢?高速先生尝试着从理论和实际测试上来给大家做一个分析。 为了验证它&#xff0c;高速先生做了以下几种情况&#xff0c;如图5-…

leetcode hot 100之:二叉树的最近公共祖先

本来不打算写的哈哈哈但是发现这一道递归我是有思路的&#xff01;&#xff01;自己能想到一些方向&#xff01;我真棒&#xff01;所以记录一下哈哈哈 我的思路&#xff1a; 1、祖先一定是自身或往上找&#xff0c;所以如何逆着走呢&#xff1f; 2、3种情况&#xff1a; 有…

【VUE】某时间某空间占用情况效果展示,vue2+element ui实现。场景:会议室占用、教室占用等。

某时间某空间占用情况效果展示&#xff0c;vue2element ui实现。场景&#xff1a;会议室占用、教室占用等。 场景说明&#xff1a; 现在需要基于vue2和el-table实现每日会议室个时间点占用情况。 已知数据&#xff1a; 1、会议室数据&#xff08;名称&#xff0c;id&#xff…

Git更换源方式记录

本文首发地址&#xff1a;https://www.dawnsite.cn/archives/198.html 该方式前提是本地项目已关联远程仓库&#xff0c;由于业务变更git地址改变 1. 移除本地已有远程仓库 git remote remove origin2. 添加新的远程仓库源 git remote add origin "clone地址"3.一步…