GL,C++を使った球の特性方程式について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ひえらるきー

GL,C++を使った球の特性方程式について

#1

投稿記事 by ひえらるきー » 15年前

バネにつながった球の特性方程式の根が実数根をもつとき,虚数根をもつとき,重根をもつとき,となるようにm, c, kの係数を適当に決めて,それぞれの場合における解軌跡(ドラッグを離した場所を初期値として)を示すものをOPENGLを用いて表示させるプログラムをC++で作成したのが下記のプログラムなのですが、classを用いてm, c, kの値が異なる球を複数表示させたいと思っています。Omori classとしてclassの中にはx,y,z(球の座標)、m,c,k(球の質量, 減衰係数,ばね定数)、球の大きさ、色、バネの位置と設定しょうとしているのですが、うまく作ることが出来ません。
この場合のclassの書き方をどなたか教えていただけないでしょうか?
私は今大学4年生でC++は始めて2ヶ月くらいのまだまだ初心者です。
そのため下記のプログラムもかなり読みづらいかと思いますがどうぞよろしくお願いします。



#include<string>
#include<iostream>
#include<cstring>
#include<stdlib.h>
#include<GL/glut.h>
#include<math.h>

unsigned char mouseFlag = GL_FALSE;
float x0;
float x = 0.0;
int a = 0;
int samplingTime = 50;
int startFlug;
double t = 0.0;
double xStart;
double yStart;
double startFlag;
double yy;


const int width = 1000, height = 1000;

void myKeyboard(unsigned char key, int x, int y)
{
if (key == 27 ) exit(0);
if(key == 'a'){
a = 1;
x = 0.0;
x0 = 0.0;
t = 0.0;
}
if(key == 'b'){
a = 2;
x = 0.0;
x0 = 0.0;
t = 0.0;
}
if(key == 'c'){
a = 3;
x = 0.0;
x0 = 0.0;
t = 0.0;
}
}

void glutDrawString(const char *str,void *font,float A,float B,float C)
{
glRasterPos3f(0,2,0);
while(*str){
glutBitmapCharacter(font, *str);
++str;
}
}


void myDisplay(void)
{

glClear(GL_COLOR_BUFFER_BIT);
glColor3d(0.6, 0.0, 0.5);
glBegin(GL_LINES);
glVertex2d(-10.0, 0.0);
glVertex2d(x, 0.0);

glEnd();

glPushMatrix();
glTranslated(x, 0.0, 0.0);
glutWireSphere(0.5, 70, 70);
glPopMatrix();

glEnd();
glFlush();
}

void myInit(char *progname)
{
glutInitDisplayMode(GLUT_RGBA);
glutInitWindowSize(1000, 1000);
glutInitWindowPosition(0, 0);
glutCreateWindow(progname);
glClearColor(1.0, 1.0, 1.0, 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (double)width / (double)height, 0.1, 200.0);
glMatrixMode(GL_MODELVIEW);
gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

}


void myMouseFunc(int button, int state, int x1, int y1)
{
if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN){
startFlag = 0;
t = 0.0;
x = 0.0;
x0 = 0.0;
yy = 0.0;
xStart = x1;
yStart = y1;
mouseFlag =GL_TRUE;
}else{
mouseFlag = GL_FALSE;
startFlag = 1;
}
}

void myMouseMotion(int xx, int yyy)
{
if(mouseFlag == GL_FALSE) return;
x0 = 0.01 * (xx-xStart);
glutPostRedisplay();
}


void myTimer(int value)
{

glutTimerFunc(samplingTime, myTimer, 1);

if(a == 1){
double m = 2, c = 5, k = 2, w, y, x1, x2, c1, c2;
w = sqrt(k / m);

y = c / (2 * sqrt(m * k));
x1 = -y * w + sqrt(y * y - 1) * w;

x2 = -y * w - sqrt(y * y - 1) * w;

c1 = (x2 / (x2 - x1)) * x0;

c2 = (x1 / (x1 - x2)) * x0;
if(startFlag == 1){
x = c1 * exp(x1 * t) + c2 *exp(x2 * t);

t += 0.2;
}else{
x = x0;
}
glutPostRedisplay();
}
if(a == 2){

double m = 2, c = 4, k = 2, w, x1, c1, c2;
w = sqrt(k / m);
x1 = -w;

c1 = x0;

c2 = x0 * w;

if(startFlag == 1){
x = (c1 + c2 * t) * exp(x1 * t);

t += 0.2;
}else{
x = x0;
}
glutPostRedisplay();
}if(a == 3){

double m = 3.0, c = 0.4, k = 2, w, y, q;
w = sqrt(k / m);

y = c / (2 * sqrt(m * k));
q = w * sqrt(1 - y * y);

if(startFlag == 1){
x = exp(-y * w * t) * (x0 * cos(q * t) + ((y * w * x0) / q) * sin(q * t));

t += 0.2;
}else{
x = x0;
}
glutPostRedisplay();
}
}


int main(int argc, char** argv)
{
glutInit(&argc, argv);
myInit(argv[0]);
glutKeyboardFunc(myKeyboard);
glutDisplayFunc(myDisplay);
glutMouseFunc(myMouseFunc);
glutMotionFunc(myMouseMotion);
glutTimerFunc(samplingTime, myTimer, 1);
glutMainLoop();
return 0;
}

ひえらるきー

タイトルつけ忘れました><

#2

投稿記事 by ひえらるきー » 15年前

タイトルは"classについて教えていただきたい"です^^;
よろしくお願いします。

組木紙織

Re:タイトルつけ忘れました><

#3

投稿記事 by 組木紙織 » 15年前

OPENGLは使った事がないので、指摘が正しいかどうか分かりませんが、
ほかのGUI系のライブラリと比較して、
glutTimerFunc()の第二引数の中でループ毎の動作を書くのだとおもうのですが、
その中でglutTimerFunc()を再度呼び出し、再帰の形をしてるのが気になります。
ライブラリを正しく使えているのでしょうか。
確認をお願いします。


aの値毎に物体の運動だと考えれらる処理を分岐させてますが、複数の物体の処理をしていないので
どう頑張っても一つの物体しか扱えないようになっているんですが、それはいいんでしょうか。

ひえらるきー

Re:タイトルつけ忘れました><

#4

投稿記事 by ひえらるきー » 15年前

> OPENGLは使った事がないので、指摘が正しいかどうか分かりませんが、
> ほかのGUI系のライブラリと比較して、
> glutTimerFunc()の第二引数の中でループ毎の動作を書くのだとおもうのですが、
> その中でglutTimerFunc()を再度呼び出し、再帰の形をしてるのが気になります。
> ライブラリを正しく使えているのでしょうか。
> 確認をお願いします。

この書き方は一応参考書に書いてあったもので動作はうまくいくようになっています。
>
>
> aの値毎に物体の運動だと考えれらる処理を分岐させてますが、複数の物体の処理をしていないので
> どう頑張っても一つの物体しか扱えないようになっているんですが、それはいいんでしょうか。
>
このプログラムに複数の物体を表示させる場合にはm2,c2,k2のようにもう1セットの値を用意して物体の運動の式を書けば2つ描くことはできるのですが、物体をclassにすることでいくつも値を作る必要がないようにしたいんです。物体のclassの中に書きたいと思っているのは、物体の初期座標・サイズ・色・m,c,kの計算などです。よろしくおねがいします。

組木紙織

Re:タイトルつけ忘れました><

#5

投稿記事 by 組木紙織 » 15年前

>この書き方は一応参考書に書いてあったもので動作はうまくいくようになっています。
なら問題ないのかな。



手っ取り早いのが、
物体の運動に関するクラスを用意して、
グローバルな配列やstd::vectorに放り込んで操作するというものです。

class Object
{
private:
/*物体の情報*/
public:
/*物体の動作に関する関数*/
/*物体の表示に関する関数*/
};

std::vector<Objct> vec;//物体のオブジェクトを入れる動的配列。

ISLe

Re:タイトルつけ忘れました><

#6

投稿記事 by ISLe » 15年前

myTimer関数内の座標計算がまったく異なるのでクラスにするとオーバーライドとか手間が増えると思います。
とりあえず(純粋な)構造体を使って考えてみてはいかが?
クラス化するのはその先ということで。

glutTimerFuncはワンショットタイマー(指定時間後に一回コールバックされるだけ)なので繰り返し呼ばないと止まってしまいます。
でもコールバック関数の最初で呼ぶと時間のかかる関数だと再入がかかる気がします。

いちおう構造体使ったコード貼っておきます。

#include<string>
#include<iostream>
#include<cstring>
#include<stdlib.h>
#include<GL/glut.h>
#include<math.h>

unsigned char mouseFlag = GL_FALSE;
float x0;
int samplingTime = 50;
int startFlug;
double xStart;
double yStart;
double startFlag;
double yy;

struct Omori {
float x;
double t;
};

const int OMORI_NUM = 3;
Omori omori[OMORI_NUM];

const int width = 1000, height = 1000;

void myKeyboard(unsigned char key, int x, int y)
{
if (key == 27 ) exit(0);
}

void glutDrawString(const char *str,void *font,float A,float B,float C)
{
glRasterPos3f(0,2,0);
while(*str) {
glutBitmapCharacter(font, *str);
++str;
}
}

void myDisplay(void)
{
int i;

glClear(GL_COLOR_BUFFER_BIT);

for (i=0; i<OMORI_NUM; i++) {
if (i==0) glColor3d(1.0, 0.0, 0.0);
if (i==1) glColor3d(0.0, 1.0, 0.0);
if (i==2) glColor3d(0.0, 0.0, 1.0);

glBegin(GL_LINES);
glVertex2d(-10.0, 0.0);
glVertex2d(omori.x, 0.0);
glEnd();

glPushMatrix();
glTranslated(omori.x, 0.0, 0.0);
glutWireSphere(0.5, 70, 70);
glPopMatrix();
}
glFlush();
}

void myInit(char *progname)
{
glutInitDisplayMode(GLUT_RGBA);
glutInitWindowSize(1000, 1000);
glutInitWindowPosition(0, 0);
glutCreateWindow(progname);
glClearColor(1.0, 1.0, 1.0, 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (double)width / (double)height, 0.1, 200.0);
glMatrixMode(GL_MODELVIEW);
gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

}

void myMouseFunc(int button, int state, int x1, int y1)
{
if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
int i;
for (i=0; i<OMORI_NUM; i++) {
omori.t = 0.0;
}
x0 = 0.0;
startFlag = 0;
yy = 0.0;
xStart = x1;
yStart = y1;
mouseFlag =GL_TRUE;
} else {
mouseFlag = GL_FALSE;
startFlag = 1;
}
}

void myMouseMotion(int xx, int yyy)
{
if(mouseFlag == GL_FALSE) return;
x0 = 0.01 * (xx-xStart);
glutPostRedisplay();
}

void omori_a1(Omori *omori)
{
double m = 2, c = 5, k = 2, w, y, x1, x2, c1, c2;
w = sqrt(k / m);

y = c / (2 * sqrt(m * k));
x1 = -y * w + sqrt(y * y - 1) * w;

x2 = -y * w - sqrt(y * y - 1) * w;

c1 = (x2 / (x2 - x1)) * x0;

c2 = (x1 / (x1 - x2)) * x0;
if(startFlag == 1) {
omori->x = c1 * exp(x1 * omori->t) + c2 *exp(x2 * omori->t);

omori->t += 0.2;
} else {
omori->x = x0;
}
}
void omori_a2(Omori *omori)
{

double m = 2, c = 4, k = 2, w, x1, c1, c2;
w = sqrt(k / m);
x1 = -w;

c1 = x0;

c2 = x0 * w;

if(startFlag == 1) {
omori->x = (c1 + c2 * omori->t) * exp(x1 * omori->t);

omori->t += 0.2;
} else {
omori->x = x0;
}
}
void omori_a3(Omori *omori)
{

double m = 3.0, c = 0.4, k = 2, w, y, q;
w = sqrt(k / m);

y = c / (2 * sqrt(m * k));
q = w * sqrt(1 - y * y);

if(startFlag == 1) {
omori->x = exp(-y * w * omori->t) * (x0 * cos(q * omori->t) + ((y * w * x0) / q) * sin(q * omori->t));

omori->t += 0.2;
} else {
omori->x = x0;
}
}

void myTimer(int value)
{
glutTimerFunc(samplingTime, myTimer, 1);

omori_a1(&omori[0]);
omori_a2(&omori[1]);
omori_a3(&omori[2]);

glutPostRedisplay();
}

int main(int argc, char** argv)
{
glutInit(&argc, argv);
myInit(argv[0]);
glutKeyboardFunc(myKeyboard);
glutDisplayFunc(myDisplay);
glutMouseFunc(myMouseFunc);
glutMotionFunc(myMouseMotion);
glutTimerFunc(samplingTime, myTimer, 1);
glutMainLoop();
return 0;
}

ひえらるきー

Re:タイトルつけ忘れました><

#7

投稿記事 by ひえらるきー » 15年前

今回の目標がclassを用いる練習ということなんでおもす><
一応classを使ってプログラムを作り直してみました。
でもm,c,kの入力を促すようにcout,cinを使っているのですが、そこが上手く動いてくれなくなってしまっています。
そのため、物体の動きの判別もうまく動いてくれなくて困っています。
どうすればよいかどなたか教えていただけないでしょうか?
よろしくお願いします。


#include<string>
#include<iostream>
#include<cstring>
#include<stdlib.h>
#include<GL/glut.h>
#include<math.h>

using namespace std;

unsigned char mouseFlag = GL_FALSE;
int a = 0;
int samplingTime = 50;
int startFlug;
double t = 0.0;
double xStart;
double yStart;
double startFlag;
double yy;
double m1, k1, m2, k2, c1, c2;
double x, x0;


class Omori{

public:


double y, x1, x2, t, w;
double m, c, k;

Omori();

void zeta(int zeta_num);
void Hanbetsu(double m, double c, double k);
void draw(double A, double B, double C, double D, double E, double F);
};


Omori::Omori()
{
x = 0.0;
x0 =0.0;
}

void Omori::Hanbetsu(double m, double c, double k)
{
w = sqrt(k / m);
y = c / (2 * sqrt(m * k));

if(y > 1) a == 1;
if(y == 1) a == 2;
if(y < 1) a == 3;

}

void Omori::zeta(int zeta_num)

{
if(a == 1){
x1 = -y * w + sqrt(y * y - 1) * w;
x2 = -y * w - sqrt(y * y - 1) * w;
c1 = (x2 / (x2 - x1)) * x0;
c2 = (x1 / (x1 - x2)) * x0;
if(startFlag == 1){
x = c1 * exp(x1 * t) + c2 *exp(x2 * t);

t += 0.2;
}else{
x = x0;
}
glutPostRedisplay();
}
else if(a == 2){
x1 = -w;
c1 = x0;
c2 = x0 * w;
if(startFlag == 1){
x = (c1 + c2 * t) * exp(x1 * t);

t += 0.2;
}else{
x = x0;
}
glutPostRedisplay();
}else if(a == 3){
double w, y, q;
w = sqrt(k / m);
y = c / (2 * sqrt(m * k));
q = w * sqrt(1 - y * y);
if(startFlag == 1){
x = exp(-y * w * t) * (x0 * cos(q * t) + ((y * w * x0) / q) * sin(q * t));

t += 0.2;
}else{
x = x0;
}
glutPostRedisplay();
}
}

void Omori::draw(double A, double B, double C, double D, double E, double F)
{
//glClear(GL_COLOR_BUFFER_BIT);
glColor3d(A, B, C);
glBegin(GL_LINES);
glVertex2d(D, E);
glVertex2d(x, E);

glEnd();

glPushMatrix();
glTranslated(x, E, 0.0);
glutWireSphere(F, 30, 30);
glPopMatrix();

glEnd();
glFlush();
}


Omori om1;
Omori om2;
const int width = 1000, height = 1000;

void myKeyboard(unsigned char key, int x, int y)
{
cout << "m1:";
cin >> m1;
cout << "c1:";
cin >> c1;
cout << "k1:";
cin >> k1;
cout << "m2:";
cin >> m2;
cout << "c2:";
cin >> c2;
cout << "k2:";
cin >> k2;

om1.Hanbetsu(m1, c1, k1);
om2.Hanbetsu(m2, c2, k2);

if (key == 27 ) exit(0);
/*if(key == 'a'){
a = 1;
x = 0.0;
x0 = 0.0;
t = 0.0;
}
if(key == 'b'){
a = 2;
x = 0.0;
x0 = 0.0;
t = 0.0;
}
if(key == 'c'){
a = 3;
x = 0.0;
x0 = 0.0;
t = 0.0;
}*/
}

void glutDrawString(const char *str,void *font,float A,float B,float C)
{
glRasterPos3f(0,2,0);
while(*str){
glutBitmapCharacter(font, *str);
++str;
}
}

void myDisplay(void)
{
om1.draw(0.6, 0.0, 0.5, -10.0, 0.8, 0.3);
om2.draw(0.3, 0.3, 0.3, -10.0, -0.8, 0.3);
}


void myInit(char *progname)
{
glutInitDisplayMode(GLUT_RGBA);
glutInitWindowSize(1000, 1000);
glutInitWindowPosition(0, 0);
glutCreateWindow(progname);
glClearColor(1.0, 1.0, 1.0, 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (double)width / (double)height, 0.1, 200.0);
glMatrixMode(GL_MODELVIEW);
gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

}


void myMouseFunc(int button, int state, int x1, int y1)
{
if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN){
startFlag = 0;
t = 0.0;
x = 0.0;
x0 = 0.0;
yy = 0.0;
xStart = x1;
yStart = y1;
mouseFlag =GL_TRUE;
}else{
mouseFlag = GL_FALSE;
startFlag = 1;
}
}


void myMouseMotion(int xx, int yyy)
{
if(mouseFlag == GL_FALSE) return;
x0 = 0.055 * (xx-xStart);
glutPostRedisplay();
}


void myTimer(int value)
{
glutTimerFunc(samplingTime, myTimer, 1);

om1.zeta(a);
om2.zeta(a);
}


int main(int argc, char** argv)
{
glutInit(&argc, argv);
myInit(argv[0]);
glutKeyboardFunc(myKeyboard);
glutDisplayFunc(myDisplay);
glutMouseFunc(myMouseFunc);
glutMotionFunc(myMouseMotion);
glutTimerFunc(samplingTime, myTimer, 1);
glutMainLoop();
return 0;
}

閉鎖

“C言語何でも質問掲示板” へ戻る