// OSG.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include <iostream>
#include <osg/Node>
#include <osg/Group>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Texture2D>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osg/PositionAttitudeTransform>
#include <osgGA/TrackballManipulator>
#include<string>
using namespace std;
int main(int argc, char **argv)
{
osg::Group* root = new osg::Group();//场景图形根节点
osg::Geode* pyramidGeode = new osg::Geode();//记录可绘制对象(Drawable)的几何体节点(Geode)
osg::Geometry* pyramidGeometry = new osg::Geometry();//作为可绘制对象基类的Drawable类是一个纯虚类,它有六个派生类
//其中Geometry类中可以直接指定顶点数据,或者指定任意数目的几何基元PrimitiveSet类与其关联。
//现在我们将金字塔几何体与Geode关联,并将Geode叶节点添加到场景图形的根节点。
pyramidGeode->addDrawable(pyramidGeometry);
root->addChild(pyramidGeode);
//顶点数组
osg::Vec3Array* pyramidVertices = new osg::Vec3Array;
pyramidVertices->push_back(osg::Vec3(0, 0, 0)); // 左前
pyramidVertices->push_back(osg::Vec3(10, 0, 0)); // 右前
pyramidVertices->push_back(osg::Vec3(10, 10, 0)); // 右后
pyramidVertices->push_back(osg::Vec3(0, 10, 0)); // 左后
pyramidVertices->push_back(osg::Vec3(5, 5, 10)); // 塔尖
//将这一顶点集合关联到Geometry实例上,后者已经与场景的Geode叶节点相关联。
pyramidGeometry->setVertexArray(pyramidVertices);
//我们创建几何基元类PrimitiveSet的实例并添加到金字塔几何体上
osg::DrawElementsUInt* pyramidBase =
new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);//画四边形
//几何基元枚举类型(与OpenGL的几何基元枚举类型相同)作为输入参数,另一个输入参数是作为起始点的顶点索引值
pyramidBase->push_back(3); //逆时针的顺序添加顶点数据
pyramidBase->push_back(2);
pyramidBase->push_back(1);
pyramidBase->push_back(0);
pyramidGeometry->addPrimitiveSet(pyramidBase); //相关联 添加
osg::DrawElementsUInt* pyramidFaceOne =
new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);//画三角形
pyramidFaceOne->push_back(0);
pyramidFaceOne->push_back(1);
pyramidFaceOne->push_back(4);
pyramidGeometry->addPrimitiveSet(pyramidFaceOne);
osg::DrawElementsUInt* pyramidFaceTwo =
new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);//画三角形
pyramidFaceTwo->push_back(1);
pyramidFaceTwo->push_back(2);
pyramidFaceTwo->push_back(4);
pyramidGeometry->addPrimitiveSet(pyramidFaceTwo);
osg::DrawElementsUInt* pyramidFaceThree =
new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);//画三角形
pyramidFaceThree->push_back(2);
pyramidFaceThree->push_back(3);
pyramidFaceThree->push_back(4);
pyramidGeometry->addPrimitiveSet(pyramidFaceThree);
osg::DrawElementsUInt* pyramidFaceFour =
new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
pyramidFaceFour->push_back(3);
pyramidFaceFour->push_back(0);
pyramidFaceFour->push_back(4);
pyramidGeometry->addPrimitiveSet(pyramidFaceFour);
//定义一个Vec4的数组,用于保存颜色值
osg::Vec4Array* colors = new osg::Vec4Array;
colors->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f)); //索引0 红色
colors->push_back(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); //索引1 绿色
colors->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f)); //索引2 蓝色
colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f)); //索引3 白色
/*下一步要将顶点数组的元素与颜色数组的元素对应起来。我们将声明一个与顶点数组有相同个数元素的向量组。它将负责连接各个顶点与颜色。该向量组的--索引 --对应---顶点数组的元素,其取值对应颜色数组的索引。如果需要将顶点数组与法线数组或者纹理坐标数组一一对应,那么还需重复这一步骤。
注意在本例中,我们需要将5个顶点对应到4种颜色上。因此顶点数组的元素0(左下)和元素4(塔尖)都需要对应到颜色数组元素0(红色)上。
*/
osg::TemplateIndexArray
<unsigned int, osg::Array::UIntArrayType, 4, 4> *colorIndexArray;
colorIndexArray =
new osg::TemplateIndexArray<unsigned int, osg::Array::UIntArrayType, 4, 4>;
//于颜色绑定
colorIndexArray->push_back(0); // vertex 0 assigned color array element 0
colorIndexArray->push_back(1); // vertex 1 assigned color array element 1
colorIndexArray->push_back(2); // vertex 2 assigned color array element 2
colorIndexArray->push_back(3); // vertex 3 assigned color array element 3
colorIndexArray->push_back(0); // vertex 4 assigned color array element 0
pyramidGeometry->setColorArray(colors);//几何体直接与颜色绑定
//pyramidGeometry->setColorIndices(colorIndexArray);
pyramidGeometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);//绑定方式
osg::Vec2Array* texcoords = new osg::Vec2Array(5);
(*texcoords)[0].set(0.00f, 0.0f);
(*texcoords)[1].set(0.25f, 0.0f);
(*texcoords)[2].set(0.50f, 0.0f);
(*texcoords)[3].set(0.75f, 0.0f);
(*texcoords)[4].set(0.50f, 1.0f);
pyramidGeometry->setTexCoordArray(0, texcoords);;//设置纹理坐标 参数1纹理单元,参数2纹理坐标
//初始化位置变换节点
osg::PositionAttitudeTransform* pyramidTwoXForm =
new osg::PositionAttitudeTransform();
//使用osg::Group的addChild方法,将位置变换节点添加到根节点的子节点上,并将金字塔节点作为变换节点的子节点
root->addChild(pyramidTwoXForm);
pyramidTwoXForm->addChild(pyramidGeode);//平移后的金字塔(第二个金字塔)
// 初始化一个Vec3实例,用于改变模型在场景中的位置
osg::Vec3 pyramidTwoPosition(15, 0, 0);
pyramidTwoXForm->setPosition(pyramidTwoPosition);
osgViewer::Viewer viewer;
viewer.setSceneData(root);
viewer.run();
// std::cout << "Hello World!\n";
}