2012-04-22 26 views
0

目前我正在使用OpenFrameworks构建布料物理应用程序。我是新来的C + +,提高了头。不可预测的指针行为

在我的应用程序中,两个'邻居'粒子对象作为指针传递给一个弹簧对象。作为测试,我在两个粒子之间(在它们的三维矢量位置之间)绘制了弹簧对象画线。由于某些原因,即使没有涉及随机值,每次运行该程序时,这些行都是不同的。当我从弹簧结构中获取粒子位置的值时,它们通常是像-4.15301e-12这样的荒谬值。我几乎逐字地跟踪示例代码,所以我不确定我要错哪里。

下面是我在下面的示例代码:

https://sites.google.com/site/ofauckland/examples/17-cloth-physics

这里是我的春天结构:

#pragma once 
#include "ofMain.h" 
#include "Particle.h" 

struct Spring { 

    float k, restLength; 
    Particle *a, *b; 
    ofVec3f posA, posB; 

    Spring(Particle *a, Particle *b, float k = .2) : a(a), b(b), k(k) { 
     restLength = (b->pos - a->pos).length(); 
    } 

    void update() { 
     posA = a->pos; 
     posB = b->pos; 
    } 
    void draw() { 
     ofSetLineWidth(5); 
     ofSetColor(0, 255, 0); 
     ofLine(posA.x, posA.y, posB.x, posB.y); 
    } 
};        

的颗粒结构:

#pragma once 
#include "ofMain.h" 

struct Particle { 

    ofVec3f pos; 

    Particle(ofVec3f pos) : pos(pos) { 
    } 

    void update() { 
    } 
    void draw() { 
     ofSetColor(ofRandom(255), 0, 0); 
     ofFill(); 
     ofCircle(pos.x, pos.y, 3); 
    } 
};  

这是我将两个粒子作为指针传递给弹簧:

#pragma once 
#include "ofMain.h" 
#include "Particle.h" 
#include "Spring.h" 

struct Petal { 

    float maxWidth, spacing; 
    vector<Particle> particles; 
    vector<Spring> springs; 

    Petal(float maxWidth, float spacing) : maxWidth(maxWidth), spacing(spacing) {   
     setupPoints(); 
    } 

    void setupPoints() { 
     float x = 0; 
     float y = 0; 

     for(int r = 1; r <= maxWidth; r++) { 
      x = (int)(r/2) * -spacing; 
      y += spacing; 
      for(int c = 1; c <= r; c++) { 
       ofVec3f pos = ofVec3f(x, y, 0); 
       Particle p(pos); 
       particles.push_back(p); 
       x+=spacing; 
      } 
     } 

     for(int r = maxWidth; r > 0; r--) { 
      x = (int)(r/2) * -spacing; 
      y += spacing; 
      for(int c = 1; c <= r; c++) { 
       ofVec3f pos = ofVec3f(x, y, 0); 
       Particle p(pos); 
       particles.push_back(p); 
       x+=spacing; 
      } 
     } 

     //find neighbors 
     for(int i = 0; i < particles.size(); i++) { 
      Spring s(&particles[i], &particles[findNeighbor(i)]); 
      springs.push_back(s); 
     } 
    } 

    int findNeighbor(int pIndex) { 
     float leastDist = 0; 
     float leastDistIndex = 0; 
     for(int i = 0; i < particles.size(); i++) { 
      if(i != pIndex) { 
       float distance = particles[pIndex].pos.distance(particles[i].pos); 
       if(abs(distance) < abs(leastDist) || leastDist == 0) { 
         leastDist = distance; 
         leastDistIndex = i; 
       } 
      } 
     } 
     return leastDistIndex; 

    } 

    void update() { 
     for(int i = 0; i < particles.size(); i++) { 
      particles[i].update(); 
     } 
     for(int s = 0; s < springs.size(); s++) { 
      springs[s].update(); 
     } 
    } 
    void draw() { 
     for(int i = 0; i < particles.size(); i++) { 
      particles[i].draw(); 
     } 
     for(int s = 0; s < springs.size(); s++) { 
      springs[s].draw(); 
     } 
    } 
}; 

This是什么情况。奇怪的是,有些弹簧似乎处于正确的位置。

请让我知道,如果我可以澄清的东西。

谢谢!

+1

你确定你在'draw'之前调用'update'吗?一般来说,当构造函数完成时,确保一个对象是完全构造的(可以调用任何操作)是一个好主意,但是您要进行两步初始化:粒子在构造函数中初始化,但是位置, 'k'和'​​restLength'不是。 – 2012-04-22 15:35:20

+0

我接受了关于在构造函数中初始化k和restlength的建议。是的,更新在绘制之前调用。 谢谢 – Miles 2012-04-22 15:47:55

回答

2

您的particles矢量按值保存Particles,而vector可以复制并移动这些值。当您通过Particles作为指向Spring的指针时,您将传递未来某处可能不存在的地址。我不确定这是否是问题,但它肯定是需要解决的问题。

+0

这是有道理的,虽然我创建指针的时候,我已经完成向粒子矢量添加元素。地址在这之后仍然改变? 那么我应该使用一个数组来确保地址的稳定性? – Miles 2012-04-22 15:45:59

+0

@Miles你应该认为他们可以随时移动。你可以使用数组,但也可以问自己是否真的需要传递指针。你也可以保存智能指针的向量而不是值。有很多解决方案,但我不完全知道你的用例。 – juanchopanza 2012-04-22 15:48:47

+0

我想到了一个解决方案,但似乎并不奏效。 我将粒子矢量的指针和第一个和第二个粒子的索引传递给了spring结构体。粒子矢量本身的地址是否会改变? – Miles 2012-04-22 17:15:26