2012-04-22 13 views
0

現時点では、私はOpenFrameworksを使って布物理アプリケーションを構築しています。私は頭が上がるためにC++を初めて使っています。予測できないポインタの振る舞い

私のアプリでは、2つの '隣人'のパーティクルオブジェクトがポインタとしてスプリングオブジェクトに渡されます。テストとして、私は2つのパーティクル(3dベクトル位置の間)の間に春のオブジェクト描画線を持っています。何らかの理由で、これらの行は、ランダム値が関係していなくても、プログラムを実行するたびに異なります。私がスプリング構造体からパーティクルポジションの値を取り上げると、しばしば-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); 
    } 
};  

そして、これはここで

は、私は次てるのコード例であります私は2つの粒子をポインターとしてスプリングに渡します:

#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'を呼び出していることを確認していますか?一般に、コンストラクタが完了したときにオブジェクトが完全に構築されている(すべての操作が呼び出される)ことを確認することをお勧めしますが、2段階の初期化を行っています:コンストラクタでパーティクルは初期化されますが、 'k'と' restLength'はそうではありません。 –

+0

コンストラクタでkとrestlengthの初期化についてアドバイスを受けました。そして、はい、更新は描画前に呼び出されます。 ありがとう – Miles

答えて

2

particlesベクトルは値でParticlesを保持し、vectorはこれらの値をコピーして移動できます。 ParticlesSpringへのポインタとして渡すと、将来、ある時点では存在しない可能性のあるアドレスが渡されます。これが問題なのかどうかはわかりませんが、確かに修正が必要なものです。

+0

これは意味がありますが、ポインタを作成する頃には、要素をParticlesベクトルに追加することになりました。このあと、アドレスはまだ変わっていますか? アドレスの安定性を確保するために代わりに配列を使用する必要がありますか? – Miles

+0

@Milesいつでも移動できると仮定する必要があります。あなたは配列を使うこともできますが、実際にポインタを渡す必要があるかどうかを尋ねることもできます。値の代わりにスマートポインタのベクトルを保持することもできます。多くのソリューションがありますが、私はあなたのユースケースを正確には分かりません。 – juanchopanza

+0

私は解決策を考えましたが、うまくいかないようです。 私はパーティクルベクトルのポインタと、最初のパーティクルと2番目のパーティクルのインデックスをspring構造体に渡しました。パーティクルベクタ自体のアドレスが変更される可能性はありますか? – Miles