-
-
-
-
-
-
-
-
-
-
-
-
AI介绍OF
3D图元示例
部分代码
参考链接
-
-
-
-
-
-
-
-
-
-
-
一、AI介绍OF
chatgpt
claude
二、3D图元示例
示例截图
运行演示
三角面片运动模式
三、部分代码
void ofApp::draw() {
//物体旋转角度
float spinX = sin(ofGetElapsedTimef()*.35f);
float spinY = cos(ofGetElapsedTimef()*.075f);
//按下鼠标 旋转角度置为0
if (bMousePressed) {
spinX = spinY = 0.0f;
}
//相机全局位置
cam.setGlobalPosition({ 0,0,cam.getImagePlaneDistance(ofGetCurrentViewport()) });
cam.begin();//开启相机渲染
ofEnableDepthTest();//启用深度测试
ofEnableLighting();//启用光照
pointLight.enable(); //点光源启用
pointLight2.enable();
pointLight3.enable();
// draw the outer sphere 绘制外轮廓球体
material.begin();
ofNoFill();//使用当前绘制颜色将形状绘制为轮廓。
//使用当前渲染器绘制一个球体。球体是用代表球体中心的 x、y 和 z 坐标绘制的。此函数使用默认原点 z=O 绘制球体。
ofDrawSphere(0, 0, max(ofGetWidth(),ofGetHeight()));
material.end();
if (mode == 1 || mode == 3) texture.getTexture().bind();//绑定纹理:mode==1/3
if (mode == 2) vidGrabber.getTexture().bind();//视频采集器绑定纹理
//屏幕宽高
float screenWidth = ofGetWidth();
float screenHeight = ofGetHeight();
//设置3D图元的位置
plane.setPosition( -screenWidth * .5 + screenWidth * 1/4.f, screenHeight * 1.1/6.f, 0);
box.setPosition( -screenWidth * .5 + screenWidth * 2/4.f, screenHeight * 1.1/6.f, 0);
sphere.setPosition( -screenWidth * .5 + screenWidth * 3/4.f, screenHeight * 1.1/6.f, 0);
icoSphere.setPosition( -screenWidth * .5 + screenWidth * 1/4.f, screenHeight * -1.1/6.f, 0);
cylinder.setPosition( -screenWidth * .5 + screenWidth * 2/4.f, screenHeight * -1.1/6.f, 0);
cone.setPosition( -screenWidth * .5 + screenWidth * 3/4.f, screenHeight * -1.1/6.f, 0);
// Plane 平面//
plane.rotateDeg(spinX, 1.0, 0.0, 0.0);
plane.rotateDeg(spinY, 0, 1.0, 0.0);
//计算变形曲面
if (mode == 3) {
deformPlane = plane.getMesh();//平面网格->变形曲面
// x = columns, y = rows //
glm::vec2 planeDims = plane.getResolution();//平面分辨率
float planeAngleX = ofGetElapsedTimef()*3.6;//平面角度x:随时间增加
float planeAngleInc = 3.f / (float)planeDims.x;//角度增加量
glm::vec3 vert;//顶点
for (size_t i = 0; i < deformPlane.getNumIndices(); i++) {//遍历变形平面的所有顶点
planeAngleX += planeAngleInc;//计算角度x
int ii = deformPlane.getIndex(i);//获取顶点索引ii
vert = deformPlane.getVertex(ii);//获取顶点坐标
vert.z += cos(planeAngleX) * 50;//顶点的z值 余弦波动
deformPlane.setVertex(ii, vert);//更新顶点
}
}
//非填充 且 线框
if (!bFill && bWireframe) {
// if we are only drawing the wireframe, use
// the material to draw it, otherwise the material
// will be bound and unbound for every geometry
// and the wireframe will be drawn in black
// 如果我们只绘制线框,则使用材质来绘制它,否则材质将为每个几何体绑定和取消绑定,线框将绘制为黑色
material.begin();
}
//填充模式:绘制平面或者变形曲面
if (bFill) {
material.begin();
ofFill();//绘制填充当前绘制颜色的形状。~~~~f。cpp) void ofApp: drawOf ofSetColor(0,0,255); offillO: ofDrawRect(10,10,100,100); //绘制蓝色填充的矩形)
if (mode == 3) {
plane.transformGL();//将 opengl 渲染器的模型视图矩阵设置为此节点转换。
deformPlane.draw();//绘制变形曲面
plane.restoreTransformGL();//恢复 opengl 渲染器之前的模型视图变换矩阵。
}
else {
plane.draw();//绘制平面
}
material.end();
}
//线框模式 绘制平面
if (bWireframe) {
ofNoFill();//使用当前绘制颜色将形状绘制为轮廓。~~~~{. cpp) void ofApp: drawOf ofSetColor(0,0,255); 的NoFillO; ofDrawRectangle(10,10,100,100); //只绘制蓝色轮廓)~~~~
ofSetColor(0, 0, 0);//黑色
plane.setPosition(plane.getPosition().x, plane.getPosition().y, plane.getPosition().z + 1);//平面位置z+1
plane.drawWireframe();//绘制线框
plane.setPosition(plane.getPosition().x, plane.getPosition().y, plane.getPosition().z - 1);//平面位置z-1
}
// Box 盒子 角度 //
box.rotateDeg(spinX, 1.0, 0.0, 0.0);
box.rotateDeg(spinY, 0, 1.0, 0.0);
//填充模式:绘制盒子
if (bFill) {
material.begin();
ofFill();
if (mode == 3) {
box.transformGL();
for (int i = 0; i < ofBoxPrimitive::SIDES_TOTAL; i++) {//遍历6个面
ofPushMatrix();//将 opengl 渲染器的模型视图矩阵设置为此节点变换。
ofTranslate(boxSides[i].getNormal(0) * sin(ofGetElapsedTimef()) * 50);//这个面沿其法线方向 正弦运动
boxSides[i].draw();
ofPopMatrix();
}
box.restoreTransformGL();
}
else {
box.draw();
}
material.end();
}
//线框模式
if (bWireframe) {
ofNoFill();
ofSetColor(0, 0, 0);
box.setScale(1.01f);//设置局部统一比例(x、y 和 z 等比例缩放)。
box.drawWireframe();//绘制线框盒子
box.setScale(1.f);//恢复统一比例
}
// Sphere 球体 设置旋转角度 绕x轴 绕Y轴//
sphere.rotateDeg(spinX, 1.0, 0.0, 0.0);
sphere.rotateDeg(spinY, 0, 1.0, 0.0);
//球体
if (mode == 3) {
sphere.setMode(OF_PRIMITIVE_TRIANGLES);//原始三角形球体
triangles = sphere.getMesh().getUniqueFaces();//球体的三角面片集合
}
//填充球体
if (bFill) {
material.begin();
ofFill();
if (mode == 3) {
float angle = ofGetElapsedTimef()*3.2;//
float strength = (sin(angle + .25)) * .5f * 5.f;//正弦移动
glm::vec3 faceNormal;
for (size_t i = 0; i < triangles.size(); i++) {//遍历球体的三角面片
// store the face normal here.
// we change the vertices, which makes the face normal change
// every time that we call getFaceNormal //
// 在这里存储面法线。
// 我们改变了顶点,这使得面部正常变化
// 每次我们调用 getFaceNormal //
faceNormal = triangles[i].getFaceNormal();//获取三角面片法线
for (int j = 0; j < 3; j++) {
triangles[i].setVertex(j, triangles[i].getVertex(j) + faceNormal * strength);//三角面片沿法线方向做正弦运动
}
}
sphere.getMesh().setFromTriangles(triangles);//以三角面片集合设置球体
}
sphere.draw();//绘制球体
material.end();
}
//绘制球体线框
if (bWireframe) {
ofNoFill();
ofSetColor(0, 0, 0);
sphere.setScale(1.01f);
sphere.drawWireframe();
sphere.setScale(1.f);
}
}
参考链接:
https://openframeworks.cc/zh_cn/documentation/
https://openframeworks.cc/download/
https://github.com/openframeworks/openFrameworks/releases/tag/nightly
The End