Announce

PukiWiki contents have been moved into SONOTS Plugin (20070703)

18.Push

体当たり3Dゲーム

投稿者s1080134
作成日2002/12 (学部3年後期)
最終更新日2003/01
言語C++, OpenGLライブラリ
行数12000
Table of Contents

説明

OpenGL ライブラリを使って作ったゲームです。敵に体当たりをしてフィールドから落とせば勝ちという、ありがちなゲームです。

Push - OpenGL 3D game へどうぞ。

後記:会津大学CG論のプロジェクト。開発時はOpenGL はマシンスペックによって表示速度が変わることに気づかずに、会津大学の環境でまともに動かせるための調整しかしなかった。現在のコンピュータ情勢では早すぎてろくにプレイできないと思われます。

付属シェルスクリプト

OpenGL を使ったプログラムのコンパイルを楽にするためのシェルスクリプトです。 元々は たかなしさん (s1061099) が作ってくれたものの改変です。

% ln -s gl.sh bin/gl (C実行ファイル)
% ln -s gl.sh bin/gllib (Cオブジェクトファイル)
% ln -s gl.sh bin/gl++ (C++実行ファイル)
% ln -s gl.sh bin/gllib++ (C++オブジェクトファイル)

とシンボリックリンクを作成し、実行時のコマンドの名前で処理を変えるという技を使っていたりします。

後記:完全に会津大学依存です。

gl.sh

#!/bin/sh
######									######
#	                                                         	     #
#	    		      GLgcc(Non aux)				     #
#   			      Made By Taka				     #
#	                                                        2000 6/8     #
#					         Last modified: 2002 10/15   #
#                                                modified by Naotoshi Seo    #
#                                                Last modified: 2002 11/27   #
######									######

if [ $# -lt 1 ]; then
  exit;
fi

if [ -x /bin/uname ]; then
   OS=`uname -s`
fi
case "$OS" in 
  # For Solaris
    SunOS )
      LD_LIBRARY_PATH=/usr/local/X11R6.4/lib
      export LD_LIBRARY_PATH
      if [ $0 = /home/student/s1080134/bin/gllib ]; then
	echo "Now make C object file..."
	exec /usr/local/gnu/bin/gcc -fpcc-struct-return -O2 \
	-I. -I/usr/local/X11R6.4/include \
	-I/home/student/s1080134/usr/Solaris/include -c "$@"
      elif [ $0 = /home/student/s1080134/bin/gl ]; then
	echo "Now Make C execution file..."
	exec /usr/local/gnu/bin/gcc "$@" -fpcc-struct-return -O2 \
	-I. -I/usr/local/X11R6.4/include \
	-I/home/student/s1080134/usr/Solaris/include \
	-L/usr/local/X11R6.4/lib \
	-L/home/student/s1080134/usr/Solaris/lib \
	-lXext -lX11 -lXi -lXmu -lglut -lGL -lGLU -lm -lglpng
      elif [ $0 = /home/student/s1080134/bin/gllib++ ]; then
	echo "Now make C++ object file..."
	exec /usr/local/bin/g++  \
	-I. -I/usr/local/X11R6.4/include \
	-I/home/student/s1080134/usr/Solaris/include -c "$@"
      elif [ $0 = /home/student/s1080134/bin/gl++ ]; then
	echo "Now Make C++ execution file..."
	exec /usr/local/bin/g++ "$@" \
	-I. -I/usr/local/X11R6.4/include \
	-I/home/student/s1080134/usr/Solaris/include \
	-L/usr/local/X11R6.4/lib \
	-L/home/student/s1080134/usr/Solaris/lib \
	-lXext -lX11 -lXi -lXmu -lglut -lGL -lGLU -lm -lglpng          
      fi
    ;;
    
    # For IRIX
      IRIX )
	LD_LIBRARY_PATH=/usr/local/X11R6.4/lib
	export LD_LIBRARY_PATH
	if [ $0 = /home/student/s1080134/bin/gllib ]; then
	  echo "Now make C object file..."
	  exec /usr/sbin/gcc \
	  -I/home/student/s1080134/usr/IRIX/include -n32 -c  "$@"
	elif [ $0 = /home/student/s1080134/bin/gl ]; then
	  echo "Now Make C execution file..."
	  exec /usr/sbin/gcc "$@" \
	  -I. -I/home/student/s1080134/usr/IRIX/include \
	  -L/home/student/s1080134/usr/IRIX/lib\
	  -n32 -L/usr/lib32 \
	  -lglpng -lglut -lGL -lGLU -lXext -lXmu -lX11 -lm 
	elif [ $0 = /home/student/s1080134/bin/gllib++ ]; then
	  echo "Now make C++ object file..."
	  exec /usr/local/bin/g++ -I/usr/local/X11R6.4/include \
	  -I/home/student/s1080134/usr/IRIX/include -c "$@"
       elif [ $0 = /home/student/s1080134/bin/gl++ ]; then
	 echo "Now Make C++ execution file..."
	 exec /usr/local/bin/g++ -I/usr/local/X11R6.4/include "$@" \
	 -L/usr/local/X11R6.4/lib -L/usr/lib32 \
	 -Wl,-rpath -Wl,/usr/local/X11R6.4/lib \
	 -I/home/student/s1080134/usr/IRIX/include \
	  -L/home/student/s1080134/usr/IRIX/lib \
	  -lglpng -lglut -lGL -lGLU -lXext -lXmu -lX11 -lXi -lm 
	fi
	
      ;;
    esac
    #-I/usr/local/X11R6.4/include/ \
    #-I/usr/local/X11R6.4/include -L/usr/local/X11R6.4/lib \ 
    #-I/usr/local/Mesa-4.1/include -L/usr/local/Mesa-4.1/lib32 \
    #-L. -L/usr/lib32 \
    #-I/home/grd/m5051108/include -L/home/grd/m5051108/lib/sgi \
    #-I/home/student/s1080134/usr/IRIX/include -L/home/student/s1080134/usr/IRIX/lib \
    #-I/home/student/s1061099/Solaris8/include -L/home/student/s1061099/Solaris8/lib \

付属ライブラリ

Vector3d(OpenGL 用三次元ベクトル計算ライブラリ)

OpenGL 用の三次元ベクトル計算ライブラリです。 OpenGL には glRotate などのモデルビュー変換用の関数は用意してあるのですが、結局どの座標に移動したか取得する関数がないっぽい(たぶん)ので、自前で座標を計算するライブラリを作りました。

外積、内積、絶対値、正規化、 X軸中心の回転、Y軸中心の回転、Z軸中心の回転、任意の軸中心の回転、平行移動、拡大縮小、などの関数を用意してあります。 + 演算子等も用意してあります。Vector3d * スカラー、Vector3d * 3x3 行列などもできます。

Vector3d.h

/* Vector3d.h	-- Naotoshi Seo 2002 11/26*/

#include <stdlib.h>
#include <math.h>
#include <GL/gl.h>
#include <iostream>

#ifndef _VECTOR3D_H_
#define _VECTOR3D_H_

#ifndef M_PI
#define M_PI 3.14159265358979323846264338327
#endif

struct Angle{
  double theta;//zx
  double phai;//zy
  Angle():theta(0),phai(0){}
  Angle(const double & t,const double & p):theta(t),phai(p){}
};

class Vector3d{
public:
  double x, y, z;

  Vector3d::Vector3d();
  Vector3d::Vector3d( const double& x, const double& _y, const double& _z);
  Vector3d::Vector3d( const double [] );
  
 /* 設定 */
  void Vector3d::set( const double&, const double&, const double& );
  void Vector3d::set( const double []);
  void Vector3d::set( void );
  void Vector3d::reset( void );
  void Vector3d::glVertex( void ) const;
  friend void std::glVertex(const Vector3d & v);
  void Vector3d::glTranslate( void ) const;
  friend void std::glTranslate(const Vector3d & v);
  void Vector3d::glScale( void ) const;
  friend void std::glScale(const Vector3d & v);
  void Vector3d::glRotate( const double & angle ) const;
  friend void std::glRotate(const double & angle,const Vector3d & v);
  void Vector3d::glColor() const;  
  friend void std::glColor(const Vector3d & color);
  void Vector3d::glColor(const double & alpha) const ;  
  friend void std::glColor(const Vector3d & color,const double & alpha);
  void Vector3d::glLightModel (const GLenum &pname) const;
  friend void std::glLightModel (const GLenum &pname,const Vector3d & param);
  void Vector3d::glLightModel (const GLenum &pname,const float &alpha) const;
  friend void std::glLightModel (const GLenum &pname,const Vector3d & param,const float & alpha);
  void Vector3d::glLight(const GLenum &light, const GLenum &pname) const;
  friend void std::glLight(const GLenum &light, const GLenum &pname, const Vector3d & param);
  void Vector3d::glLight(const GLenum &light, const GLenum &pname, const float & fourth) const;
    friend void std::glLight(const GLenum &light, const GLenum &pname, const Vector3d & param, const float & fourth);
  void Vector3d::glMaterial(const GLenum & face, const GLenum & pname) const;
  friend void std::glMaterial(const GLenum & face, const GLenum & pname, const Vector3d & color);
  void Vector3d::glMaterial(const GLenum & face, const GLenum & pname,const float & alpha) const;
  friend void std::glMaterial(const GLenum & face, const GLenum & pname, const Vector3d & color,const float & alpha);
  /*
  void Vector3d::glMaterial() const;
  friend void std::glMaterial(const Vector3d & color);
  void Vector3d::glMaterial(const double & alpha) const;
  friend void std::glMaterial(const Vector3d & color,const double & alpha);
  */
  friend void std::resetMaterial();
  void Vector3d::glNormal() const;
  friend void std::glNormal(const Vector3d & normal);
  /* 絶対値(長さ)を返す */
  double Vector3d::abs( void ) const;
  /* 絶対値の2乗 */
  double Vector3d::abs2( void ) const;
  /* 外積 */
  Vector3d Vector3d::cross( const Vector3d & ); 
  /* 内積 */
  double Vector3d::dot( const Vector3d & );
  /* ガンマ */
  double Vector3d::gamma( void ) const;
  double Vector3d::ugamma( void ) const;
  void Vector3d::v2uv( void );
  void Vector3d::uv2v( void );
  /* 正規化*/
  void Vector3d::norm( void );

  // v1.cross(v2) に同じ  ( cross(v1.v2) のように使える) 
  friend Vector3d std::cross( const Vector3d &, const Vector3d & ); 
  friend double std::dot( const Vector3d &, const Vector3d & );
  friend double std::abs( const Vector3d & );
  friend double std::abs2( const Vector3d & );
  /* Vector3d を double 型のポインタに変換 */
  double * Vector3d::convert2double( void ) const;
  friend double * std::convert2double( const Vector3d &);
  float * Vector3d::convert2float( void ) const;
  friend float * std::convert2float( const Vector3d &);

  /* 2ベクトル間の角度 thisを基準に考えた*/
  Angle Vector3d::angle(const Vector3d &);
  /* X 軸を中心にして( y軸 -> z軸 ) angle(radian) だけ回転 */
  void Vector3d::rotateX(const double &angle);
  /* Y 軸を中心にして( z軸 -> x軸 ) angle(radian) だけ回転 */
  void Vector3d::rotateY(const double &angle);
  /* Z 軸を中心にして( y軸 -> z軸 ) angle(radian) だけ回転 */
  void Vector3d::rotateZ(const double &angle);
  /* axe を軸にして angle(radian)だけ回転 */
  void Vector3d::rotateAxe(const double &angle, const double &axe_x, const double &axe_y, const double &axe_z);
  void Vector3d::rotateAxe(const double & angle, const Vector3d &axe);
  /* tr を足して 平行移動 */
  void Vector3d::translate(const double &_x,const double &_y,const double &_z);
  void Vector3d::translate(const Vector3d &tr);
  /* v に sc をかけて 拡大縮小 */
  void Vector3d::scale(const double &_x,const double & _y, const double & _z);
  void Vector3d::scale(const Vector3d & sc);

  // unary operators
  Vector3d & Vector3d::operator  = ( const Vector3d & );
  Vector3d & Vector3d::operator += ( const Vector3d & );
  Vector3d & Vector3d::operator -= ( const Vector3d & );
  Vector3d & Vector3d::operator *= ( const double& );
  Vector3d & Vector3d::operator *= ( const Vector3d & );
  Vector3d & Vector3d::operator *= ( const Vector3d []);  //3x3行列との掛け算
  Vector3d & Vector3d::operator /= ( const double& );
  Vector3d & Vector3d::operator /= ( const Vector3d & );
  friend Vector3d std::operator + ( const Vector3d & );
  friend Vector3d std::operator - ( const Vector3d & );

  // binary operators
  friend Vector3d std::operator + ( const Vector3d &, const Vector3d & );
  friend Vector3d std::operator - ( const Vector3d &, const Vector3d & );
  friend Vector3d std::operator * (const Vector3d &,const Vector3d []);  //3x3行列との掛け算

  friend Vector3d std::operator * ( const double&, const Vector3d & );
  friend Vector3d std::operator * ( const Vector3d &, const double& );
  friend Vector3d std::operator * ( const Vector3d &, const Vector3d & );
  friend Vector3d std::operator / ( const Vector3d &, const double& );
  friend Vector3d std::operator / ( const Vector3d &, const Vector3d & );

  // logical operators
  friend bool std::operator == ( const Vector3d &,  const Vector3d &  );
  friend bool std::operator != ( const Vector3d &,  const Vector3d &  );

#ifdef _IOSTREAM_H
  // stream operators
  friend ostream & std::operator<< ( ostream &s, Vector3d v );
  friend istream & std::operator>> ( istream &s, Vector3d v );
#endif 
};

#endif

Vector3d.cpp

/* Vector3d.cpp	-- Naotoshi Seo 2002 11/25*/
#include <stdlib.h>
#include <math.h>
#include <GL/gl.h>
#include <iostream>
#include "../include/Vector3d.h"

//#define DEBUG

#ifdef DEBUG
#include <stdio.h>
#include <iostream.h>
int main(){
  Vector3d v(0.0,4.0,0.0);
  Vector3d axe(0.0,1.0,1.0);
  cout << "initial v "<<v << endl;
  cout << "initial axe "<<axe << endl;
  v=v.rotateAxe(M_PI,axe);
  cout << "after v " << v<< endl;
  return 1;
}
#endif

Vector3d::Vector3d( void )
  : x( 0.0 ), y( 0.0 ), z( 0.0 ) {}

Vector3d::Vector3d( const double& _x, const double& _y, const double& _z )
  : x( _x ), y( _y ), z( _z ) {}

Vector3d::Vector3d( const double d[])
  :x(d[0]) , y(d[1]) , z(d[2]){}


void Vector3d::set( const double& _x, const double& _y, const double& _z )
{
  x = _x ; y = _y ; z = _z ;
}

void Vector3d::set( const double d[] )
{
  x = d[0]; y = d[1]; z =d[2];
}

void Vector3d::reset( void ){ x = 0.0 ; y = 0.0 ; z = 0.0 ; }

void Vector3d::glVertex( void ) const{
  glVertex3d(x,y,z);
}
void std::glVertex(const Vector3d & v){
  glVertex3d(v.x,v.y,v.z);
}
void Vector3d::glTranslate( void ) const{
  glTranslated(x,y,z);
}
void std::glTranslate(const Vector3d & v){
  glTranslated(v.x,v.y,v.z);
}
void Vector3d::glScale( void ) const{
  glScaled(x,y,z);
}
void std::glScale(const Vector3d & v){
  glScaled(v.x,v.y,v.z);
}
void Vector3d::glRotate( const double & angle ) const{
  glRotated(angle,x,y,z);
}
void std::glVertex(const double & angle,const Vector3d & v){
  glRotated(angle,v.x,v.y,v.z);
}

void Vector3d::glColor() const{
  glColor3d(x,y,z);
}
void std::glColor(const Vector3d & color){
  glColor3d(color.x,color.y,color.z);
}
void Vector3d::glColor(const double & alpha) const{
  glColor4d(x,y,z,alpha);
}
void std::glColor(const Vector3d & color,const double & alpha){
  glColor4d(color.x,color.y,color.z,alpha);
}

void 
Vector3d::glLightModel (const GLenum &pname) const{
  float param[4];
  param[0]=(float)x;
  param[1]=(float)y;
  param[2]=(float)z;
  param[3]=1.0;
  glLightModelfv(pname,param);
}
void 
std::glLightModel (const GLenum &pname,const Vector3d & p){
  float param[4];
  param[0]=(float)p.x;
  param[1]=(float)p.y;
  param[2]=(float)p.z;
  param[3]=1.0;
  glLightModelfv(pname,param);
}
void 
Vector3d::glLightModel (const GLenum &pname,const float &alpha) const{
  float param[4];
  param[0]=(float)x;
  param[1]=(float)y;
  param[2]=(float)z;
  param[3]=alpha;
  glLightModelfv(pname,param);
}
void 
std::glLightModel (const GLenum &pname,const Vector3d & p,const float & alpha){
  float param[4];
  param[0]=(float)p.x;
  param[1]=(float)p.y;
  param[2]=(float)p.z;
  param[3]=alpha;
  glLightModelfv(pname,param);
}


void 
Vector3d::glLight(const GLenum &light, const GLenum &pname) const{
  float param[4];
  param[0]=(float)x;
  param[1]=(float)y;
  param[2]=(float)z;
  param[3]=1.0;
  glLightfv(light,pname,param);
}

void 
std::glLight(const GLenum &light, const GLenum &pname, const Vector3d & p){
  float param[4];
  param[0]=(float)p.x;
  param[1]=(float)p.y;
  param[2]=(float)p.z;
  param[3]=1.0;
  glLightfv(light,pname,param);
}

void 
Vector3d::glLight(const GLenum &light, const GLenum &pname, const float & fourth) const{
  float param[4];
  param[0]=(float)x;
  param[1]=(float)y;
  param[2]=(float)z;
  param[3]=(float)fourth;
  glLightfv(light,pname,param);
}

void 
std::glLight(const GLenum &light, const GLenum &pname, const Vector3d & p, const float & fourth){
  float param[4];
  param[0]=(float)p.x;
  param[1]=(float)p.y;
  param[2]=(float)p.z;
  param[3]=(float)fourth;
  glLightfv(light,pname,param);
}  

void Vector3d::glMaterial(const GLenum & face, const GLenum & pname) const{
  float color[4];
  color[0]=(float)x;
  color[1]=(float)y;
  color[2]=(float)z;
  color[3]=1.0;
  glMaterialfv(face,pname,color);
}
void std::glMaterial(const GLenum & face, const GLenum & pname, const Vector3d & c){
  float color[4];
  color[0]=(float)c.x;
  color[1]=(float)c.y;
  color[2]=(float)c.z;
  color[3]=1.0;
  glMaterialfv(face,pname,color);
}
void Vector3d::glMaterial(const GLenum & face, const GLenum & pname,const float & alpha) const{
  float color[4];
  color[0]=(float)x;
  color[1]=(float)y;
  color[2]=(float)z;
  color[3]=(float)alpha;
  glMaterialfv(face,pname,color);
}
void std::glMaterial(const GLenum & face, const GLenum & pname, const Vector3d & c,const float & alpha){
  float color[4];
  color[0]=(float)c.x;
  color[1]=(float)c.y;
  color[2]=(float)c.z;
  color[3]=(float)alpha;
  glMaterialfv(face,pname,color);
}

/*
void Vector3d::glMaterial() const{
  float *color;
  color=this->convert2float();
  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color);
  color[0]/=4;
  color[1]/=4;
  color[2]/=4;  
  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color);
  delete color;  
}
void std::glMaterial(const Vector3d & c){
  c.glMaterial();
}
void Vector3d::glMaterial(const double & alpha) const{
  float color[4];
  color[0]=(float)x;
  color[1]=(float)y;
  color[2]=(float)z;
  color[3]=(float)alpha;
  resetMaterial();
  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color);
  color[0]/=4;
  color[1]/=4;
  color[2]/=4;
  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color);  
}

void std::glMaterial(const Vector3d & c,const double & alpha){
  c.glMaterial(alpha);
  
  //glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);
  //glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color);
  //glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, color);
  //glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color);
  
}*/

void std::resetMaterial(){
  float ambient[]={0.2,0.2,0.2,1.0};
  float diffuse[]={0.8,0.8,0.8,1.0};
  float specular[]={0.0,0.0,0.0,1.0};
  float shininess=0.0;
  float emission[]={0.0,0.0,0.0,1.0};
  glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
  glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, emission);
  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient);
  glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
}
void Vector3d::glNormal() const{
  glNormal3d(x,y,z);
}
void std::glNormal(const Vector3d & normal){
  glNormal3d(normal.x,normal.y,normal.z);
}

double Vector3d::abs2( void ) const
{
  return( x*x + y*y + z*z );
}

double Vector3d::abs( void ) const
{
  return sqrt( x*x + y*y + z*z );
}

Vector3d Vector3d::cross( const Vector3d & v ) // 外積
{
  return Vector3d( y*v.z - z*v.y ,z*v.x - x*v.z ,x*v.y - y*v.x );
}

double Vector3d::dot( const Vector3d & v ) //内積
{
  return ( x*v.x + y*v.y + z*v.z );
}

double Vector3d::gamma( void ) const
{
  return 1.0 / sqrt( 1.0 - x*x - y*y - z*z );
}

double Vector3d::ugamma( void ) const
{
  return sqrt( 1.0 + x*x + y*y + z*z );
}

void Vector3d::v2uv( void )
{
  double f = 1.0 / sqrt( 1.0 - x*x - y*y - z*z );
  set( f*x, f*y, f*z );
}

void Vector3d::uv2v( void )
{
  double f = 1.0 / sqrt( 1.0 + x*x + y*y + z*z );
  set( f*x, f*y, f*z );
}

void
Vector3d::norm()
{
  double leng;
  leng=this->abs();
  set(x/leng,y/leng,z/leng);
}

// friend function
Vector3d std::cross( const Vector3d & a, const Vector3d & v )
{
  return Vector3d( a.y*v.z - a.z*v.y ,a.z*v.x - a.x*v.z ,a.x*v.y - a.y*v.x );
}
double std::dot( const Vector3d & a, const Vector3d & v )
{
  return ( a.x*v.x + a.y*v.y + a.z*v.z );
}
double std::abs( const Vector3d & v )
{
  return( v.Vector3d::abs() );
}
double std::abs2( const Vector3d & v )
{
  return( v.Vector3d::abs2() );
}

double *
Vector3d::convert2double() const
{
  double *ret;
  ret = new double[3];
  ret[0]=x;
  ret[1]=y;
  ret[2]=z;
  return ret;
}

double * std::convert2double( const Vector3d & v){
  return v.Vector3d::convert2double();
}
float *
Vector3d::convert2float() const
{
  float *ret;
  ret = new float[3];
  ret[0]=(float)x;
  ret[1]=(float)y;
  ret[2]=(float)z;
  return ret;
}

float * std::convert2float( const Vector3d & v){
  return v.Vector3d::convert2float();
}

//Angle * にしてアドレス渡しにしたほうが早いが、使いにくくなるのでパス
Angle
Vector3d::angle(const Vector3d &v){
  //thisを基準にした引数の角度
  double z = this->z;
  if(z==0)z+=0.0000000000000000000001;
  double theta1 = atan(this->x/z);
  if(z<0)theta1 += M_PI;
  double phai1 = atan(this->y/sqrt(pow(this->x,2)+pow(z,2)));
  phai1 = -phai1; //正方向
  //z軸との角度。thetaはzx平面(Y軸) phai はzy 平面(X軸)
  //Vector3d(0,0,1).angle(v)ならこの値になる。
  //Vector3d(1,0,0).angle(v)ならx軸との角度になる
  z = v.z;
  if(z==0)z+=0.0000000000000001;
  double theta2 = atan(v.x/z);
  if(z<0)theta2 +=M_PI;
  double phai2 = atan(v.y/sqrt(pow(v.x,2)+pow(z,2)));
  phai2 = -phai2; //正方向
  double theta = theta2 - theta1;
  double phai = phai2 - phai1;
  while(theta>2*M_PI){
    theta-=2*M_PI;
  }
  while(theta<0){
    theta+=2*M_PI;
  }
  if(theta>M_PI){theta -= 2*M_PI;}//-M_PI ~ M_PI に
  while(phai>2*M_PI){
    phai-=2*M_PI;
  }
  while(phai<0){
    phai+=2*M_PI;
  }
  if(phai>M_PI){phai -= 2*M_PI;}//-M_PI ~ M_PI に

  return Angle(theta,phai);
}

void
Vector3d::rotateX(const double &angle){
  Vector3d mat[3];
 
  mat[0].set(1.0,0.0,0.0);
  mat[1].set(0.0,cos(angle),sin(angle));
  mat[2].set(0.0,-sin(angle),cos(angle));
  (*this) *= mat;
}

void
Vector3d::rotateY(const double &angle){
  Vector3d mat[3];

  mat[0].set(cos(angle),0.0,-sin(angle));
  mat[1].set(0.0,1.0,0.0);
  mat[2].set(sin(angle),0.0,cos(angle));

  (*this) *= mat;
}

void
Vector3d::rotateZ(const double& angle){
  Vector3d mat[3];
  mat[0].set(cos(angle),sin(angle),0.0);
  mat[1].set(-sin(angle),cos(angle),0.0);
  mat[2].set(0.0,0.0,1.0);

  (*this) *= mat;
}

//yを小さい数にすると誤差がでるかも。
void
Vector3d::rotateAxe(const double &angle, const double& axe_x, const double &axe_y, const double &axe_z){
  Vector3d axe;
  double theta;
  double phai;

  if(axe_y==0){axe.set(axe_x,0.000000000000000000000000001,axe_z);}
  else {axe.set(axe_x,axe_y,axe_z);}

  //軸をxy平面に降ろしたベクトルとY軸との角度theta
  theta=atan(axe.x/axe.y);
  theta=-theta;//正回転
  if(axe.y<0)theta+=M_PI;

  //Vector3d tmp=axe;
  //axeをz軸中心に-theta 回転に同じ
  axe.set(0.0,sqrt(pow(axe.y,2)+pow(axe.x,2)),axe.z);
  // Y軸との角度 phai. 範囲は-M_PI/2 ~ M_PI/2 で十分
  phai = atan(axe.z/axe.y);

  //vをZ軸中心に-theta回転させる
  this->rotateZ(-theta);
  //vをX軸中心に-phai回転させる
  this->rotateX(-phai);
  //vをY軸中心にangle回転させる
  this->rotateY(angle);
  //戻す
  this->rotateX(phai);
  this->rotateZ(theta);
}

void
Vector3d::rotateAxe(const double &angle, const Vector3d &axe){
  this->rotateAxe(angle,axe.x,axe.y,axe.z);
}


void 
Vector3d::translate(const double& _x,const double &_y,const double& _z){
  this->set(x*_x, y*_y, z+_z);
}

void
Vector3d::translate(const Vector3d& tr){
 (*this) += tr;
}

void
Vector3d::scale(const double &_x, const double &_y, const double &_z){
  this->set(x*_x, y*_y, z*_z);
}

void
Vector3d::scale(const Vector3d &sc){
  this->scale(sc.x,sc.y,sc.z);
}

// ----  operators ------

// unary operators
Vector3d & Vector3d::operator = ( const Vector3d & v )
{
  x = v.x ; y = v.y ; z = v.z ;
  return *this;
}

Vector3d & Vector3d::operator += ( const Vector3d & v )
{
  x += v.x ; y += v.y ; z += v.z ;
  return *this;
}

Vector3d & Vector3d::operator -= ( const Vector3d & v )
{
  x -= v.x ; y -= v.y ; z -= v.z ;
  return *this;
}

Vector3d & Vector3d::operator *= ( const double& d )
{
  x *= d ; y *= d ; z *= d ;
  return *this;
}

Vector3d & Vector3d::operator *= ( const Vector3d & v )
{
  x *= v.x;
  y *= v.y;
  z *= v.z;
  return *this;
}

Vector3d & Vector3d::operator *= ( const Vector3d mat[])
{
  double x=this->x;
  double y=this->y;
  double z=this->z;
  this->x = x * mat[0].x + y* mat[1].x + z*mat[2].x;
  this->y = x * mat[0].y + y* mat[1].y + z*mat[2].y;
  this->z = x * mat[0].z + y* mat[1].z + z*mat[2].z;
  return *this;
}

Vector3d & Vector3d::operator /= ( const double& d )
{
  x /= d ; y /= d ; z /= d ;
  return *this;
}

Vector3d & Vector3d::operator /= ( const Vector3d & v)
{
  x /= v.x;
  y /= v.y;
  z /= v.z;
  return *this;
}


Vector3d std::operator + ( const Vector3d & v )
{
  return v;
}

Vector3d std::operator - ( const Vector3d & v )
{
  return Vector3d( -v.x, -v.y, -v.z );
}

// binary operators
Vector3d std::operator + ( const Vector3d & a, const Vector3d & b )
{
  return Vector3d( a.x+b.x, a.y+b.y, a.z+b.z );
}

Vector3d std::operator - ( const Vector3d & a, const Vector3d & b )
{
  return Vector3d( a.x-b.x, a.y-b.y, a.z-b.z );
}

Vector3d std::operator * ( const Vector3d & v, const Vector3d mat[])
{
  return Vector3d( v.x * mat[0].x + v.y* mat[1].x + v.z*mat[2].x,
		   v.x * mat[0].y + v.y* mat[1].y + v.z*mat[2].y,
		   v.x * mat[0].z + v.y* mat[1].z + v.z*mat[2].z);
}
		   
// vector and scholar operations
Vector3d std::operator * ( const double& d, const Vector3d & v ) 
{
  return Vector3d( d * v.x, d * v.y, d * v.z );
}

Vector3d std::operator * ( const Vector3d & v, const double& d )
{
  return Vector3d( d * v.x, d * v.y, d * v.z );
}

Vector3d std::operator * ( const Vector3d & v1, const Vector3d & v2)
{
  return Vector3d( v1.x*v2.x, v1.y*v2.y, v1.z*v2.z );
}

Vector3d std::operator / ( const Vector3d & v, const double& d )
{
  return Vector3d( v.x/d , v.y/d, v.z/d );
}

Vector3d std::operator / ( const Vector3d &v1, const Vector3d &v2 )
{
  return Vector3d( v1.x/v2.x, v1.y/v2.y, v1.z/v2.z );
}
// logical operators
bool std::operator == ( const Vector3d & a, const Vector3d & b )
{
  return (( a.x == b.x ) && ( a.y == b.y ) && ( a.z == b.z ));
}
bool std::operator != ( const Vector3d & a, const Vector3d & b )
{
   return (( a.x != b.x ) || ( a.y != b.y ) || ( a.z != b.z ));
}

#ifdef _IOSTREAM_H
// stream operators 
ostream & std::operator<< ( ostream &s, Vector3d v )
{
  s << "(" << v.x << " , " << v.y << " , " << v.z <<")";
  return s;
}

istream & std::operator>> ( istream &s, Vector3d &v )
{
  s >> v.x >> v.y >> v.z;
  return s;
}
#endif

Camera(OpenGL 用カメラ座標計算ライブラリ)

OpenGL 用のカメラ座標計算ライブラリです。上の Vector3d をインクルードして使っています。

任意の座標を通る X 軸と平行なベクトルを軸とした回転(もちろん Y 軸、 Z 軸 バージョンもあり)、任意の座標を通る任意のベクトルを軸とした回転、任意の座標を中心に右回転、下回転、指定した角度の方向に回転(0 で右回転, PI/2 で下回転)、カメラの位置を平行移動、カメラの位置を上、下、左、右、前、後ろに移動、カメラの up ベクトルを回転、などの関数を用意してあります。

CameraTest.cpp が使い方例です。

Camera.h

/* Camera.h 
   Naotoshi Seo 2002 11/25 */

#include <stdlib.h>
#include <GL/glu.h>
#include <math.h>
#include <iostream>
#include "Vector3d.h"


#ifndef _CAMERA_H
#define _CAMERA_H

class Camera{
public:
  Vector3d eye;
  Vector3d center;
  Vector3d up;

  Camera();
  Camera(const Vector3d &eye,const Vector3d &center,const Vector3d &up);
  Camera(const Vector3d v[]);
  Camera(const double &eye_x,const double &eye_y,const double &eye_z,
	 const double &center_x,const double &center_y,const double &center_z,
	 const double &up_x,const double &up_y, const double &up_z);
  Camera(const double d[]);
  
  /* 設定 */
  void reset(void);
  void set(const Vector3d &eye,const Vector3d &center,const Vector3d &up);
  void set(const Vector3d v[]);
  void set(const double &eye_x,const double &eye_y,const double &eye_z,
	 const double &center_x,const double &center_y,const double &center_z,
	 const double &up_x,const double &up_y, const double &up_z);
  void set(const double d[]);


  /* gluLookAt に設定 */
  void gluLookAt(void) const;
  friend void std::gluLookAt( const Camera & );

  /* up ベクトルをcenter-eyeに垂直な本当のupベクトルに変換する*/
  void convert2trueUp(void);

  /* camera の up ベクトルを center-eye ベクトルを軸として回転*/
  void upRotate(const double &angle);
  
  /* camera の位置をX軸に平行な _centerを通るベクトルを軸にして回転 
     普通は _center には camera.center でいいと思う*/
  void eyeRotateX(const Vector3d &_center,const double &angle);
  
  /* camera の位置をY軸に平行な_centerを通るベクトルを軸にして回転
     以下同文*/
  void eyeRotateY(const Vector3d &_center,const double &angle);
  
  /* camera の位置をZ軸に平行な_centerを通るベクトルを軸にして回転
     以下同文*/
  void eyeRotateZ(const Vector3d &_center,const double &angle);
  
  /* camera の位置を指定した軸に平行な_centerを通る軸を中心にして回転
     以下同文 */
  void eyeRotateAxe(const Vector3d & _center,const double &angle,const Vector3d &axe);
  
  /* camera の位置を _center 中心に横回転(右回転が正) 
     以下同文*/
  void eyeRotate2Right(const Vector3d &_center,const double &angle);
  
  /* camera の位置を _center 中心に横回転(下回転が正) 
     以下同文*/
  void eyeRotate2Down(const Vector3d &_center,const double &angle);
  
  /* camera の位置を _center 中心に任意の方向に回転。
     phai が 0 のとき右に。PI/4 なら 右下に。
     以下同文*/
  void eyeRotate(const Vector3d &_center,const double &angle,const double &phai);

  /* camera のcenter位置をX軸に平行な _centerを通るベクトルを軸にして回転 
     普通は _center には camera.eye でいいと思う*/
  void centerRotateX(const Vector3d &_center,const double &angle);
  
  /* camera のcenter位置をY軸に平行な_centerを通るベクトルを軸にして回転
     以下同文*/
  void centerRotateY(const Vector3d &_center,const double &angle);
  
  /* camera のcenter位置をZ軸に平行な_centerを通るベクトルを軸にして回転
     以下同文*/
  void centerRotateZ(const Vector3d &_center,const double &angle);
  
  /* camera のcenter位置を指定した軸に平行な_centerを通る軸を中心にして回転
     以下同文 */
  void centerRotateAxe(const Vector3d & _center,const double &angle,const Vector3d &axe);
  
  /* camera のcenter位置を _center 中心に横回転(右回転が正) 
     以下同文*/
  void centerRotate2Right(const Vector3d &_center,const double &angle);
  
  /* camera のcenter位置を _center 中心に横回転(下回転が正) 
     以下同文*/
  void centerRotate2Down(const Vector3d &_center,const double &angle);
  
  /* camera のcenter位置を _center 中心に任意の方向に回転。
     phai が 0 のとき右に。PI/4 なら 右下に。
     以下同文*/
  void centerRotate(const Vector3d &_center,const double &angle,const double &phai);
  
  /* camera の位置を平行移動*/
  void translate(const Vector3d &trans);
  void translate(const double &trans_x,const double &trans_y,const double &trans_z);
  
  /* camera の位置を上(upベクトル)にlength 移動*/
  void upTranslate(const double &length);
  
  /* camera の位置を右に移動*/
  void rightTranslate(const double &length);

  /* camera の位置を下に移動*/
  void downTranslate(const double &length);

   /* camera の位置を左に移動*/
  void leftTranslate(const double &length);
 
  /* camera の位置を前に移動*/
  void forwardTranslate(const double &length);
  
  /* camera の位置を後ろに移動*/
  void backTranslate(const double &length);
  
  /* camera の成分をエラー出力*/
  void print(void);

  Camera & operator  = ( const Camera & );
  Camera & operator += ( const Camera & );
  Camera & operator -= ( const Camera & );
  Camera & operator *= ( const double& );
  Camera & operator *= ( const Camera& );
  Camera & operator /= ( const double& );
  Camera & operator /= ( const Camera& );
  friend Vector3d std::operator + ( const Vector3d & );
  friend Vector3d std::operator - ( const Vector3d & ); 

  // binary operators
  friend Camera std::operator + ( const Camera &, const Camera & );
  friend Camera std::operator - ( const Camera &, const Camera & );

  friend Camera std::operator * ( const double&, const Camera & );
  friend Camera std::operator * ( const Camera &, const double& );
  friend Camera std::operator * ( const Camera &, const Camera& );
  friend Camera std::operator / ( const Camera &, const double& );
  friend Camera std::operator / ( const Camera &, const Camera& );

  // logical operators
  friend bool std::operator == ( const Camera &,  const Camera &  );
  friend bool std::operator != ( const Camera &,  const Camera &  );

#ifdef _IOSTREAM_H
  // stream operators
  friend ostream &std::operator<< ( ostream &s, Camera v );
  friend istream &std::operator>> ( istream &s, Camera v );
#endif

};

#endif

Camera.cpp

/* Camera.cc 
   Naotoshi Seo  2002 11/25 */

#include <stdlib.h>
#include <GL/glut.h>
#include <GL/glu.h>
#include <GL/gl.h>
#include <math.h>
#include <iostream>
#include "../include/Vector3d.h"
#include "../include/Camera.h"

//#define DEBUG
#ifdef DEBUG
#include <stdio.h>
#include <iostream.h>
#endif

using namespace std;

#ifdef DEBUG
int main(){
  Camera camera;
  Camera tmp;
  double theta;
  double phai=0;
  camera.set(1.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ,1.0 ,0.0);
  tmp=camera;
  for(theta=0;theta<2*M_PI;theta+= M_PI/8){
    tmp= camera.eyeRotateAxe(camera.center,theta,Vector3d(0.0,1.0,0.0));
    cout << tmp << endl;
  }
  tmp=camera;
  tmp = camera.upRotate(M_PI);
  cout << tmp << endl;
  return 1;
}
#endif

Camera::Camera(){
  reset();
}
Camera::Camera(const Vector3d &eye,const Vector3d &center,const Vector3d &up){
  Camera::set(eye,center,up);
}
Camera::Camera(const Vector3d v[]){
  Camera::set(v);
}
Camera::Camera(const double &eye_x,const double &eye_y,const double &eye_z,
	       const double &center_x,const double &center_y,const double &center_z,
	       const double &up_x,const double &up_y, const double &up_z){
  Camera::set(eye_x,eye_y,eye_z,center_x,center_y,center_z,up_x,up_y,up_z);
}
Camera::Camera(const double d[]){
  Camera::set(d);
}

void Camera::reset(void){
  eye.Vector3d::set(0.0,0.0,0.0);
  center.Vector3d::set(0.0,0.0,0.0);
  up.Vector3d::set(0.0,0.0,0.0);
}
void Camera::set(const Vector3d &eye,const Vector3d &center,const Vector3d &up){
  this->eye=eye;
  this->center=center;
  this->up=up;
}
void Camera::set(const Vector3d v[]){
  Camera::set(v[0],v[1],v[2]);
}
void Camera::set(const double &eye_x,const double &eye_y,const double &eye_z,
		 const double &center_x,const double &center_y,const double &center_z,
		 const double &up_x,const double &up_y, const double &up_z){
  eye.Vector3d::set(eye_x,eye_y,eye_z);
  center.Vector3d::set(center_x,center_y,center_z);
  up.Vector3d::set(up_x,up_y,up_z);
}

  
void Camera::set(const double d[]){
  Camera::set(d[0],d[1],d[2],d[3],d[4],d[5],d[6],d[7],d[8]);
}


void
Camera::convert2trueUp()
{
  Vector3d n,u;
  n = center - eye;
  u = n.cross(up);
  this->up= u.cross(n);
  this->up.norm();
}

void 
Camera::gluLookAt() const
{
  std::gluLookAt( eye.x , eye.y , eye.z , center.x , center.y , center.z , up.x , up.y , up.z );
}
void 
std::gluLookAt( const Camera & c){
  c.gluLookAt();
} 

void
Camera::upRotate(const double &angle)
{
  this->up.Vector3d::rotateAxe(angle, center-eye);
}

void
Camera::eyeRotateX(const Vector3d & _center, const double &angle)
{
  this->eye -= _center;
  this->eye.Vector3d::rotateX(angle);
  this->eye +=  _center;
  this->up.Vector3d::rotateX(angle);
}

void
Camera::eyeRotateY(const Vector3d & _center,const double &angle)
{
  this->eye -= _center;
  this->eye.Vector3d::rotateY(angle);
  this->eye += _center;
  this->up.Vector3d::rotateY(angle);
}

void
Camera::eyeRotateZ(const Vector3d &_center,const double &angle)
{
  this->eye -= _center;
  this->eye.Vector3d::rotateZ(angle);
  this->eye += _center;
  this->up.Vector3d::rotateZ(angle);
}

void
Camera::eyeRotateAxe(const Vector3d & _center,const double &angle,const Vector3d &axe)
{
  this->eye -= _center;
  this->eye.Vector3d::rotateAxe(angle,axe);
  this->eye += _center;
  this->up.Vector3d::rotateAxe(angle,axe);
}

void
Camera::eyeRotate2Right(const Vector3d &_center,const double &angle)
{
  Vector3d axe;
  this->convert2trueUp();
  axe = this->up;
  this->eyeRotateAxe(_center,angle,axe);
}

void
Camera::eyeRotate2Down(const Vector3d &_center,const double &angle)
{
  Vector3d axe;
  this->convert2trueUp();
  axe = this->up;
  axe.rotateAxe(M_PI/2,center-eye);
  this->eyeRotateAxe(_center,angle,axe);  
}

void
Camera::eyeRotate(const Vector3d &_center,const double &angle,const double &phai)
{
  Vector3d axe;
  this->convert2trueUp();
  axe = this->up;
  axe.rotateAxe(phai,center-eye);
  this->eyeRotateAxe(_center,angle,axe);  
}

void
Camera::centerRotateX(const Vector3d & _center, const double &angle)
{
  this->center -= _center;
  this->center.Vector3d::rotateX(angle);
  this->center +=  _center;
  this->up.Vector3d::rotateX(angle);
}

void
Camera::centerRotateY(const Vector3d & _center,const double &angle)
{
  this->center -= _center;
  this->center.Vector3d::rotateY(angle);
  this->center += _center;
  this->up.Vector3d::rotateY(angle);
}

void
Camera::centerRotateZ(const Vector3d &_center,const double &angle)
{
  this->center -= _center;
  this->center.Vector3d::rotateZ(angle);
  this->center += _center;
  this->up.Vector3d::rotateZ(angle);
}

void
Camera::centerRotateAxe(const Vector3d & _center,const double &angle,const Vector3d &axe)
{
  this->center -= _center;
  this->center.Vector3d::rotateAxe(angle,axe);
  this->center += _center;
  this->up.Vector3d::rotateAxe(angle,axe);
}

void
Camera::centerRotate2Right(const Vector3d &_center,const double &angle)
{
  Vector3d axe;
  this->convert2trueUp();
  axe = this->up;
  this->centerRotateAxe(_center,angle,axe);
}

void
Camera::centerRotate2Down(const Vector3d &_center,const double &angle)
{
  Vector3d axe;
  this->convert2trueUp();
  axe = this->up;
  axe.Vector3d::rotateAxe(M_PI/2,center-eye);
  this->centerRotateAxe(_center,angle,axe);  
}

void
Camera::centerRotate(const Vector3d &_center,const double &angle,const double &phai)
{
  Vector3d axe;
  this->convert2trueUp();
  axe = this->up;
  axe.Vector3d::rotateAxe(phai,center-eye);
  this->Camera::centerRotateAxe(_center,angle,axe);  
}


void
Camera::translate(const Vector3d &trans)
{
  this->set(eye+trans,center+trans,up);
}

void
Camera::translate(const double &trans_x,const double &trans_y,const double &trans_z)
{
  Vector3d trans(trans_x,trans_y,trans_z);
  this->translate(trans);
}

void
Camera::upTranslate(const double &length)
{
  Vector3d trans;
  trans=up;
  trans.norm();
  trans*=length;
  this->translate(trans);
}

void
Camera::rightTranslate(const double &length)
{
  Camera tmp;
  Vector3d trans;

  tmp = *this;
  tmp.upRotate(M_PI*1.0/2.0);
  trans=tmp.up;
  trans.norm();
  trans*=length;
  this->translate(trans);
}

void
Camera::downTranslate(const double &length)
{
  Camera tmp;
  Vector3d trans;

  tmp = *this;
  tmp.upRotate(M_PI*2.0/2.0);
  trans= tmp.up;
  trans.norm();
  trans*=length;
  this->translate(trans);
}

void
Camera::leftTranslate(const double &length)
{
  Camera tmp;
  Vector3d trans;

  tmp = *this;
  tmp.upRotate(M_PI*3.0/2.0);
  trans=tmp.up;
  trans.norm();
  trans*=length;
  this->translate(trans);
}

void
Camera::forwardTranslate(const double &length)
{
  Vector3d trans;

  trans= center-eye;
  trans.norm();
  trans*=length;
  this->translate(trans);
}

void
Camera::backTranslate(const double &length)
{
  Vector3d trans;

  trans= eye-center;
  trans.norm();
  trans*=length;
  this->translate(trans);
}


// ----  operators ------

// unary operators
Camera & Camera::operator = ( const Camera & v )
{
  eye = v.eye;
  center = v.center;
  up = v.up;
  return *this;
}

Camera & Camera::operator += ( const Camera & v )
{
  eye += v.eye;
  center += v.center;
  up += v.up;
  return *this;
}

Camera & Camera::operator -= ( const Camera & v )
{
  eye -= v.eye;
  center -= v.center;
  up -= v.up; 
  return *this;
}

Camera & Camera::operator *= ( const double& d )
{
  eye *= d;
  center *= d;
  up *= d;
  return *this;
}

Camera & Camera::operator *= ( const Camera& v){
  eye *= v.eye;
  center *= v.center;
  up *= v.up; 
  return *this;
}

Camera & Camera::operator /= ( const double& d )
{
  eye /= d;
  center /= d;
  up /= d;
  return *this;

}

Camera & Camera::operator /= ( const Camera& v){
  eye /= v.eye;
  center /= v.center;
  up /= v.up; 
  return *this;
}

Camera std::operator + ( const Camera & v )
{
  return v;
}

Camera std::operator - ( const Camera & v )
{
  return Camera( -v.eye, -v.center, -v.up );
}

// binary operators
Camera std::operator + ( const Camera & a, const Camera & b )
{
  return Camera( a.eye+b.eye, a.center+b.center, a.up+b.up );
}

Camera std::operator - ( const Camera & a, const Camera & b )
{
  return Camera( a.eye-b.eye, a.center-b.center, a.up-b.up );
}

// vector and scholar operations
Camera std::operator * ( const double& d, const Camera & v ) 
{
  return Camera( d * v.eye, d * v.center, d * v.up );
}

Camera std::operator * ( const Camera & v, const double& d )
{
  return Camera( d * v.eye, d * v.center, d * v.up );
}

Camera std::operator * ( const Camera & v, const Camera& d )
{
  return Camera( d.eye * v.eye, d.center * v.center, d.up * v.up );
}

Camera std::operator / ( const Camera & v, const double& d )
{
  return Camera( v.eye/d , v.center/d, v.up/d );
}

Camera std::operator / ( const Camera & v, const Camera& d )
{
  return Camera( v.eye/d.eye , v.center/d.center, v.up/d.up );
}

// logical operators
bool std::operator == ( const Camera & a, const Camera & b )
{
  return (( a.eye == b.eye ) && ( a.center == b.center ) && ( a.up == b.up ));
}
bool std::operator != ( const Camera & a, const Camera & b )
{
   return (( a.eye != b.eye ) || ( a.center != b.center ) || ( a.up != b.up ));
}

#ifdef _IOSTREAM_H
// stream operators 
ostream & std::operator<< ( ostream &s, Camera v )
{
  s << "(" << v.eye.x << " , " << v.eye.y << " , " << v.eye.z <<") " ;
  s << "(" << v.center.x << " , " << v.center.y << " , " << v.center.z <<") " ;
  s << "(" << v.up.x << " , " << v.up.y << " , " << v.up.z <<")" ;
  return s;
}

istream & std::operator>> ( istream &s, Camera &v )
{
  s >> v.eye.x >> v.eye.y >> v.eye.z;
  s >> v.center.x >> v.center.y >> v.center.z;
  s >> v.up.x >> v.up.y >> v.up.z ;
  return s;
}
#endif

CameraTest.cpp

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <GL/glut.h>
#include <GL/glu.h>
#include <GL/gl.h>
#include "../include/Vector3d.h"
#include "../include/Camera.h"

static Camera camera(15.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0);

/* 初期化 */
static void
initializeAll( void )
{
  camera.convert2trueUp();
}

/* 光源の設定 */
static void point_light(void){

  float light_ambient[ ] = {0.7, 0.7, 0.5, 1.0};
  float light_position[ ] = {10.0,  2.0, 10.0, 1.0};
  
  /* ポイントライトを設定するコードを書く */
  glEnable ( GL_LIGHTING );
  glEnable ( GL_LIGHT0 );
  glLightfv(GL_LIGHT0, GL_POSITION, light_position);
  
}

void setMaterial(float *color){
  glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);
  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color);
  glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, color);
  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color);
}
/* 描画が必要となった時に呼ばれる */
static void
displayCallback( void )
{
  float red[]={1,0,0,1};
  float green[]={0,1,0,1};
  float blue[]={0,0,1,1};

  glLoadIdentity();
  resetMaterial();
  gluLookAt(camera);

  glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
  /* ポイントライトの設定 */
  point_light( );

  glPushMatrix();
  glutSolidCube(3.0); 
  glPopMatrix( );
  glPushMatrix();
  glScalef(10,0.1,0.1);
  glTranslatef(0.5,0,0);
  setMaterial(red);
  glutSolidCube(1.0);
  glPopMatrix();

  glPushMatrix();
  glScalef(0.1,10,0.1);
  glTranslatef(0,0.5,0);
  setMaterial(green);
  glutSolidCube(1.0);
  glPopMatrix();

  glPushMatrix();
  glScalef(0.1,0.1,10);
  glTranslatef(0,0,0.5);
  setMaterial(blue);
  glutSolidCube(1.0);
  glPopMatrix();

  resetMaterial();
  glutSwapBuffers();
}

/* ウインドウがリサイズされた場合に呼ばれる */
static void
reshapeCallback( int width, int height )
{
  glViewport( 0, 0, width, height );

  glMatrixMode( GL_PROJECTION );
  glLoadIdentity();
  gluPerspective( 60.0, width/(GLdouble)height, 0.01, 100 );

  glMatrixMode( GL_MODELVIEW );
}

/* アイドル時間中は常時呼ばれる */
static void
idleCallback( void )
{
}

/* ウインドウが{表示/隠された}場合に呼ばれる */
static void
visibilityCallback( int state )
{
}

/* マウスのボタンに変化があった場合に呼ばれる */
static void
mouseCallback( int button, int state, int x, int y )
{
}

/* マウスのポインタに動きがあった場合に呼ばれる */
static void
passiveMotionCallback( int x, int y )
{
}

/* ドラッグ中、マウスのポインタに動きがあった場合に呼ばれる */
static void
motionCallback( int x, int y )
{
}

/* キー入力があった場合に呼ばれる */
static void
keyboardCallback( unsigned char key, int x, int y )
{
  //fprintf( stderr, "HIT \'%c\' KEY (CODE: %d)\n", (key<32)?'?':key, (int)key );

  switch( key ){
  /*
  ** Escが押されたらプログラムを終了する
  */
   case 27:
    exit( EXIT_SUCCESS );
    break;

  case 'r':
    camera.rightTranslate(0.5);
    cout << camera << endl;
    glutPostRedisplay();
    break;

  case 'l':
    camera.leftTranslate(0.5);
    cout << camera << endl;
    glutPostRedisplay();
    break;

  case 'u':
    camera.upTranslate(0.5);
    cout << camera << endl;
    glutPostRedisplay();
    break;

  case 'd':
    camera.downTranslate(0.5);
    cout << camera << endl;
    glutPostRedisplay();
    break;

  case 'f':
    camera.forwardTranslate(0.5);
    cout << camera << endl;
    glutPostRedisplay();
    break;

  case 'b':
    camera.backTranslate(0.5);
    cout << camera << endl;
    glutPostRedisplay();
    break;
    
  case '1':
    camera.eyeRotate2Right(camera.center,M_PI/32);
    cout << camera << endl;
    glutPostRedisplay();
    break;

  case '2':
    camera.eyeRotate2Down(camera.center,M_PI/32);
    cout << camera << endl;
    glutPostRedisplay();
    break;

  case '3':
    camera.eyeRotate(camera.center,M_PI/32,M_PI/4);
    cout << camera << endl;
    glutPostRedisplay();
    break;

  case '4':
    camera.centerRotate2Right(camera.eye,M_PI/32);
    cout << camera << endl;
    glutPostRedisplay();
    break;

  case '5':
    camera.centerRotate2Down(camera.eye,M_PI/32);
    cout << camera << endl;
    glutPostRedisplay();
    break;

  case '6':
    camera.centerRotate(camera.eye,M_PI/32,M_PI/4);
    cout << camera << endl;
    glutPostRedisplay();
    break;

  case 'x':
    camera.eyeRotateX(camera.center,M_PI/32);
    cout << camera << endl;
    glutPostRedisplay();
    break;

  case 'y':
    camera.eyeRotateY(camera.center,M_PI/32);
    cout << camera << endl;
    glutPostRedisplay();
    break;

  case 'z':
    camera.eyeRotateZ(camera.center,M_PI/32);
    cout << camera << endl;
    glutPostRedisplay();
    break;

  case 'n':
    camera.upRotate(M_PI/32);
    cout << camera << endl;
    glutPostRedisplay();
    break;

  default:
    break;
  }
}

/* 初期化 */
static void
initGL( void )
{
  int width, height;

  width  = glutGet( GLUT_WINDOW_WIDTH );
  height = glutGet( GLUT_WINDOW_HEIGHT );

  reshapeCallback( width, height );

  glClearColor( 0.25, 0.25, 0.25, 1.0 );
  glEnable( GL_DEPTH_TEST );
  glEnable( GL_LIGHTING );


}

/* MAIN */
int
main( int argc, char *argv[] )
{
  initializeAll( );
  glutInit( &argc, argv );
  glutInitDisplayMode( GLUT_DOUBLE|GLUT_RGB|GLUT_DEPTH );

  glutCreateWindow( "Camera Test" );

  glutDisplayFunc      ( displayCallback       );
  glutKeyboardFunc     ( keyboardCallback      );
  glutReshapeFunc      ( reshapeCallback       );
  //glutIdleFunc         ( idleCallback          );
  glutVisibilityFunc   ( visibilityCallback    );
  glutMouseFunc        ( mouseCallback         );
  glutPassiveMotionFunc( passiveMotionCallback );
  glutMotionFunc       ( motionCallback        );
  
  initGL();
  
  glutMainLoop();

  return EXIT_SUCCESS;
}

PpmTexture(OpenGL 用 ppm 画像テクスチャライブラリ)

OpenGL 用の ppm 形式画像ファイルを読み込んでテクスチャにするためのライブラリです。 P3 形式の ppm を読み込めるようにできていると思いますが、ちゃんとした定義を調べていないのでダメなときもあるかもしれません。一応 &ref(): File not found: "ascii.ppm" at page "Undergrad/Software/18.Push"; なら確実に読み込めます。

createTexture() などでテクスチャを作ったら、メンバ変数の id をテクスチャ登録関係の OpenGL の関数で使ってください。

PpmTexture.h

/* PpmTexture.h	-- Naotoshi Seo 2002 12/26*/

#include <GL/gl.h>
#include <GL/glu.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <string.h>
#include <stdio.h>

#ifndef _PPMTEXTURE_H
#define _PPMTEXTURE_H

class PpmTexture{
public:
  char * filename;
  GLuint * id;
private:
  int width,height;
  GLubyte * data;
public:
  //only substitute filename and id 
  PpmTexture(char *filename,GLuint * id);
  ~PpmTexture();
  //actually make texture
  void createTexture();
  void createTextureWithLOD(GLint lod);
  void createTextureWithMipmap();
private:
  void createData();
};

#endif

PpmTexture.cpp

/* PpmTexture.h	-- Naotoshi Seo 2002 12/26*/

#include <GL/gl.h>
#include <GL/glu.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <string.h>
#include "../include/PpmTexture.h"
#include <stdio.h>

//#define DEBUG

PpmTexture::PpmTexture(char *filename,GLuint * id){
  this->filename = filename;
  this->id = id;
}

void 
PpmTexture::createData(){
  FILE * texturefile;
  char readbuf[80];
  int color_max;

  if(NULL == (texturefile = fopen(filename,"r"))){
    fprintf(stderr,"File Open Error %s\n",filename);
    return;
  }
  
  fscanf(texturefile,"%s",readbuf);
  if(strcmp(readbuf,"P3")!=0){return;}
    
  while(true){
    fscanf(texturefile,"%s",readbuf);
    if(readbuf[0]=='#'){
      while(1){
	fscanf(texturefile,"%c",&readbuf[0]);
	if(readbuf[0]=='\n')break;
      }
    }else{
      width=atoi(readbuf);break;
    }
  }
  fscanf(texturefile,"%d",&height);
  fscanf(texturefile,"%d",&color_max);
  
  data = new GLubyte[width*height*3];
  
  int dat;
#ifdef DEBUG
  int count=0;
#endif
  for(int y=0;y<height;y++){
    for(int x=0;x<width;x++){
      for(int c=0;c<3;c++){
	fscanf(texturefile,"%d",&dat);
#ifdef DEBUG
	printf("%3d ",dat);
#endif
	*(data+(x+y*width)*3+c) = (GLubyte) dat;
      }
#ifdef DEBUG
      if(++count==5){printf("\n");count=0;}
#endif
    }
  }
}


PpmTexture::~PpmTexture(){
  delete [] data;
}

void 
PpmTexture::createTexture(){
  this->createData();
  glBindTexture(GL_TEXTURE_2D, *id);
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 
         0, GL_RGB, GL_UNSIGNED_BYTE, (GLubyte *)data);
  //delete [] data; //In SGI, if delete data[], happen Bus Error. ?

}
void 
PpmTexture::createTextureWithLOD(GLint lod){
  this->createData();
  glBindTexture(GL_TEXTURE_2D, *id);
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  glTexImage2D(GL_TEXTURE_2D, lod, GL_RGB, width, height, 
	       0, GL_RGB, GL_UNSIGNED_BYTE, (GLubyte *)data);
  //delete []data;
  }
void 
PpmTexture::createTextureWithMipmap(){
  this->createData();
  glBindTexture(GL_TEXTURE_2D, *id);
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  if (0 == gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, width, height, 
			     GL_RGB, GL_UNSIGNED_BYTE, (GLubyte *)data)){
    //return 1;
  }else{
    //return 0;
  }
  //delete [] data;
}

   /*malloc():  2 × 3 文字の配列を作成
      int i;
      char** p;
      p = (char **) malloc(2 * sizeof(char *));
      for (i=0; i<2; i++) p[i] = (char *) malloc(3);

      new:
      int j;
      char** q;
      q = new char* [2];
      for (j=0; j<2; j++) q[j] = new char [3];
      
      */

DrawString(OpenGL 用文字列描画ライブラリ)

OpenGL 用で文字列を描画するためのライブラリです。上の PpmTexture クラスを使用します。 &ref(): File not found: "ascii.ppm" at page "Undergrad/Software/18.Push"; をテクスチャとして読み込むので、実行時のディレクトリにコピーしておいてください。カメラの位置と文字列を与えると、カメラの目の前に文字列を表示します。カメラの位置の指定にはせっかくなので上の Camera クラスを利用しています。 Camera を使っているので Vector3d クラスも必要です。

DrawString クラスのオブジェクトを作ったら、init() で初期化して(コンストラクタでやったらエラー出た)、setPosition(Camera &) でカメラの位置を教えてあげたら、あとは drawString(string &) で文字列を指定してあげてください。

DrawStringTest.cpp が使い方例です。

DrawString.h

/* DrawString.h	-- Naotoshi Seo 2002 12/26*/

#include <string> //特殊なオプションつけないと SGI ではsegmentation fault
#include "Vector3d.h"
#include "Camera.h"
#include "PpmTexture.h"

#ifndef _DRAWSTRING_H
#define _DRAWSTRING_H

class DrawString{
public:
  GLuint texid;
  const static unsigned char CENTER=0; 
  const static unsigned char RIGHTDOWN=1;
  const static unsigned char RIGHTUP=2;
  const static unsigned char LEFTDOWN=3;
  const static unsigned char LEFTUP=4;
private:
  double fontsize; 
  double theta;
  double phai;
  double gamma;
  Vector3d move;
  Vector3d eye;
  unsigned char position;
  void drawChar(const char &a);
public:
  //default is 10 (In fact, 10/1000)
  DrawString();
  void setFontsize(const double & fontsize); 

  //position is CENTER
  void setPosition(const Camera &camera);
  void setPosition(const unsigned char & position);
  void setPosition(const Camera &camera,const unsigned char & position);
  DrawString(const double & fontsize);
  DrawString(const double & fontsize,const Camera & camera);
  DrawString(const double & fontsize,const Camera & camera,const unsigned char & position);
  ~DrawString();
  void init();
  void deleteTexture();
public:
  //draw string at origin (0,0,0). maybe you can not see because default font size is too small.
  void drawStringOrigin(const string &str); 
  //draw string just before at camera. The background of character is white board.
  void drawString(const string &str);
  //draw String at origin. The background of character is transparency.
  void drawStringClearOrigin(const string &str);
  //draw String just before at camera. The background of character is transparency.
  void drawStringClear(const string &str);
  //draw String just before at camera. The background of character is semi-transparent white board.
  void drawStringWhiteback(const string &str);
};

#endif

DrawString.cpp

/* DrawString.cpp -- Naotoshi Seo 2002 12/26*/

#include <GL/gl.h>
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <float.h>
#include "../include/PpmTexture.h"
#include "../include/DrawString.h"
#include "../include/Camera.h"
#include "../include/Vector3d.h"

DrawString::DrawString(){
  fontsize=0.01;
}

DrawString::DrawString(const double & fontsize){
  setFontsize(fontsize);
}


DrawString::DrawString(const double & fontsize,const Camera & camera){
  setFontsize(fontsize);
  setPosition(camera,DrawString::CENTER);
}

DrawString::DrawString(const double & fontsize,const Camera & camera,const unsigned char & position){
  setFontsize(fontsize);
  setPosition(camera,position);
}

DrawString::~DrawString(){
  glDeleteTextures(1,&texid);
}

void DrawString::init(){
  //Constructor に書いたら Gen してくれなかった。?
  glGenTextures(1, &texid);
  PpmTexture ascii("ascii.ppm",&texid);
  ascii.createTextureWithMipmap();
}

void
DrawString::deleteTexture(){
  glDeleteTextures(1,&texid);
}

void
DrawString::setFontsize(const double & fontsize){
  this->fontsize=fontsize/1000.0;
}

void
DrawString::setPosition(const Camera & camera){
  this->eye=camera.eye;
  Camera n_camera=camera;

  n_camera.convert2trueUp();
  Vector3d u = n_camera.eye - n_camera.center;
  Vector3d up = n_camera.up;
  
  //u を (0,0,1) に持っていき、同時に up_tmp も回転させたい
  this->taxe = Vector3d(0,0,1).cross(u);
  this->theta = Vector3d(0,0,1).angle(u);

  up.rotateAxe(-theta,taxe);

  //xy平面になってるはずのupとy軸との角度phai
  this->paxe = Vector3d(0,1,0).cross(up);
  this->phai = Vector3d(0,1,0).angle(up);
 
  setPosition(DrawString::CENTER);
}
void 
DrawString::setPosition(const unsigned char & position){
  this->position=position;
  switch (position){
  case DrawString::CENTER:
    move.set(0.0,0.0,0.0);
    break;
  case DrawString::RIGHTDOWN:
    move.set(0.057,-0.057,0.0);
    break;
  case DrawString::RIGHTUP:
    move.set(0.057,0.0575,0.0);
    break;
  case DrawString::LEFTDOWN:
    move.set(-0.0575,-0.057,0.0);
    break;
  case DrawString::LEFTUP:
    move.set(-0.0575,0.0575,0.0);
    break;
  default:
    break;
  }

}

void
DrawString::setPosition(const Camera &camera,const unsigned char &position){
  setPosition(camera);
  setPosition(position);
}

void 
DrawString::drawChar(const char &a){
  if(a < ' ' ) return;
  //0x7f は黒四角
  //0.004はtextureの隅を貼って汚くならないようにするため少し内側にずらすため。
  double left=0.004;
  double right=0.00;
  double up=0.004;
  double down=0.004;
  if(a == 'o' || a == '/' )right=0.004;//右側が汚くなるのはこのときだけ?。
  else if(a == 'O' || a == 0x7f)right=0.003;
  else if(a == ' '){right=0.01;left=0.01;up=0.01;down=0.01;}
  //glVertex2f(x,y) = glVertex3f(x,y,0)
  glBegin(GL_QUADS);
  glTexCoord2f(8*(a%16)/128.0+left, 16*(a/16)/128.0+up);
  glVertex2f(0.0, 0.0);
  glTexCoord2f(8*(a%16)/128.0+1/16.0-right, 16*(a/16)/128.0+up);
  glVertex2f(fontsize/2.0, 0.0);
  glTexCoord2f(8*(a%16)/128.0+1/16.0-right, 16*(a/16)/128.0 + 1/8.0-down);
  glVertex2f(fontsize/2.0, -fontsize);
  glTexCoord2f(8*(a%16)/128.0+left, 16*(a/16)/128.0 + 1/8.0-down);
  glVertex2f(0.0, -fontsize);
  glEnd();
}

void
DrawString::drawStringOrigin(const string &str){
  double x=0;
  int i=0;

  glBindTexture(GL_TEXTURE_2D, texid);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);//WithMipmap
  //glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//normal texture
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
  glDisable(GL_LIGHTING); 
  glEnable(GL_TEXTURE_2D);
  glPushMatrix();
  for(i=0;i<str.size();i++){
    if(str[i]=='\n'){
      glTranslatef(-x,-fontsize,0.0);
      x=0;
    }else{
      drawChar(str[i]);
      glTranslatef(fontsize/2.0,0.0,0.0);
      x+=fontsize/2;
    }
  }
  glPopMatrix();
  glDisable(GL_TEXTURE_2D);
  glEnable(GL_LIGHTING);
}

void 
DrawString::drawString(const string &str){
  double rightmost=0,downmost=0,x=0,y=0;
  Vector3d mid;

  for(int i=0;i<str.size();i++){
    if(str[i]=='\n'){
      y-=fontsize;x=0;
      if(downmost>y)downmost=y;
    }
    else{
      x+=fontsize/2.0;
      if(rightmost<x)rightmost=x;
    }
  }downmost-=fontsize;

  switch (position){
  case DrawString::CENTER:
    mid.set(rightmost/2.0,downmost/2.0,0.0);
    break;
  case DrawString::RIGHTDOWN:
    mid.set(rightmost,downmost,0.0);
    break;
  case DrawString::RIGHTUP:
    mid.set(rightmost,0.0,0.0);
    break;
  case DrawString::LEFTDOWN:
    mid.set(0.0,downmost,0.0);
    break;
  case DrawString::LEFTUP:
    mid.set(0.0,0.0,0.0);
    break;
  default:
    break;
  }

  glPushMatrix();
  glTranslate(eye);
  glRotatef(theta*180/M_PI,0,1,0);
  glRotatef(phai*180/M_PI,1,0,0);
  glRotatef(gamma*180/M_PI,0,0,1);
  glTranslatef(0.0,0.0,-0.1);
  glTranslate(move);
  glTranslate(-mid);
  drawStringOrigin(str);
  glPopMatrix();
}

void 
DrawString::drawStringClearOrigin(const string &str){
  //glDepthMask( GL_FALSE );
  glEnable(GL_BLEND);
  glBlendFunc(GL_DST_COLOR, GL_ZERO);
  drawStringOrigin(str);
  glDisable(GL_BLEND);
}
void 
DrawString::drawStringClear(const string &str){
  glEnable(GL_BLEND);
  glBlendFunc(GL_DST_COLOR, GL_ZERO);
  drawString(str);
  glDisable(GL_BLEND);
}

void 
DrawString::drawStringWhiteback(const string &str){
  double rightmost=0,downmost=0,x=0,y=0;
  Vector3d mid;

  for(int i=0;i<str.size();i++){
    if(str[i]=='\n'){
      y-=fontsize;x=0;
      if(downmost>y)downmost=y;
    }
    else{
      x+=fontsize/2.0;
      if(rightmost<x)rightmost=x;
    }
  }downmost-=fontsize;

  switch (position){
  case DrawString::CENTER:
    mid.set(rightmost/2.0,downmost/2.0,0.0);
    break;
  case DrawString::RIGHTDOWN:
    mid.set(rightmost,downmost,0.0);
    break;
  case DrawString::RIGHTUP:
    mid.set(rightmost,0.0,0.0);
    break;
  case DrawString::LEFTDOWN:
    mid.set(0.0,downmost,0.0);
    break;
  case DrawString::LEFTUP:
    mid.set(0.0,0.0,0.0);
    break;
  default:
    break;
  }

  glEnable(GL_BLEND);
  
  glPushMatrix();
  glTranslate(eye);
  glRotate(theta*180/M_PI,taxe);
  glRotate(phai*180/M_PI,paxe);
  glTranslatef(0.0,0.0,-0.11);
  glMaterial(GL_FRONT_AND_BACK, GL_SPECULAR, Vector3d(1,1,1),0.7);
  glMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE, Vector3d(1,1,1),0.7);
  glMaterial(GL_FRONT_AND_BACK, GL_EMISSION, Vector3d(1,1,1),0.7);
  glMaterial(GL_FRONT_AND_BACK, GL_AMBIENT, Vector3d(1,1,1),0.7);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glBegin(GL_QUADS);
  glVertex3d(-0.6,-0.6,0.0);
  glVertex3d(0.6,-0.6,0.0);
  glVertex3d(0.6,0.6,0.0);
  glVertex3d(-0.6,0.6,0.0);
  glEnd();
  resetMaterial();

  glTranslatef(0.0,0.0,0.01);//gluPerspectiveでnear が 0.01 だから
  glTranslate(move);
  glTranslate(-mid);
  glBlendFunc(GL_DST_COLOR, GL_ZERO);
  drawStringOrigin(str);
  glPopMatrix();
  
  glDisable(GL_BLEND);
}

DrawStringTest.cpp

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <GL/glut.h>
#include <GL/glu.h>
#include <GL/gl.h>
#include "../include/Vector3d.h"
#include "../include/Camera.h"
#include "../include/DrawString.h"
#include "../include/PpmTexture.h"

static void
reshapeCallback( int width, int height );
static void
displayCallback( void );

static DrawString str;
static Camera camera;

static void
initAll(void)
{  
  glutDisplayFunc      ( displayCallback       );
  glutReshapeFunc      ( reshapeCallback       );
  reshapeCallback(glutGet( GLUT_WINDOW_WIDTH ),glutGet( GLUT_WINDOW_HEIGHT ));
  glClearColor( 0.5, 0.5, 0.5, 1.0 );
  glEnable( GL_DEPTH_TEST );

  str.init();
  camera = Camera(15.0 , 15.0 , 3.0 , 0.0 , 0.0 , 0.0, 0.0, 1.0, 0.0);
  camera.convert2trueUp();
}

static void 
freeAll(void)
{
}


static void
displayCallback( void )
{
  glLoadIdentity();

  gluLookAt(camera);

  glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );

  Vector3d position(0,15,0);
  glLight(GL_LIGHT0, GL_POSITION,position);
  glEnable( GL_LIGHTING );
  glEnable( GL_LIGHT0 );

  glEnable(GL_AUTO_NORMAL);
  glutSolidCube(5.0);

  str.setPosition(camera,DrawString::CENTER);
  str.setFontsize(13);
  str.drawStringWhiteback("DrawStringTest\n\n\n\n\n\n\n");
  str.setFontsize(7);
  str.drawStringClear("This is sample program of
DrawString class.");
  str.setPosition(camera,DrawString::RIGHTDOWN);
  str.setFontsize(5);
  str.drawStringClear("Are you OK?");

  glutSwapBuffers();
}

static void
reshapeCallback( int width, int height )
{
  glViewport( 0, 0, width, height );

  glMatrixMode( GL_PROJECTION );
  glLoadIdentity();
  gluPerspective( 60.0, width/(GLdouble)height, 0.01, 100 );

  glMatrixMode( GL_MODELVIEW );
}

/* MAIN */
int
main( int argc, char *argv[] )
{
  glutInit( &argc, argv );
  glutInitDisplayMode( GLUT_DOUBLE|GLUT_RGB|GLUT_DEPTH );
  glutInitWindowPosition(100,100); 
  glutInitWindowSize(300,300);
  glutCreateWindow( "DrawStringTest" );
  initAll( );
  glutMainLoop();
  freeAll();
  return EXIT_SUCCESS;
}