【openframeworks】高级3D示例(Claude写的OF高级3D应用示例文章)

8f882f940958e4f71f66b6a3f35ee164.png

主界面截图

43c4001c24f10c723bd1ab3f4af22214.png

程序框架

视频演示


部分代码

初始化粒子群

void swarm::init(int nParticles, float positionDispersion, float velocityDispersion){
  // 检查我们是否已经初始化Check if we've already initialised
  if(particles.size() != 0){ 
    //清除旧数据 clear out old data
    ofLogWarning("swarm") <<  "Swarm: Already initialised";
    particles.clear();//清空旧粒子
  }
  ofSeedRandom();//随机种子
  //
  glm::vec3 position, velocity;//位置 速度
  ofColor color;//颜色
  for(int i = 0; i < nParticles; i++){//初始化粒子   
    position.x = (ofRandom(1.0f) - 0.5f)  * positionDispersion;
    position.y = (ofRandom(1.0f) - 0.5f)  * positionDispersion;
    position.z = (ofRandom(1.0f) - 0.5f)  * positionDispersion;


    velocity.x = (ofRandom(1.0f) - 0.5f)  * velocityDispersion;
    velocity.y = (ofRandom(1.0f) - 0.5f)  * velocityDispersion;
    velocity.z = (ofRandom(1.0f) - 0.5f)  * velocityDispersion;


    color.r = ofRandom(255.0f);
    color.g = ofRandom(255.0f);
    color.b = 150.0f;
    color.a = 255.0f;


    particle newParticle;
    newParticle.position = position;
    newParticle.velocity = velocity;
    newParticle.color = color;


    // add our new particle to the vector
    particles.push_back(newParticle);
  }
}

更新每个粒子位置、速度 

void swarm::update(){
  //计算每帧过去的时间 Calculate time past per frame
  float dt = ofGetLastFrameTime();


  // 更新位置、速度 Update positions, velocities
  for(unsigned int i = 0; i < particles.size(); i++){


    //  MOTION MATHS
    //
    //    'Simple Harmonic Motion' + a little extra
    // [1] apply velocity to postion
    //  (i.e. integrate velocity)
    //
    //  v = dx / dt (*)
    //  x = x + dx [every frame]
    //
    // therefore
    //  x = x + v * dt (*)
    // (velcotity is taken from previous frame)
    particles[i].position += particles[i].velocity * dt;
    // [2]对速度施加弹簧力 apply spring force to velocity
    //  (i.e. integrate acceleration)
    //
    //  a = -k * x (this is the shm restoring force, aka spring force)
    //  a = dv / dt
    //
    // therefore from (*)s above
    //  (v = v + dv)
    //
    //  v = v + (dt * a)
    //  v = v + (dt * -k * x)
    //
    particles[i].velocity += -SPRING_CONSTANT * particles[i].position * dt;//修改速度:-弹簧系数*位置*dt
    // [3] to get a super simple kind of 'flocking' behaviour
    //  we add a second spring force to velocity relative
    //  to the position of the light
    // NOTICE: THIS ISN'T REAL FLOCKING!获得一种超级简单的“簇拥”行为
    // 我们将第二个弹簧力添加到相对速度
    // 到灯的位置
    // 注意:这不是真正的簇拥!
    particles[i].velocity += -SPRING_CONSTANT * (particles[i].position - light.getPosition()) * dt;
    // [4]强制最大速度 Force a maximum velocity
    if(glm::length(particles[i].velocity) > MAX_VELOCITY){
      particles[i].velocity /= glm::length(particles[i].velocity) * MAX_VELOCITY;// 数组v*(1/3*max)
    }
  }
}

绘制粒子群:

void swarm::customDraw(){
  // We run the update ourselves manually. ofNode does
  //  not do this for us.我们自己手动运行更新。ofNode 不会为我们做这些。
  update();
  // 绘制粒子Draw particles
  // We use the position of the first
  //  particle as the position of the
  //  light. 我们使用第一个粒子的位置作为光的位置。
  ofPushStyle();//在调用后保存 ofGraphics 的当前样式设置。
  light.enable();//启用光源:绘制带材质的球体
  light.setPosition(particles[0].position);//设置光源位置


  for(unsigned int i = 0; i < particles.size(); i++){
    //ofPushStyle();
    //ofSetColor(particles[i].color);
    material.setDiffuseColor(particles[i].color);//设置材质颜色


    material.begin();
    ofDrawSphere(particles[i].position, 1.0);//绘制粒子球体
    //ofPopStyle();
  }
  material.end();//结束材质
  light.disable();//禁用光源
  ofDisableLighting();//禁用光照
  //将光源渲染为白色球体 Render light as white sphere
  ofSetColor(255, 255, 255); //白色
  ofDrawSphere(light.getPosition(), 2.0);//绘制球体
  /*设置位图绘制模式 有效模式:OF BITMAPMODE SCREEN:这是默认模式。它将 3d prositionl 投影到屏幕上,因此字母看起来总是相同大小,但可以定位在任何 3d 坐标中。
  OF BITMAPMODE VIEWPORT:与屏幕相同,但如果不同,则使用当前视口而不是整个窗口。OF_BITMAPMODE_MODEL:使用真实的 3d 坐标,因此如果文本不在 z=0 中,则文本看起来会缩放
  OF BITMAPMODE MODEL BILLBOARD:使用真实的 3d 坐标,但文本始终面向相机。OF BITMAPMODE SIMPLE:l 只做 2d 而 z 坐标只是被丢弃,所以如果 z 不是 O,它绘制的位置将是错误的。*/
  ofSetDrawBitmapMode(OF_BITMAPMODE_MODEL);//
  ofDrawBitmapString(" light", particles[0].position);//绘制文本:light
  ofPopStyle();//恢复以前的样式设置。需要在 ofPushStyle 之后调用。
}

相机节点设置父节点与取消父节点

if(key == 'p'){
    if(bCamParent){
      camFront.clearParent();//删除父节点链接。
      camTop.clearParent();
      camLeft.clearParent();


      bCamParent = false;
    }
    else{
      camFront.setParent(nodeSwarm.light);//为节点设置父节点。该camFront节点将从 parent(nodeSwarm.light) 继承变换
      camTop.setParent(nodeSwarm.light);
      camLeft.setParent(nodeSwarm.light);


      bCamParent = true;
    }
  }

绘制注释

ofPushStyle();
  ofDisableDepthTest();//禁用深度测试  :绘制边框和gui  文本时 禁用。绘制3D场景时启用


  // 绘制一些标签draw some labels
  ofSetColor(255, 255, 255);//白色
  //在主视口左上角显示文本
  ofDrawBitmapString("Press keys 1-4 to select a camera for main view", viewMain.x + 20, 30);
  ofDrawBitmapString("Camera selected: " + ofToString(iMainCamera + 1), viewMain.x + 20, 50);
  ofDrawBitmapString("Press 'f' to toggle fullscreen", viewMain.x + 20, 70);
  ofDrawBitmapString("Press 'p' to 切换 parents on OrthoCamera's", viewMain.x + 20, 90);
  //侧边视口显示文本
  ofDrawBitmapString("EasyCam",   viewGrid[0].x + 20, viewGrid[0].y + 30);
  ofDrawBitmapString("Front",     viewGrid[1].x + 20, viewGrid[1].y + 30);
  ofDrawBitmapString("Top",       viewGrid[2].x + 20, viewGrid[2].y + 30);
  ofDrawBitmapString("Left",      viewGrid[3].x + 20, viewGrid[3].y + 30);


  //绘制侧边视口矩形 draw outlines on views
  ofSetLineWidth(5);
  ofNoFill();//使用当前绘制颜色将形状绘制为轮廓。
  ofSetColor(255, 255, 255);


  for(int i = 0; i < N_CAMERAS; i++){
    ofDrawRectangle(viewGrid[i]);//绘制四个矩形框
  }
  ofDrawRectangle(viewMain);//主视口矩形框


  // restore the GL depth function
  ofPopStyle();//恢复GL深度函数

调整窗口大小

void ofApp::setupViewports(){
  // 每当我们调整窗口大小时调用这里 call here whenever we resize the window
  // Define viewports
  float xOffset = ofGetWidth() / 3;
  float yOffset = ofGetHeight() / N_CAMERAS;
  //主视口矩形
  viewMain.x = xOffset;
  viewMain.y = 0;
  viewMain.width = xOffset * 2;
  viewMain.height = ofGetHeight();
  //4个侧边视口矩形框 的数组:最左侧
  for(int i = 0; i < N_CAMERAS; i++){


    viewGrid[i].x = 0;
    viewGrid[i].y = yOffset * i;
    viewGrid[i].width = xOffset;
    viewGrid[i].height = yOffset;
  }
}

附:Claude写的OF高级3D应用示例文章

e0b4391bdfdabdd03bc673b86594c550.png

372ac27c0151000b194a88c45334b9d1.png

9634ad971a4310936d26b22652e1fc48.png

The End

猜你喜欢

转载自blog.csdn.net/cxyhjl/article/details/130437396