綜述
該程序是在我之前的項目中修改的。
因爲3dmax不支持頂點色彩的obj文件渲染,而meshlabserver不支持導出圖片的批處理腳本。所以只好手寫openGL渲染。
這個項目的更加基本的版本是我之前的寫的一個程序:
openGL-讀取off、stl、obj文件並旋轉平移縮放操作-Zhiyang
- 讀取頂點色彩信息主要看readerOBJ即可。
- 保存圖片的關鍵函數是:
void PPMWriter(unsigned char *in,char *name,int dimx, int dimy)
{
int i, j;
FILE *fp = fopen(name, "wb"); /* b - binary mode */
(void) fprintf(fp, "P6 %d %d", dimx, dimy);
for (j = 0; j < dimy; ++j)
{
for (i = 0; i < dimx; ++i)
{
static unsigned char color[3];
color[0] = in[3*i+3*j*dimy]; /* red */
color[1] = in[3*i+3*j*dimy+1]; /* green */
color[2] = in[3*i+3*j*dimy+2]; /* blue */
(void) fwrite(color, 1, 3, fp);
}
}
(void) fclose(fp);
}
void saveScreenshotToFile(std::string filename, int windowWidth, int windowHeight) {
const int numberOfPixels = windowWidth * windowHeight * 3;
unsigned char pixels[numberOfPixels];
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadBuffer(GL_FRONT);
glReadPixels(0, 0, windowWidth, windowHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels);
FILE *outputFile = fopen(filename.c_str(), "w");
short header[] = {0, 2, 0, 0, 0, 0, (short) windowWidth, (short) windowHeight, 24};
fwrite(&header, sizeof(header), 1, outputFile);
fwrite(pixels, numberOfPixels, 1, outputFile);
fclose(outputFile);
printf("Finish writing to file.\n");
}
代碼
//
//計算機圖形學實驗2
// 作者:山東大學計算機基地班frankdura
// Standard include files
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <assert.h>
#include<string>
#include<vector>
#include<iostream>
#include <fstream>
#include <GLUT/GLUT.h>
using namespace std;
//只使用glut足夠
//支持平移旋轉縮放
//支持調整材質色彩和環境色彩
//支持off/obj/stl
int if_face=1, if_line=0, if_point=0;
//判斷三種幾何信息是否展示
//static GLfloat my_set_material[] = { 1.0, 1.0, 0.1, 0.8};
int if_control_move = 0 ;
static char *name2 = "/Users/frankdura/Desktop/CG_playground/b.stl";
string fname = "/Users/frankdura/Desktop/0.obj";
static char *filename = "/Users/frankdura/Desktop/CG_playground/bunny.off";
//展示目錄清單:
/*
obj:ddd.obj bunny.obj
off:bunny.off
stl:b.stl
*/
//設置光源的位置
void PPMWriter(unsigned char *in,char *name,int dimx, int dimy)
{
int i, j;
FILE *fp = fopen(name, "wb"); /* b - binary mode */
(void) fprintf(fp, "P6 %d %d", dimx, dimy);
for (j = 0; j < dimy; ++j)
{
for (i = 0; i < dimx; ++i)
{
static unsigned char color[3];
color[0] = in[3*i+3*j*dimy]; /* red */
color[1] = in[3*i+3*j*dimy+1]; /* green */
color[2] = in[3*i+3*j*dimy+2]; /* blue */
(void) fwrite(color, 1, 3, fp);
}
}
(void) fclose(fp);
}
void saveScreenshotToFile(std::string filename, int windowWidth, int windowHeight) {
const int numberOfPixels = windowWidth * windowHeight * 3;
unsigned char pixels[numberOfPixels];
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadBuffer(GL_FRONT);
glReadPixels(0, 0, windowWidth, windowHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels);
FILE *outputFile = fopen(filename.c_str(), "w");
short header[] = {0, 2, 0, 0, 0, 0, (short) windowWidth, (short) windowHeight, 24};
fwrite(&header, sizeof(header), 1, outputFile);
fwrite(pixels, numberOfPixels, 1, outputFile);
fclose(outputFile);
printf("Finish writing to file.\n");
}
static GLfloat light0_position[] = { 4.0, 4.0, 4.0, 0.0 };
static GLfloat light1_position[] = { -3.0, -3.0, -3.0, 0.0 };
typedef struct Vertex {
//定義三維圖形的
//用於face結構體中
float x, y, z;
float r,g,b;
} Vertex;
typedef struct Face {
//多邊形(三角形)面的結構體
Face(void) : vert_number(0), verts(0) {};
int vert_number; //記錄頂點的個數
Vertex **verts; //這是一個面的所有 頂點數組(含有座標)
float normal[3]; //記錄點的法向量,分別是x,y,z三個方向
//注意點的法向量通過頂點的信息計算得到!
//對於obj模型如果我們已經得到了法線的信息
//那麼就直接拿來用就好!
} Face;
typedef struct myMesh {
//自定義mesh的結構體
myMesh(void) : vert_number(0), verts(0), face_number(0), faces(0) {};
//自定義構造器
int vert_number; //總的頂點個數
Vertex *verts; //定點數組
int face_number; //面的數目
Face *faces;
vector<Vertex>point;
} myMesh;
//輸入指定的文件名
static int GLUTwindow = 0;
static int GLUTwindow_height = 800; //設置窗口的大小
static int GLUTwindow_width = 1000;
static int GLUTmouse[2] = { 0, 0 };
static int GLUTbutton[3] = { 0, 0, 0 };
static int GLUTarrows[4] = { 0, 0, 0, 0 };
static int GLUTmodifiers = 0;
static int scaling = 0;
static int translating = 0;
static int rotating = 0;
static float scale = 2.0;
static float center[3] = { 0.0, 0.0, 0.0 };
static float rotation[3] = { 0.0, 0.0, 0.0 };
static float translation[3] = { 0.0, 0.0, -4.0 };
static myMesh *mesh = NULL;
vector<vector<GLfloat> > vcolor; // lazy style
void get_normal( Face& face){
//計算面法線!
//計算面的法線
//通過公式計算:
face.normal[0] = face.normal[1] = face.normal[2] = 0;
Vertex *v1 = face.verts[face.vert_number-1];
for (int i = 0; i < face.vert_number; i++) {
Vertex *v2 = face.verts[i];
//新建所有的點
face.normal[0] += (v1->y - v2->y) * (v1->z + v2->z);
face.normal[1] += (v1->z - v2->z) * (v1->x + v2->x);
face.normal[2] += (v1->x - v2->x) * (v1->y + v2->y);
//首先完成叉乘的工作
v1 = v2;
}
//計算歸一化法線
float squared_normal_length = 0.0;
squared_normal_length += face.normal[0]*face.normal[0];
squared_normal_length += face.normal[1]*face.normal[1];
squared_normal_length += face.normal[2]*face.normal[2];
float normal_length = sqrt(squared_normal_length);
//得到歸一化長度
if (normal_length > 1.0E-6) {
face.normal[0] /= normal_length;
face.normal[1] /= normal_length;
face.normal[2] /= normal_length;
}
//然後完成歸一化任務
}
vector<string> split(const string &str,const string &pattern)
{
//進行字符串的切割
//const char* convert to char*
char * strc = new char[strlen(str.c_str())+1];
strcpy(strc, str.c_str());
vector<string> resultVec;
char* tmpStr = strtok(strc, pattern.c_str());
while (tmpStr != NULL)
{
resultVec.push_back(string(tmpStr));
tmpStr = strtok(NULL, pattern.c_str());
}
delete[] strc;
return resultVec;
}
myMesh * ReadASCII(const char *cfilename);
myMesh * ReadBinary(const char *cfilename);
myMesh * ReadSTLFile(const char *cfilename)
{
//只處理三角形足夠了!
if (cfilename == NULL)
return 0;
std::ifstream in(cfilename, std::ifstream::in);
if (!in)
return 0;
std::string headStr;
getline(in, headStr, ' ');
in.close();
if (headStr.empty())
return 0;
if (headStr[0] == 's')
return ReadASCII(cfilename);
else
return ReadBinary(cfilename);
}
myMesh * ReadASCII(const char *cfilename)
{
std::vector<float> coorX;
std::vector<float> coorY;
std::vector<float> coorZ;
int i = 0, j = 0, cnt = 0, pCnt = 4;
char a[100];
char str[100];
double x = 0, y = 0, z = 0;
std::ifstream in(cfilename, std::ifstream::in);
if (!in)
return 0;
do
{
i = 0;
cnt = 0;
in.getline(a, 100, '\n');
while (a[i] != '\0')
{
if (!islower((int)a[i]) && !isupper((int)a[i]) && a[i] != ' ')
break;
cnt++;
i++;
}
while (a[cnt] != '\0')
{
str[j] = a[cnt];
cnt++;
j++;
}
str[j] = '\0';
j = 0;
if (sscanf(str, "%lf%lf%lf", &x, &y, &z) == 3)
{
coorX.push_back(x);
coorY.push_back(y);
coorZ.push_back(z);
}
pCnt++;
} while (!in.eof());
return 0;
}
myMesh * ReadBinary(const char *cfilename)
{
std::vector<GLfloat> coorX;
std::vector<GLfloat> coorY;
std::vector<GLfloat> coorZ;
char str[80];
std::ifstream in(cfilename, std::ifstream::in | std::ifstream::binary);
if (!in)
return 0;
//首先使用二進制讀入文件
myMesh *meshs = new myMesh(); //建立我們的mesh類
in.read(str, 80);
int triangles; //triangles 記錄了三角面的數目
in.read((char*)&triangles, sizeof(int));
if (triangles == 0)
return 0;
for (int i = 0; i < triangles; i++)
{
//開始處理三角片 所以面的數量計數器++
float coorXYZ[12];
in.read((char*)coorXYZ, 12 * sizeof(float));
for (int j = 1; j < 4; j++)
{
//三個四字節信息
//分別處理每個座標點
coorX.push_back(coorXYZ[j * 3]);
coorY.push_back(coorXYZ[j * 3 + 1]);
coorZ.push_back(coorXYZ[j * 3 + 2]);
//將點的信息壓入暫存數組
//由於stl文件特性只需要保持三個一組進行最後的劃分即可!
}
in.read((char*)coorXYZ, 2);
}
in.close();
//向結構體進行轉換
int vert_number = coorX.size();
int face_number = triangles;
meshs->verts = new Vertex [vert_number+1];
assert(meshs->verts);
//處理點的信息
for(int i = 0 ; i < vert_number;i++)
{
Vertex& vert = meshs->verts[meshs->vert_number++];
vert.x =coorX[i];
vert.y =coorY[i];
vert.z =coorZ[i];
}
//處理面的信息
meshs->faces = new Face [face_number];
assert(meshs->faces);
int index=0;
for(int i = 0; i < face_number;i++)
{
Face fa ;
fa.vert_number = 3; //這裏直接設置爲定3即可! STL三角片決定的!
fa.verts =new Vertex* [fa.vert_number];
for (int j = 0 ; j < 3; j++) {
fa.verts[j] = &meshs->verts[index++];
}
get_normal(fa);
meshs->faces[meshs->face_number++] = fa;
//首先分配第一維數組
}
return meshs;
}
//讀取obj文件
myMesh * ReaderOBj(string fname2) {
string line;
fstream f;
f.open(fname2, ios::in);
if (!f.is_open()) {
cout << "文件打開出錯" << endl;
}
vector<vector<GLfloat> > vset;
vector<vector<GLint> > fset;
int v_counter = 1;
int f_counter = 1;
while (!f.eof()) {
getline(f, line);//拿到obj文件中一行,作爲一個字符串
vector<string>parameters;
string tailMark = " ";
string ans = "";
line = line.append(tailMark);
if(line[0]!='v'&&line[0]!='f'){
continue;
}
for (int i = 0; i < line.length(); i++) {
char ch = line[i];
if (ch != ' ') {
ans += ch;
}
else {
if(ans!=""){
parameters.push_back(ans); //取出字符串中的元素,以空格切分
ans = "";}
}
}
cout << endl;
if (parameters[0] == "v") { //如果是頂點的話
vector<GLfloat>Point;
vector<GLfloat>color;
v_counter++;
// cout <<atof( parameters[1].c_str()) << "--" << atof( parameters[2].c_str()) <<" -- " << atof( parameters[3].c_str());
Point.push_back(atof( parameters[1].c_str()));
Point.push_back(atof( parameters[2].c_str()));
Point.push_back(atof( parameters[3].c_str()));
color.push_back(atof( parameters[4].c_str()));
color.push_back(atof( parameters[5].c_str()));
color.push_back(atof( parameters[6].c_str()));
vset.push_back(Point);
vcolor.push_back(color);
}
else if (parameters[0] == "f") { //如果是面的話,存放頂點的索引
vector<GLint>vIndexSets; //臨時存放點的集合
for (int i = 1; i < 4; i++) {
string x = parameters[i];
string ans = "";
for (int j = 0; j < x.length(); j++) { //跳過‘/’
char ch = x[j];
if (ch != '/') {
ans += ch;
}
else {
break;
}
}
vector<string >res = split(ans,"/");
int index = atof(res[0].c_str());
index--;//因爲頂點索引在obj文件中是從1開始的,而我們存放的頂點vector是從0開始的,因此要減1
vIndexSets.push_back(index);
}
fset.push_back(vIndexSets);
}
}
f.close();
myMesh *meshs = new myMesh(); //建立我們的mesh類
// cout << fset.size() << endl;
// cout << vset.size() << endl;
//向結構體進行轉換
int vert_number = vset.size();
int face_number = fset.size();
meshs->verts = new Vertex [vert_number+1];
assert(meshs->verts);
//處理mesh的信息
//----------------處理點的信息 --------------
for(int i = 0 ; i < vset.size();i++)
{
Vertex& vert = meshs->verts[meshs->vert_number++];
vert.x = vset[i][0];
vert.y = vset[i][1];
vert.z = vset[i][2];
vert.r = vcolor[i][0];
vert.g = vcolor[i][1];
vert.b = vcolor[i][2];
}
//----------------處理面信息 --------------
meshs->faces = new Face [face_number];
assert(meshs->faces);
for(int i = 0; i < fset.size();i++)
{
Face a ;
a.vert_number = fset[i].size();
a.verts =new Vertex* [fset[i].size()];
for (int j = 0 ; j < fset[i].size(); j++) {
a.verts[j] = &meshs->verts[fset[i][j]];
}
get_normal(a);
meshs->faces[meshs->face_number++] = a;
//首先分配第一維數組
}
return meshs;
}
//讀取off文件
myMesh * ReadOffFile(const char *filename)
{ /*
函數說明: 對文件進行讀取,讀取的是off文件
*/
int i;
FILE *fp; //開始讀入文件
if (!(fp = fopen(filename, "r"))) {
cout << "無法打開文件" << endl;
return 0;
}
myMesh *mesh = new myMesh(); //建立我們的mesh類
//進行讀入文件的操作
int vert_number = 0; //記錄頂點個數
int face_number = 0; //記錄面的個數
int line_number = 0; //記錄邊的個數
int line_count = 0; //這個是我讀入了幾行
char buffer[1024];
while (fgets(buffer, 1023, fp)) {
line_count++;
char *bufferp = buffer;
while (isspace(*bufferp)) bufferp++;
if (*bufferp == '#') continue;
if (*bufferp == '\0') continue;
if (vert_number == 0) {
if (!strstr(bufferp, "OFF")) {
if ((sscanf(bufferp, "%d%d%d", &vert_number, &face_number, &line_number) != 3) || (vert_number == 0)) {
cout << "存在語法錯誤!" << endl;
fclose(fp);
return NULL;
}
//存儲頂點的信息
cout << "aa" << vert_number << "--" << face_number << endl;
mesh->verts = new Vertex [vert_number];
assert(mesh->verts);
//存儲面的信息
mesh->faces = new Face [face_number];
assert(mesh->faces);
//如果頭文件信息合適那麼開闢內存空間
}
}
else if (mesh->vert_number < vert_number) {
Vertex& vert = mesh->verts[mesh->vert_number++];
if (sscanf(bufferp, "%f%f%f", &(vert.x), &(vert.y), &(vert.z)) != 3) {
cout << "點的信息中,數據量不足(3個)" << endl;
fclose(fp);
return NULL;
}
}
else if (mesh->face_number < face_number) {
Face& face = mesh->faces[mesh->face_number++]; //新建一個face對象
bufferp = strtok(bufferp, " \t");
if (bufferp) face.vert_number = atoi(bufferp);
else {
fclose(fp);
return NULL;
}
face.verts = new Vertex *[face.vert_number];
//建立面的數組
assert(face.verts);
for (i = 0; i < face.vert_number; i++) {
bufferp = strtok(NULL, " \t");
if (bufferp) face.verts[i] = &(mesh->verts[atoi(bufferp)]);
else {
fprintf(stderr, "Syntax error with face on line %d in file %s\n", line_count, filename);
fclose(fp);
return NULL;
}
}
get_normal(face);
}
else {
cout << "格式存在錯誤!" << endl;
break;
}
}
//判斷實際的 面 的數目是否和要求數目一樣!
if (face_number != mesh->face_number) {
cout << "面的數目與實際不符"<<endl;
}
fclose(fp);
return mesh;
}
void draw_faces(){
for (int i = 0; i < mesh->face_number; i++) {
//注意我們的操作都是
Face& face = mesh->faces[i];
glBegin(GL_POLYGON); //繪製多邊形即可!
//在繪製面的過程中載入我們已經計算好的法線量信息
glNormal3fv(face.normal); //在繪製面的時候同時載入法向量信息
for (int j = 0; j < face.vert_number; j++) {
Vertex *vert = face.verts[j];
glVertex3f(vert->x, vert->y, vert->z);
glColor3f(vert->r,vert->g, vert->b);
}
glEnd();
}
}
void draw_points(){
//下面繪製點的信息
//依次將面的信息點進行遍歷
glColor3f(0.0, 1.0, 0.0);
glPointSize(2);
glBegin(GL_POINTS);
for (int j = 0 ; j < mesh->vert_number; j++) {
glVertex3f(mesh->verts[j].x, mesh->verts[j].y,mesh->verts[j].z);
}
glEnd();
// for (int i = 0; i < mesh->face_number; i++) {
// Face& face = mesh->faces[i];
// glColor3f(0.0, 1.0, 0.0);
// glPointSize(1);
// glBegin(GL_POINTS);
//
// for (int j = 0; j < face.vert_number; j++) {
// Vertex *vert = face.verts[j];
//// cout << vert->x << " " << vert->y <<" "<<vert ->z << endl;
// glVertex3f(vert->x, vert->y, vert->z);
// }
// glEnd();
// }
}
void draw_lines(){
double temp_x,temp_y,temp_z;
for (int i = 0; i < mesh->face_number; i++) {
Face& face = mesh->faces[i];
glColor3f(0, 0, 1);
glBegin(GL_LINES);
for (int j = 0; j < face.vert_number; j++) {
Vertex *vert = face.verts[j];
if(j==0){
temp_x = vert->x;
temp_y = vert->y;
temp_z = vert->z;
continue;
}
glVertex3f(temp_x, temp_y, temp_z);
glVertex3f(vert->x, vert->y, vert->z);
temp_x = vert->x;
temp_y = vert->y;
temp_z = vert->z;
}
glEnd();
}
}
void GLUTRedraw(void)
{
//進行空間的重繪
glLoadIdentity();
glScalef(scale, scale, scale);
glTranslatef(translation[0], translation[1], 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (GLfloat) GLUTwindow_width /(GLfloat) GLUTwindow_height, 0.1, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(translation[0], translation[1], translation[2]);
glScalef(scale, scale, scale);
//刷新放縮的大小
glRotatef(rotation[0], 1.0, 0.0, 0.0);
glRotatef(rotation[1], 0.0, 1.0, 0.0); //控制不同角度
glRotatef(rotation[2], 0.0, 0.0, 1.0);
glTranslatef(-center[0], -center[1], -center[2]);
//改變旋轉中心
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//設置光照
//載入不同光源的位置
glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
glLightfv(GL_LIGHT1, GL_POSITION, light1_position);
//定義材料信息
//這裏可以調整環境顏色和散射顏色數組
// glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, my_set_material);
// 下面開始繪製表面
if(if_face==1)
draw_faces();
if(if_line==1)
draw_lines();
if(if_point==1)
draw_points();
glutSwapBuffers();
}
void GLUTResize(int w, int h)
{
glViewport(0, 0, w, h);
//當用戶拖拽之後用獲取的高度和寬度信息去更新全局變量
GLUTwindow_width = w;
GLUTwindow_height = h;
glutPostRedisplay();
}
void GLUTMotion(int x, int y)
{
//通過鼠標事件控制所調用的活動類型!
//真正的鼠標控制事件的執行者
y = GLUTwindow_height - y;
if (rotating) {
//控制旋轉的信號
rotation[0] += -0.5 * (y - GLUTmouse[1]);
rotation[2] += 0.5 * (x - GLUTmouse[0]);
//rotation[1] += 0.5 * (x - GLUTmouse[0]);
//這樣可以面向你進行旋轉
//在重繪的時候就可以了
}
else if (scaling) {
// 控制縮放信號
//GLUTmouse存儲了之前記錄的點信息
scale *= exp(2.0 * (float)( (x- GLUTmouse[0])) / (float) GLUTwindow_width);
//如果想調成按照y方向控制可以:
// scale *= exp(2.0 * (float)( (y- GLUTmouse[1])) / (float) GLUTwindow_width);
}
else if (translating) {
// 控制平移信號
translation[0] += 2.0 * (float) (x - GLUTmouse[0]) / (float) GLUTwindow_width;
translation[1] += 2.0 * (float) (y - GLUTmouse[1]) / (float) GLUTwindow_height;
}
//我們在拖拽旋轉的過程中需要設置定點中心
GLUTmouse[0] = x;
GLUTmouse[1] = y;
//刷新定點
}
void GLUTMouse(int button, int state, int x, int y)
{ cout << "控制鍵的情況: " << if_control_move << endl;
y = GLUTwindow_height - y;
int kind = 0;
if(button == GLUT_LEFT_BUTTON&&if_control_move){
translating = 1;
cout << "double" << endl;
kind=2;
rotating=0;
scaling = 0;
}else{if(button == GLUT_LEFT_BUTTON&&button != GLUT_RIGHT_BUTTON){
kind = 0;
rotating =1;
scaling = 0;
translating = 0;
}else if(button != GLUT_LEFT_BUTTON&&button == GLUT_RIGHT_BUTTON){
kind = 1;
scaling = 1;
rotating =0;
translating = 0;
}}
if (rotating || scaling || translating) glutIdleFunc(GLUTRedraw);
else glutIdleFunc(0);
cout << "此時的B 選擇的操作:"<< kind<< endl;
GLUTbutton[kind] = (state == GLUT_DOWN) ? 1 : 0;
GLUTmodifiers = glutGetModifiers();
GLUTmouse[0] = x;
GLUTmouse[1] = y;
}
void GLUTSpecial(int key, int x, int y)
{
y = GLUTwindow_height - y;
//記錄當下鼠標點擊的位置
GLUTmouse[0] = x;
GLUTmouse[1] = y;
// Remember modifiers
GLUTmodifiers = glutGetModifiers();
glutPostRedisplay();
}
void GLUTKeyboard(unsigned char key, int x, int y)
{
// Process keyboard button event
//處理鼠標事件
GLint viewPort[4] = {0};
switch (key) {
case '1':
cout << "打開/關閉點的信息" << endl;
if_point = 1 - if_point;
break;
case '2':
cout << "打開/關閉線的信息" << endl;
if_line = 1 - if_line;
break;
case '3':
cout << "打開/關閉面的信息" << endl;
if_face = 1 - if_face;
break;
//調節表面的材質的信息
case 'z':
if_control_move = 1 - if_control_move;
break;
case 'c':
saveScreenshotToFile("/Users/frankdura/Desktop/test.tga", 1000, 700);
break;
// case 'q':
// my_set_material[0] += 0.1;
// break;
// case 'w':
// my_set_material[1] += 0.1;
// break;
// case 'e':
// my_set_material[2] += 0.1;
// break;
// case 'r':
// my_set_material[3] += 0.1;
// break;
// case 'a':
// my_set_material[0] -= 0.1;
// break;
// case 's':
// my_set_material[1] -= 0.1;
// break;
// case 'd':
// my_set_material[2] -= 0.1;
// break;
// case 'f':
// my_set_material[3] -= 0.1;
// break;
case '4':
for(int i = 0 ; i < 4 ;i ++){
light0_position [i]+=0.01;
}
break;
case '5':
for(int i = 0 ; i < 4 ;i ++){
light0_position [i]-=0.01;
if(light0_position[i]<=0)
light0_position[i] = 0;
}
break;
case '6':
for(int i = 0 ; i < 4 ;i ++){
cout <<light1_position [i] << " ~~ "<< endl;
light1_position [i]+=0.01;
}
break;
case '7':
for(int i = 0 ; i < 4 ;i ++){
light1_position [i]-=0.01;
cout <<light1_position [i] << " ~~ "<< endl;
if(light1_position[i]<=0)
light1_position[i] = 0;
}
break;
}
// Remember mouse position
GLUTmouse[0] = x;
GLUTmouse[1] = GLUTwindow_height - y;
// Remember modifiers
GLUTmodifiers = glutGetModifiers();
}
void GLUTInit(int *argc, char **argv)
{
// Open window
glutInit(argc, argv);
glutInitWindowPosition(100, 100);
glutInitWindowSize(GLUTwindow_width, GLUTwindow_height);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); // | GLUT_STENCIL
GLUTwindow = glutCreateWindow("myreader_by_zhiyang~");
glutReshapeFunc(GLUTResize);
//設置重繪信息
glutDisplayFunc(GLUTRedraw);
//註冊鍵盤事件
glutKeyboardFunc(GLUTKeyboard);
glutSpecialFunc(GLUTSpecial);
glutMouseFunc(GLUTMouse);
glutMotionFunc(GLUTMotion);
glutIdleFunc(0);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_POLYGON_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// 設置光照信息
// static GLfloat lmodel_ambient[] = { 0.2, 0.2, 0.2, 1.0 };
// glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
// glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
// static GLfloat light0_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
// 設置滿散射
// glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
// glEnable(GL_LIGHT0);
// static GLfloat light1_diffuse[] = { 0.5, 0.5, 0.5, 1.0 };
// glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
// glEnable(GL_LIGHT1);
glEnable(GL_NORMALIZE);
// glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
}
void GLUTMainLoop(void)
{
float bbox[2][3] = { { 1.0E30F, 1.0E30F, 1.0E30F }, { -1.0E30F, -1.0E30F, -1.0E30F } };
for (int i = 0; i < mesh->vert_number; i++) {
Vertex& vert = mesh->verts[i];
if (vert.x < bbox[0][0]) bbox[0][0] = vert.x;
else if (vert.x > bbox[1][0]) bbox[1][0] = vert.x;
if (vert.y < bbox[0][1]) bbox[0][1] = vert.y;
else if (vert.y > bbox[1][1]) bbox[1][1] = vert.y;
if (vert.z < bbox[0][2]) bbox[0][2] = vert.z;
else if (vert.z > bbox[1][2]) bbox[1][2] = vert.z;
}
// Setup initial viewing scale
float dx = bbox[1][0] - bbox[0][0];
float dy = bbox[1][1] - bbox[0][1];
float dz = bbox[1][2] - bbox[0][2];
scale = 3.5 / sqrt(dx*dx + dy*dy + dz*dz);
// Setup initial viewing center
center[0] = 0.5 * (bbox[1][0] + bbox[0][0]);
center[1] = 0.5 * (bbox[1][1] + bbox[0][1]);
center[2] = 0.5 * (bbox[1][2] + bbox[0][2]);
glutMainLoop();
//計算並更新視角邊框以及中心
}
int main(int argc, char **argv)
{
GLUTInit(&argc, argv);
mesh = ReaderOBj(fname); //objreader;
//obj和off很相似
// mesh = ReadSTLFile(name2);
// mesh = ReadOffFile(filename);
GLUTMainLoop();
return 0;
}