CDR6275

Michio SHIRAISHI Official Site


コンピュータ科学特論 (2014 Fall)

レポート課題

 RotationAnimationプロジェクトのうち、RotationAnimation.hRotationAnimation.cppの2つのファイルを以下のものに入れかえてください。これは、2つのモデルを同じ位置に描いていますが、ウィンドウの左側と右側に一体ずつ描くように変更し、また、回転する方向を逆になるように変更してください。どのように変更したかをWordファイルにまとめてメールで提出してください。

RotationAnimation.h

#ifndef _RotationAmination_Defined
#define _RotationAmination_Defined

#include "BaseApplication.h"
#include "PolygonModel.h"

class RotationAnimation : public BaseApplication{
private:
  // プログラムオブジェクト
  GLuint program;
  // 頂点配列オブジェクト
  GLuint vertexArrayObject;
  // 頂点バッファオブジェクト
  GLuint vertexBufferObjects[3];
  // 要素配列バッファオブジェクト
  GLuint elementArrayBufferObject;
  // テクスチャオブジェクト
  GLuint* textures;
  // 投影変換行列
  float projectionMatrix[16];
  // モデル変換行列
  float modelMatrix[16];
  // 法線ベクトルを変換する行列
  float normalMatrix[16];
  PolygonModel polygonModel;
public:
  bool initialize();
  void update();
  void draw();
  void drawModel();
  void setUniforms();
  void setModelMatrix();
};
#endif

RotationAnimation.cpp

#include <iostream>

#include "pmd.h"
#include "RotationAnimation.h"
#include "SimpleProgramObject.h"
#include "Matrix.h"

enum
{
  ATTRIBUTE_VERTEX_COORDINATE,
  ATTRIBUTE_VERTEX_TEXTURE_COORDINATE,
  ATTRIBUTE_VERTEX_NORMAL,
  ATTRIBUTE_VERTEX_COLOR,
  NUM_ATTRIBUTES
};

enum
{
  UNIFORM_PROJECTION_MATRIX,
  UNIFORM_MODEL_MATRIX,
  UNIFORM_NORMAL_MATRIX,
  UNIFORM_LIGHT_DIRECTION,
  UNIFORM_VIEW_DIRECTION,
  UNIFORM_LIGHT_AMBIENT_COLOR,
  UNIFORM_LIGHT_DIFFUSE_COLOR,
  UNIFORM_LIGHT_SPECULAR_COLOR,
  UNIFORM_OBJECT_AMBIENT_COLOR,
  UNIFORM_OBJECT_DIFFUSE_COLOR,
  UNIFORM_OBJECT_SPECULAR_COLOR,
  UNIFORM_OBJECT_SHINNESS,
  UNIFORM_TEXTURE_ENABLED,
  UNIFORM_SHADING_ENABLED,
  NUM_UNIFORMS
};
GLint uniforms[NUM_UNIFORMS];

bool RotationAnimation::initialize(){
#if !TARGET_OS_IPHONE
  BaseApplication::initializeWindow(640, 960, "Orthogonal Projection");
#endif
  
  polygonModel.load(modelSearchPath, "miku.pmd");
  
  textures = new GLuint[polygonModel.getNumMaterials()];
  for(int i=0; i<polygonModel.getNumMaterials(); i++){
    unsigned char* data = polygonModel.getTextureDatas()[i];
    if(data==0){
      textures[i] = 0;
    }
    else{
      unsigned int width = polygonModel.getTextureWidths()[i];
      unsigned int height = polygonModel.getTextureHeights()[i];
      glGenTextures(1, &textures[i]);
      glBindTexture(GL_TEXTURE_2D, textures[i]);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
      glBindTexture(GL_TEXTURE_2D, 0);
    }
  }
  
  SimpleProgramObject programObject;
  const char* vertexShaderFileName = "phong-shading-model-with-projection.vs";
  const char* fragmentShaderFileName = "texture-mapping.fs";
  
  program = programObject.createProgram(vertexShaderFileName, fragmentShaderFileName, shaderSearchPath);
  
  // シェーダコード内の変数にインデックスを設定する
  glBindAttribLocation(program, ATTRIBUTE_VERTEX_COORDINATE, "vertexCoordinate");
  glBindAttribLocation(program, ATTRIBUTE_VERTEX_TEXTURE_COORDINATE, "vertexTextureCoordinate");
  glBindAttribLocation(program, ATTRIBUTE_VERTEX_NORMAL, "vertexNormal");
  
  programObject.linkProgram();
  
  // 頂点配列オブジェクトを作成して設定する
#if TARGET_OS_IPHONE
  glGenVertexArraysOES(1, &vertexArrayObject);
  glBindVertexArrayOES(vertexArrayObject);
#else
  glGenVertexArrays(1, &vertexArrayObject);
  glBindVertexArray(vertexArrayObject);
#endif
  
  // 頂点バッファオブジェクトを作成する
  glGenBuffers(3, vertexBufferObjects);
  glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjects[0]);
  glBufferData(GL_ARRAY_BUFFER, sizeof(float)*polygonModel.numVertices()*3, polygonModel.vertexCoordinates(), GL_STATIC_DRAW);
  
  // 頂点バッファオブジェクトにシェーダ内の変数vertexCoodrinateを結びつける
  glEnableVertexAttribArray(ATTRIBUTE_VERTEX_COORDINATE);
  glVertexAttribPointer(ATTRIBUTE_VERTEX_COORDINATE, 3, GL_FLOAT, GL_FALSE, sizeof(float)*3, 0);
  
  // 頂点バッファオブジェクトを作成する
  glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjects[1]);
  glBufferData(GL_ARRAY_BUFFER, sizeof(float)*polygonModel.numVertices()*3, polygonModel.vertexNormals(), GL_STATIC_DRAW);
  
  // 頂点バッファオブジェクトにシェーダ内の変数vertexCoodrinateを結びつける
  glEnableVertexAttribArray(ATTRIBUTE_VERTEX_NORMAL);
  glVertexAttribPointer(ATTRIBUTE_VERTEX_NORMAL, 3, GL_FLOAT, GL_FALSE, sizeof(float)*3, 0);
  
  // 頂点バッファオブジェクトを作成する
  glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjects[2]);
  glBufferData(GL_ARRAY_BUFFER, sizeof(float)*polygonModel.numVertices()*2, polygonModel.vertexTextureCoordinates(), GL_STATIC_DRAW);
  
  // 頂点バッファオブジェクトにシェーダ内の変数vertexCoodrinateを結びつける
  glEnableVertexAttribArray(ATTRIBUTE_VERTEX_TEXTURE_COORDINATE);
  glVertexAttribPointer(ATTRIBUTE_VERTEX_TEXTURE_COORDINATE, 3, GL_FLOAT, GL_FALSE, sizeof(float)*2, 0);
  
  glGenBuffers(1, &elementArrayBufferObject);
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBufferObject);
  glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*3*polygonModel.numFaces(), polygonModel.faceVertexIndices(), GL_STATIC_DRAW);
  
  // 背景色の設定
  glClearColor(0.75f, 0.75f, 0.75f, 1.0f);
  
  // 頂点シェーダ内のuniform変数の場所を保存する
  uniforms[UNIFORM_PROJECTION_MATRIX] = glGetUniformLocation(program, "projectionMatrix");
  uniforms[UNIFORM_MODEL_MATRIX] = glGetUniformLocation(program, "modelMatrix");
  uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(program, "normalMatrix");
  uniforms[UNIFORM_VIEW_DIRECTION] = glGetUniformLocation(program, "viewDirection");
  uniforms[UNIFORM_LIGHT_DIRECTION] = glGetUniformLocation(program, "lightDirection");
  uniforms[UNIFORM_LIGHT_AMBIENT_COLOR] = glGetUniformLocation(program, "lightAmbientColor");
  uniforms[UNIFORM_LIGHT_DIFFUSE_COLOR] = glGetUniformLocation(program, "lightDiffuseColor");
  uniforms[UNIFORM_LIGHT_SPECULAR_COLOR] = glGetUniformLocation(program, "lightSpecularColor");
  uniforms[UNIFORM_OBJECT_AMBIENT_COLOR] = glGetUniformLocation(program, "objectAmbientColor");
  uniforms[UNIFORM_OBJECT_DIFFUSE_COLOR] = glGetUniformLocation(program, "objectDiffuseColor");
  uniforms[UNIFORM_OBJECT_SPECULAR_COLOR] = glGetUniformLocation(program, "objectSpecularColor");
  uniforms[UNIFORM_OBJECT_SHINNESS] = glGetUniformLocation(program, "objectShinness");
  uniforms[UNIFORM_TEXTURE_ENABLED] = glGetUniformLocation(program, "textureEnabled");
  uniforms[UNIFORM_SHADING_ENABLED] = glGetUniformLocation(program, "shadingEnabled");

  Matrix::perspectiveM(projectionMatrix, 0, 45.0, (float)windowWidth / windowHeight,  1.0, 100.0);

  glActiveTexture(GL_TEXTURE0);
  glUniform1i(ATTRIBUTE_VERTEX_TEXTURE_COORDINATE, 0);
  
  return true;
}


void RotationAnimation::update(){
}

void RotationAnimation::draw(){
  glEnable(GL_CULL_FACE);
  glEnable(GL_DEPTH_TEST);
  // 背景のクリア
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  // 使用するプログラムオブジェクトをする
  glUseProgram(program);

  setUniforms();

  double currentElapsedTime = glfwGetTime();

  double angle = currentElapsedTime * 180.0;

  /* 1つめの描画 */
  // モデル行列の作成
  Matrix::setIdentityM(modelMatrix, 0);
  Matrix::translateM(modelMatrix, 0, 0.0, 0.0, -4.0);
  Matrix::scaleM(modelMatrix, 0, 0.07f, 0.07f, 0.07f);
  Matrix::translateM(modelMatrix, 0, 0.0f, -polygonModel.getMaxHeight() / 2.0f, 0.0f);
  Matrix::rotateM(modelMatrix, 0, angle, 0.0, 1.0, 0.0); // y軸を軸としてangle度だけ回転させる
  // モデル行列をシェーダに設定する
  setModelMatrix();
  // モデルを描く
  drawModel();

  /* 2つめの描画 */
  // モデル行列の作成
  Matrix::setIdentityM(modelMatrix, 0);
  Matrix::translateM(modelMatrix, 0, 0.0, 0.0, -4.0);
  Matrix::scaleM(modelMatrix, 0, 0.07f, 0.07f, 0.07f);
  Matrix::translateM(modelMatrix, 0, 0.0f, -polygonModel.getMaxHeight() / 2.0f, 0.0f);
  Matrix::rotateM(modelMatrix, 0, angle, 0.0, 1.0, 0.0); // y軸を軸としてangle度だけ回転させる
  // モデル行列をシェーダに設定する
  setModelMatrix();
  // モデルを描く
  drawModel();

  // 使用するプログラムオブジェクトを解除する
  glUseProgram(0);
#if _WIN32 || (TARGET_OS_MAC && !TARGET_OS_IPHONE)
  // バッファの入れ替え
  glfwSwapBuffers(window);
  // イベントの取得
  glfwPollEvents();
#endif
}

void RotationAnimation::setModelMatrix(){
	float invertMatrix[16];
	Matrix::invertM(invertMatrix, 0, modelMatrix, 0);
	Matrix::transposeM(normalMatrix, 0, invertMatrix, 0);

	// 行列を設定する
	glUniformMatrix4fv(uniforms[UNIFORM_PROJECTION_MATRIX], 1, 0, projectionMatrix);
	glUniformMatrix4fv(uniforms[UNIFORM_MODEL_MATRIX], 1, 0, modelMatrix);
	glUniformMatrix4fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, normalMatrix);

}

void RotationAnimation::setUniforms(){
	glUniform3f(uniforms[UNIFORM_VIEW_DIRECTION], 0.0f, 0.0f, 1.0f);
	glUniform3f(uniforms[UNIFORM_LIGHT_DIRECTION], 1.0f, 0.0f, 1.0f);
	glUniform3f(uniforms[UNIFORM_LIGHT_AMBIENT_COLOR], 1.0f, 1.0f, 1.0f);
	glUniform3f(uniforms[UNIFORM_LIGHT_DIFFUSE_COLOR], 1.0f, 1.0f, 1.0f);
	glUniform3f(uniforms[UNIFORM_LIGHT_SPECULAR_COLOR], 1.0f, 1.0f, 1.0f);
	glUniform1i(uniforms[UNIFORM_SHADING_ENABLED], 1);
}

void RotationAnimation::drawModel(){
	unsigned int* vertexCounts = polygonModel.getVertexCounts();
	float* ambientColors = polygonModel.getAmbientColors();
	float* diffuseColors = polygonModel.getDiffuseColors();
	float* specularColors = polygonModel.getSpecularColors();
	float* shinness = polygonModel.getShinness();
	int sum = 0;
	for (int i = 0; i<polygonModel.getNumMaterials(); i++){
		glUniform3f(uniforms[UNIFORM_OBJECT_AMBIENT_COLOR], ambientColors[3 * i + 0], ambientColors[3 * i + 1], ambientColors[3 * i + 2]);
		glUniform3f(uniforms[UNIFORM_OBJECT_DIFFUSE_COLOR], diffuseColors[3 * i + 0], diffuseColors[3 * i + 1], diffuseColors[3 * i + 2]);
		glUniform3f(uniforms[UNIFORM_OBJECT_SPECULAR_COLOR], specularColors[3 * i + 0], specularColors[3 * i + 1], specularColors[3 * i + 2]);
		glUniform1f(uniforms[UNIFORM_OBJECT_SHINNESS], shinness[i]);
		if (textures[i] == 0){
			glUniform1i(uniforms[UNIFORM_TEXTURE_ENABLED], 0);
			glDrawElements(GL_TRIANGLES, vertexCounts[i], GL_UNSIGNED_INT, (GLvoid*)(sum*sizeof(GLuint)));
		}
		else{
			glUniform1i(uniforms[UNIFORM_TEXTURE_ENABLED], 1);
			glBindTexture(GL_TEXTURE_2D, textures[i]);
			glEnable(ATTRIBUTE_VERTEX_TEXTURE_COORDINATE);
			glDrawElements(GL_TRIANGLES, vertexCounts[i], GL_UNSIGNED_INT, (GLvoid*)(sum*sizeof(GLuint)));
			glDisable(ATTRIBUTE_VERTEX_TEXTURE_COORDINATE);
			glBindTexture(GL_TEXTURE_2D, 0);
		}
		sum += vertexCounts[i];
	}

}