26 changed files with 137074 additions and 33 deletions
-
37.gitignore
-
35CMakeLists.txt
-
12build.sh
-
77742models/chair/chair.vrscene
-
BINmodels/chair/chair2.bin
-
1models/chair/chair2.gltf
-
30models/chair/chair2.mtl
-
51869models/chair/chair2.obj
-
BINmodels/chair/cloth.jpg
-
1models/chair/common.txt
-
BINmodels/chair/wood.jpg
-
5933src/common/CELLMath.hpp
-
141src/common/GlewOpenGL.cc
-
34src/common/GlewOpenGL.h
-
29src/common/base.h
-
6src/example/CMakeLists.txt
-
78src/example/enhance.cc
-
63src/example/example.cc
-
72src/example/rect.cc
-
8src/viewer/CMakeLists.txt
-
45src/viewer/gltfviewer.cc
-
104src/viewer/objviewer.cc
-
292src/viewer/trackball.cc
-
75src/viewer/trackball.h
-
77src/viewer/viewer.cc
-
423src/viewer/viewer0.1.cc
@ -1,34 +1,5 @@ |
|||
# ---> C++ |
|||
# Prerequisites |
|||
*.d |
|||
|
|||
# Compiled Object files |
|||
*.slo |
|||
*.lo |
|||
*.o |
|||
*.obj |
|||
|
|||
# Precompiled Headers |
|||
*.gch |
|||
*.pch |
|||
|
|||
# Compiled Dynamic libraries |
|||
*.so |
|||
*.dylib |
|||
*.dll |
|||
|
|||
# Fortran module files |
|||
*.mod |
|||
*.smod |
|||
|
|||
# Compiled Static libraries |
|||
*.lai |
|||
*.la |
|||
*.a |
|||
*.lib |
|||
|
|||
# Executables |
|||
*.exe |
|||
*.out |
|||
*.app |
|||
# building directory |
|||
build |
|||
|
|||
# netbeans project files |
|||
nbproject |
@ -0,0 +1,35 @@ |
|||
cmake_minimum_required (VERSION 3.10) |
|||
|
|||
project(3dbase) |
|||
|
|||
set(CMAKE_CXX_COMPILER "g++") |
|||
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) |
|||
|
|||
set(CXX_FLAGS |
|||
-g |
|||
-std=c++11 |
|||
) |
|||
|
|||
|
|||
find_package(Boost REQUIRED) |
|||
find_package(glfw3 3.3 REQUIRED) |
|||
find_package(OpenGL REQUIRED) |
|||
|
|||
include_directories(${Boost_INCLUDE_DIRS}) |
|||
include_directories(/usr/include/GL) |
|||
|
|||
set(GLFW_LIB |
|||
glfw |
|||
GLEW |
|||
EGL |
|||
freeimage |
|||
${OPENGL_gl_LIBRARY} |
|||
${OPENGL_glu_LIBRARY} |
|||
) |
|||
|
|||
set(COM_SRC |
|||
../common/GlewOpenGL.cc |
|||
) |
|||
|
|||
add_subdirectory(src/example) |
|||
add_subdirectory(src/viewer) |
@ -0,0 +1,12 @@ |
|||
#!/bin/sh |
|||
|
|||
set -x |
|||
|
|||
SOURCE_DIR=`pwd` |
|||
BUILD_DIR=${BUILD_DIR:-./build} |
|||
|
|||
mkdir -p $BUILD_DIR \ |
|||
&& cd $BUILD_DIR \ |
|||
&& cmake $SOURCE_DIR \ |
|||
&& make $* |
|||
|
77742
models/chair/chair.vrscene
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1 @@ |
|||
{"accessors":[{"bufferView":0,"byteOffset":0,"componentType":5126,"count":10793,"max":[315.0035,280.4064,355.3964],"min":[-315.0035,-0.004,-231.1051],"type":"VEC3"},{"bufferView":0,"byteOffset":129516,"componentType":5126,"count":10793,"max":[1.0,0.9983,0.9999],"min":[-1.0,-1.0,-0.9984],"type":"VEC3"},{"bufferView":0,"byteOffset":259032,"componentType":5126,"count":10793,"max":[1.0,1.0],"min":[0.0,9.999999999998899e-05],"type":"VEC2"},{"bufferView":1,"byteOffset":0,"componentType":5123,"count":11916,"max":[10792],"min":[0],"type":"SCALAR"},{"bufferView":0,"byteOffset":345376,"componentType":5126,"count":9297,"max":[336.932,734.8419,368.0536],"min":[-336.9319,243.7294,-368.0536],"type":"VEC3"},{"bufferView":0,"byteOffset":456940,"componentType":5126,"count":9297,"max":[1.0,0.9999,1.0],"min":[-0.9983,-0.9999,-1.0],"type":"VEC3"},{"bufferView":0,"byteOffset":568504,"componentType":5126,"count":9297,"max":[2.0229,2.27],"min":[-1.0229,-1.2932000000000001],"type":"VEC2"},{"bufferView":1,"byteOffset":23832,"componentType":5123,"count":44592,"max":[9296],"min":[0],"type":"SCALAR"}],"asset":{"generator":"ClayGL - fbx2gltf","version":"2.0"},"bufferViews":[{"buffer":0,"byteLength":642880,"byteOffset":0,"target":34962},{"buffer":0,"byteLength":113016,"byteOffset":642880,"target":34963}],"buffers":[{"byteLength":755896,"uri":"chair2.bin"}],"images":[{"uri":"wood.jpg"},{"uri":"cloth.jpg"}],"materials":[{"emissiveFactor":[0.0,0.0,0.0],"name":"Standardmaterial","pbrMetallicRoughness":{"baseColorFactor":[1,1,1,1],"baseColorTexture":{"index":0,"texCoord":0},"metallicFactor":0,"roughnessFactor":1}},{"emissiveFactor":[0.0,0.0,0.0],"name":"default","pbrMetallicRoughness":{"baseColorFactor":[1,1,1,1],"baseColorTexture":{"index":1,"texCoord":0},"metallicFactor":0,"roughnessFactor":1}}],"meshes":[{"name":"Obj3d66_710146_1_824","primitives":[{"attributes":{"NORMAL":1,"POSITION":0,"TEXCOORD_0":2},"indices":3,"material":0}]},{"name":"Obj3d66_710146_2_295","primitives":[{"attributes":{"NORMAL":5,"POSITION":4,"TEXCOORD_0":6},"indices":7,"material":1}]}],"nodes":[{"children":[1,2],"matrix":[1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0],"name":"chair2_root"},{"matrix":[1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0],"mesh":0,"name":"Obj3d66_710146_1_824"},{"matrix":[1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0],"mesh":1,"name":"Obj3d66_710146_2_295"}],"samplers":[{"magFilter":9729,"minFilter":9987,"wrapS":10497,"wrapT":10497}],"scene":0,"scenes":[{"nodes":[0]}],"textures":[{"format":6408,"internalFormat":6408,"sampler":0,"source":0,"target":3553},{"format":6408,"internalFormat":6408,"sampler":0,"source":1,"target":3553}]} |
@ -0,0 +1,30 @@ |
|||
# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware |
|||
# ´´½¨µÄÎļş:10.03.2020 16:27:17 |
|||
|
|||
newmtl Standardmaterial |
|||
Ns 10.0000 |
|||
Ni 1.5000 |
|||
d 1.0000 |
|||
Tr 0.0000 |
|||
Tf 1.0000 1.0000 1.0000 |
|||
illum 2 |
|||
Ka 0.0000 0.0000 0.0000 |
|||
Kd 0.5880 0.5880 0.5880 |
|||
Ks 0.0000 0.0000 0.0000 |
|||
Ke 0.0000 0.0000 0.0000 |
|||
map_Ka wood.jpg |
|||
map_Kd wood.jpg |
|||
|
|||
newmtl default |
|||
Ns 10.0000 |
|||
Ni 1.5000 |
|||
d 1.0000 |
|||
Tr 0.0000 |
|||
Tf 1.0000 1.0000 1.0000 |
|||
illum 2 |
|||
Ka 0.0000 0.0000 0.0000 |
|||
Kd 0.5880 0.5880 0.5880 |
|||
Ks 0.0000 0.0000 0.0000 |
|||
Ke 0.0000 0.0000 0.0000 |
|||
map_Ka cloth.jpg |
|||
map_Kd cloth.jpg |
51869
models/chair/chair2.obj
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
After Width: 1366 | Height: 1366 | Size: 1.9 MiB |
@ -0,0 +1 @@ |
|||
~/Documents/dev/python/fbx2gltf.py ./chair.obj |
After Width: 2750 | Height: 4800 | Size: 3.1 MiB |
5933
src/common/CELLMath.hpp
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,141 @@ |
|||
/*
|
|||
* To change this license header, choose License Headers in Project Properties. |
|||
* To change this template file, choose Tools | Templates |
|||
* and open the template in the editor. |
|||
*/ |
|||
|
|||
#include <glew.h>
|
|||
#include <GLFW/glfw3.h>
|
|||
#include <EGL/egl.h>
|
|||
|
|||
#include <stdio.h>
|
|||
#include <math.h>
|
|||
#include <iostream>
|
|||
#include <string>
|
|||
#include <string.h>
|
|||
|
|||
#include "base.h"
|
|||
#include "FreeImage.h"
|
|||
#include "GlewOpenGL.h"
|
|||
#include "../common/CELLMath.hpp"
|
|||
|
|||
using namespace std; |
|||
using namespace CELL; |
|||
|
|||
GlewOpenGL::GlewOpenGL(int width, int height, const string& title) : _width(width), _height(height), _title(title) { |
|||
|
|||
/* Initialize the library */ |
|||
if (!glfwInit()) |
|||
die("glfwInit"); |
|||
|
|||
/* Create a windowed mode window and its OpenGL context */ |
|||
_window = glfwCreateWindow(_width, _height, _title.c_str(), NULL, NULL); |
|||
if (!_window) { |
|||
glfwTerminate(); |
|||
die("glfwCreateWindow"); |
|||
} |
|||
|
|||
/* Make the window's context current */ |
|||
glfwMakeContextCurrent(_window); |
|||
|
|||
/*初始化 glew*/ |
|||
glewInit(); |
|||
} |
|||
|
|||
GlewOpenGL::GlewOpenGL(const GlewOpenGL& orig) { |
|||
|
|||
} |
|||
|
|||
GlewOpenGL::~GlewOpenGL() { |
|||
shutDown(); |
|||
} |
|||
|
|||
/**
|
|||
* 上下文关闭的处理 |
|||
*/ |
|||
void GlewOpenGL::shutDown() { |
|||
glfwDestroyWindow(_window); |
|||
glfwTerminate(); |
|||
} |
|||
|
|||
/**
|
|||
* 循环渲染结果 |
|||
*/ |
|||
void GlewOpenGL::loop() { |
|||
init(); |
|||
/* Loop until the user closes the window */ |
|||
while (!glfwWindowShouldClose(_window)) { |
|||
|
|||
/* Render here */ |
|||
render(); |
|||
|
|||
/* Swap front and back buffers */ |
|||
glfwSwapBuffers(_window); |
|||
|
|||
/* Poll for and process events */ |
|||
glfwPollEvents(); |
|||
} |
|||
} |
|||
|
|||
/**
|
|||
* 把图片读到内存 |
|||
* @param fileName 文件路径 |
|||
* @return |
|||
*/ |
|||
FIBITMAP* GlewOpenGL::readImage(const char* fileName) { |
|||
cout << fileName << endl; |
|||
//获取图片格式
|
|||
FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName, 0); |
|||
if (fifmt == FIF_UNKNOWN) { |
|||
printf("%s\n", fileName); |
|||
die("File not found"); |
|||
} |
|||
|
|||
//加载图片
|
|||
FIBITMAP *dib = FreeImage_Load(fifmt, fileName, 0); |
|||
|
|||
//转32位
|
|||
FIBITMAP* temp = dib; |
|||
dib = FreeImage_ConvertTo32Bits(dib); |
|||
FreeImage_Unload(temp); |
|||
|
|||
BYTE* pixels = (BYTE*) FreeImage_GetBits(dib); |
|||
int width = FreeImage_GetWidth(dib); |
|||
int height = FreeImage_GetHeight(dib); |
|||
|
|||
//颜色为数调换
|
|||
for (int i = 0; i < width * height * 4; i += 4) { |
|||
BYTE temp = pixels[i]; |
|||
pixels[i] = pixels[i + 2]; |
|||
pixels[i + 2] = temp; |
|||
} |
|||
|
|||
return dib; |
|||
} |
|||
|
|||
/**
|
|||
* 创建图片纹理 |
|||
* @param fileName |
|||
* @return |
|||
*/ |
|||
GLuint GlewOpenGL::createTexture(const char* fileName) { |
|||
GLuint texture; |
|||
glEnable(GL_TEXTURE_2D); |
|||
glGenTextures(1, &texture); |
|||
glBindTexture(GL_TEXTURE_2D, texture); |
|||
|
|||
{ |
|||
FIBITMAP* dib = readImage(fileName); |
|||
BYTE* pixels = (BYTE*) FreeImage_GetBits(dib); |
|||
int width = FreeImage_GetWidth(dib); |
|||
int height = FreeImage_GetHeight(dib); |
|||
//设置模型缩放时线性跟随
|
|||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
|||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
|||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); |
|||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); |
|||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); |
|||
} |
|||
|
|||
return texture; |
|||
} |
@ -0,0 +1,34 @@ |
|||
|
|||
#ifndef GLEWOPENGL_H |
|||
#define GLEWOPENGL_H |
|||
|
|||
#include <string> |
|||
#include <GLFW/glfw3.h> |
|||
#include "FreeImage.h" |
|||
|
|||
using namespace std; |
|||
|
|||
class GlewOpenGL { |
|||
public: |
|||
GlewOpenGL(int width, int height, const string& title); |
|||
GlewOpenGL(const GlewOpenGL& orig); |
|||
virtual ~GlewOpenGL(); |
|||
void shutDown(); |
|||
void loop(); |
|||
FIBITMAP* readImage(const char* fileName); |
|||
GLuint createTexture(const char* fileName); |
|||
|
|||
|
|||
virtual void init() = 0; |
|||
virtual void render() = 0; |
|||
|
|||
protected: |
|||
int _width; |
|||
int _height; |
|||
const string _title; |
|||
GLFWwindow* _window; |
|||
|
|||
}; |
|||
|
|||
#endif /* GLEWOPENGL_H */ |
|||
|
@ -0,0 +1,29 @@ |
|||
/* |
|||
* To change this license header, choose License Headers in Project Properties. |
|||
* To change this template file, choose Tools | Templates |
|||
* and open the template in the editor. |
|||
*/ |
|||
|
|||
/* |
|||
* File: common.h |
|||
* Author: Blobt |
|||
* |
|||
* Created on October 5, 2019, 4:55 PM |
|||
*/ |
|||
|
|||
#ifndef COMMON_H |
|||
#define COMMON_H |
|||
|
|||
#ifdef __cplusplus |
|||
extern "C" { |
|||
#endif |
|||
|
|||
#define die(m) do { perror(m); exit(EXIT_FAILURE); } while(0) |
|||
|
|||
|
|||
#ifdef __cplusplus |
|||
} |
|||
#endif |
|||
|
|||
#endif /* COMMON_H */ |
|||
|
@ -0,0 +1,6 @@ |
|||
add_executable(example example.cc) |
|||
target_link_libraries(example ${GLFW_LIB}) |
|||
|
|||
add_executable(rect rect.cc) |
|||
target_link_libraries(rect ${GLFW_LIB}) |
|||
|
@ -0,0 +1,78 @@ |
|||
#include <stdio.h>
|
|||
#include <glew.h>
|
|||
#include "../common/base.h"
|
|||
#include "../common/CELLMath.hpp"
|
|||
#include "../common/GlewOpenGL.h"
|
|||
#include "tiny_obj_loader.h"
|
|||
|
|||
using namespace std; |
|||
using namespace CELL; |
|||
|
|||
class Viewer : public GlewOpenGL { |
|||
public: |
|||
|
|||
struct Vertex { |
|||
float x, y, z; |
|||
float u, v; |
|||
}; |
|||
|
|||
Viewer(int width, int height, const string& title) : GlewOpenGL(width, height, title) { |
|||
|
|||
} |
|||
|
|||
void init() { |
|||
_texture = createTexture("/home/blobt/Documents/dev/cpp/opengl2/models/wood.jpg"); |
|||
} |
|||
|
|||
void render() { |
|||
glMatrixMode(GL_PROJECTION); |
|||
glLoadIdentity(); |
|||
gluPerspective(100, double(_width) / double(_height), 0.1, 1000); |
|||
|
|||
Vertex vertex[] = { |
|||
{-1, -1.5, 0, 0, 0}, |
|||
{1, -1.5, 0, 1, 0}, |
|||
{1, 1.5, 0, 1, 1}, |
|||
{-1, 1.5, 0, 0, 1}, |
|||
}; |
|||
|
|||
glMatrixMode(GL_MODELVIEW); |
|||
glLoadIdentity(); |
|||
glTranslatef(0, 0, -2); |
|||
|
|||
|
|||
//开始深度测试,后面绘制的面就不会遮挡前面绘制的面
|
|||
glEnable(GL_DEPTH_TEST); |
|||
|
|||
//设置顶点
|
|||
glEnableClientState(GL_VERTEX_ARRAY); |
|||
glVertexPointer(3, GL_FLOAT, sizeof (Vertex), &vertex[0].x); |
|||
|
|||
//设置贴图
|
|||
glBindTexture(GL_TEXTURE_2D, _texture); |
|||
glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
|||
glTexCoordPointer(2, GL_FLOAT, sizeof (Vertex), &vertex[0].u); |
|||
|
|||
glDrawArrays(GL_QUADS, 0, 4); |
|||
} |
|||
|
|||
~Viewer() { |
|||
shutDown(); |
|||
glDeleteTextures(1, &_texture); |
|||
} |
|||
|
|||
private: |
|||
GLuint _texture; |
|||
}; |
|||
|
|||
int main(int argc, char** argv) { |
|||
|
|||
if (argc < 2) { |
|||
cerr << "Need input .obj" << endl; |
|||
} |
|||
|
|||
Viewer viewer(1024, 768, "Viewer"); |
|||
viewer.loop(); |
|||
|
|||
return 0; |
|||
} |
@ -0,0 +1,63 @@ |
|||
#include <GLFW/glfw3.h>
|
|||
#include <stdio.h>
|
|||
|
|||
int width = 800; |
|||
int hight = 800; |
|||
|
|||
void render() { |
|||
//把背景清成红色
|
|||
glClearColor(1, 0, 0, 1); |
|||
glClear(GL_COLOR_BUFFER_BIT); |
|||
|
|||
//设置viewpoint和正交投影台体
|
|||
glViewport(0, 0, width, hight); |
|||
glOrtho(0, width, hight, 0, -100, 100); |
|||
|
|||
|
|||
//设置操作投影矩阵
|
|||
glMatrixMode(GL_PROJECTION); |
|||
//把投影矩阵设为单位矩阵
|
|||
glLoadIdentity(); |
|||
|
|||
|
|||
glBegin(GL_LINES); |
|||
|
|||
glColor3f(1, 1, 1); |
|||
glVertex3f(10, 10, 10); |
|||
glVertex3f(400, 400, 100); |
|||
|
|||
glEnd(); |
|||
} |
|||
|
|||
int main(void) { |
|||
GLFWwindow* window; |
|||
|
|||
/* Initialize the library */ |
|||
if (!glfwInit()) |
|||
return -1; |
|||
|
|||
/* Create a windowed mode window and its OpenGL context */ |
|||
window = glfwCreateWindow(width, hight, "Hello World", NULL, NULL); |
|||
if (!window) { |
|||
glfwTerminate(); |
|||
return -1; |
|||
} |
|||
|
|||
|
|||
/* Make the window's context current */ |
|||
glfwMakeContextCurrent(window); |
|||
|
|||
/* Loop until the user closes the window */ |
|||
while (!glfwWindowShouldClose(window)) { |
|||
/* Render here */ |
|||
render(); |
|||
/* Swap front and back buffers */ |
|||
glfwSwapBuffers(window); |
|||
|
|||
/* Poll for and process events */ |
|||
glfwPollEvents(); |
|||
} |
|||
|
|||
glfwTerminate(); |
|||
return 0; |
|||
} |
@ -0,0 +1,72 @@ |
|||
#include <GLFW/glfw3.h>
|
|||
#include <stdio.h>
|
|||
#include "../common/CELLMath.hpp"
|
|||
|
|||
using namespace CELL; |
|||
|
|||
int width = 800; |
|||
int hight = 800; |
|||
|
|||
void render() { |
|||
//把背景清成红色
|
|||
glClearColor(1, 0, 0, 1); |
|||
glClear(GL_COLOR_BUFFER_BIT); |
|||
|
|||
//设置viewpoint和正交投影台体
|
|||
glViewport(0, 0, width, hight); |
|||
glOrtho(0, width, hight, 0, -100, 100); |
|||
|
|||
|
|||
//设置操作投影矩阵
|
|||
glMatrixMode(GL_PROJECTION); |
|||
//把投影矩阵设为单位矩阵
|
|||
glLoadIdentity(); |
|||
|
|||
float3 v[] = { |
|||
{10, 10, 0}, |
|||
{410, 10, 0}, |
|||
{10, 410, 0}, |
|||
{410, 410, 0} |
|||
}; |
|||
|
|||
|
|||
glColor3f(0, 0, 1); |
|||
|
|||
//启动定点数组模式
|
|||
glEnableClientState(GL_VERTEX_ARRAY); |
|||
glVertexPointer(3, GL_FLOAT, sizeof (float3), v); |
|||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
|||
} |
|||
|
|||
int main(void) { |
|||
GLFWwindow* window; |
|||
|
|||
/* Initialize the library */ |
|||
if (!glfwInit()) |
|||
return -1; |
|||
|
|||
/* Create a windowed mode window and its OpenGL context */ |
|||
window = glfwCreateWindow(width, hight, "Hello World", NULL, NULL); |
|||
if (!window) { |
|||
glfwTerminate(); |
|||
return -1; |
|||
} |
|||
|
|||
|
|||
/* Make the window's context current */ |
|||
glfwMakeContextCurrent(window); |
|||
|
|||
/* Loop until the user closes the window */ |
|||
while (!glfwWindowShouldClose(window)) { |
|||
/* Render here */ |
|||
render(); |
|||
/* Swap front and back buffers */ |
|||
glfwSwapBuffers(window); |
|||
|
|||
/* Poll for and process events */ |
|||
glfwPollEvents(); |
|||
} |
|||
|
|||
glfwTerminate(); |
|||
return 0; |
|||
} |
@ -0,0 +1,8 @@ |
|||
add_executable(objviewer objviewer.cc) |
|||
target_link_libraries(objviewer ${GLFW_LIB}) |
|||
|
|||
add_executable(gltfviewer gltfviewer.cc) |
|||
target_link_libraries(gltfviewer ${GLFW_LIB}) |
|||
|
|||
add_executable(viewer viewer.cc trackball.cc ${COM_SRC}) |
|||
target_link_libraries(viewer ${GLFW_LIB}) |
@ -0,0 +1,45 @@ |
|||
#include <GLFW/glfw3.h>
|
|||
#include <stdio.h>
|
|||
#include "../common/CELLMath.hpp"
|
|||
|
|||
using namespace CELL; |
|||
|
|||
int width = 800; |
|||
int hight = 800; |
|||
|
|||
void render() { |
|||
|
|||
} |
|||
|
|||
int main(void) { |
|||
GLFWwindow* window; |
|||
|
|||
/* Initialize the library */ |
|||
if (!glfwInit()) |
|||
return -1; |
|||
|
|||
/* Create a windowed mode window and its OpenGL context */ |
|||
window = glfwCreateWindow(width, hight, "Hello World", NULL, NULL); |
|||
if (!window) { |
|||
glfwTerminate(); |
|||
return -1; |
|||
} |
|||
|
|||
|
|||
/* Make the window's context current */ |
|||
glfwMakeContextCurrent(window); |
|||
|
|||
/* Loop until the user closes the window */ |
|||
while (!glfwWindowShouldClose(window)) { |
|||
/* Render here */ |
|||
render(); |
|||
/* Swap front and back buffers */ |
|||
glfwSwapBuffers(window); |
|||
|
|||
/* Poll for and process events */ |
|||
glfwPollEvents(); |
|||
} |
|||
|
|||
glfwTerminate(); |
|||
return 0; |
|||
} |
@ -0,0 +1,104 @@ |
|||
#include <glew.h>
|
|||
#include <GLFW/glfw3.h>
|
|||
#include <stdio.h>
|
|||
#include "../common/base.h"
|
|||
#include "../common/CELLMath.hpp"
|
|||
#include "tiny_obj_loader.h"
|
|||
|
|||
using namespace CELL; |
|||
|
|||
int width = 800; |
|||
int height = 800; |
|||
|
|||
struct Vertex { |
|||
unsigned char r, g, b, a; |
|||
float x, y, z; |
|||
}; |
|||
|
|||
void render() { |
|||
glMatrixMode(GL_PROJECTION); |
|||
glLoadIdentity(); |
|||
gluPerspective(100, double(width) / double(height), 0.1, 1000); |
|||
|
|||
Vertex vertex[] = { |
|||
{ 255, 0, 0, 255, -1.0f, -1.0f, 1.0f}, |
|||
{ 255, 0, 0, 255, 1.0f, -1.0f, 1.0f}, |
|||
{ 255, 0, 0, 255, 1.0f, 1.0f, 1.0f}, |
|||
{ 255, 0, 0, 255, -1.0f, 1.0f, 1.0f}, |
|||
|
|||
{ 0, 255, 0, 255, -1.0f, -1.0f, -1.0f}, |
|||
{ 0, 255, 0, 255, -1.0f, 1.0f, -1.0f}, |
|||
{ 0, 255, 0, 255, 1.0f, 1.0f, -1.0f}, |
|||
{ 0, 255, 0, 255, 1.0f, -1.0f, -1.0f}, |
|||
|
|||
{ 0, 0, 255, 255, -1.0f, 1.0f, -1.0f}, |
|||
{ 0, 0, 255, 255, -1.0f, 1.0f, 1.0f}, |
|||
{ 0, 0, 255, 255, 1.0f, 1.0f, 1.0f}, |
|||
{ 0, 0, 255, 255, 1.0f, 1.0f, -1.0f}, |
|||
|
|||
{ 0, 255, 255, 255, -1.0f, -1.0f, -1.0f}, |
|||
{ 0, 255, 255, 255, 1.0f, -1.0f, -1.0f}, |
|||
{ 0, 255, 255, 255, 1.0f, -1.0f, 1.0f}, |
|||
{ 0, 255, 255, 255, -1.0f, -1.0f, 1.0f}, |
|||
|
|||
{ 255, 0, 255, 255, 1.0f, -1.0f, -1.0f}, |
|||
{ 255, 0, 255, 255, 1.0f, 1.0f, -1.0f}, |
|||
{ 255, 0, 255, 255, 1.0f, 1.0f, 1.0f}, |
|||
{ 255, 0, 255, 255, 1.0f, -1.0f, 1.0f}, |
|||
|
|||
{ 255, 255, 255, 255, -1.0f, -1.0f, -1.0f}, |
|||
{ 255, 255, 255, 255, -1.0f, -1.0f, 1.0f}, |
|||
{ 255, 255, 255, 255, -1.0f, 1.0f, 1.0f}, |
|||
{ 255, 255, 255, 255, -1.0f, 1.0f, -1.0f} |
|||
}; |
|||
|
|||
|
|||
glMatrixMode(GL_MODELVIEW); |
|||
glLoadIdentity(); |
|||
glTranslatef(2.5, 2.5, -6); |
|||
glScalef(1.0, 2.0, 2.0); |
|||
|
|||
|
|||
//开始深度测试,后面绘制的面就不会遮挡前面绘制的面
|
|||
glEnable(GL_DEPTH_TEST); |
|||
|
|||
glEnableClientState(GL_VERTEX_ARRAY); |
|||
glEnableClientState(GL_COLOR_ARRAY); |
|||
glVertexPointer(3, GL_FLOAT, sizeof (Vertex), &vertex[0].x); |
|||
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof (Vertex), &vertex[0].r); |
|||
|
|||
glDrawArrays(GL_QUADS, 0, 24); |
|||
} |
|||
|
|||
int main(void) { |
|||
GLFWwindow* window; |
|||
|
|||
/* Initialize the library */ |
|||
if (!glfwInit()) |
|||
return -1; |
|||
|
|||
/* Create a windowed mode window and its OpenGL context */ |
|||
window = glfwCreateWindow(width, height, "Hello World", NULL, NULL); |
|||
if (!window) { |
|||
glfwTerminate(); |
|||
return -1; |
|||
} |
|||
|
|||
|
|||
/* Make the window's context current */ |
|||
glfwMakeContextCurrent(window); |
|||
|
|||
/* Loop until the user closes the window */ |
|||
while (!glfwWindowShouldClose(window)) { |
|||
/* Render here */ |
|||
render(); |
|||
/* Swap front and back buffers */ |
|||
glfwSwapBuffers(window); |
|||
|
|||
/* Poll for and process events */ |
|||
glfwPollEvents(); |
|||
} |
|||
|
|||
glfwTerminate(); |
|||
return 0; |
|||
} |
@ -0,0 +1,292 @@ |
|||
/*
|
|||
* (c) Copyright 1993, 1994, Silicon Graphics, Inc. |
|||
* ALL RIGHTS RESERVED |
|||
* Permission to use, copy, modify, and distribute this software for |
|||
* any purpose and without fee is hereby granted, provided that the above |
|||
* copyright notice appear in all copies and that both the copyright notice |
|||
* and this permission notice appear in supporting documentation, and that |
|||
* the name of Silicon Graphics, Inc. not be used in advertising |
|||
* or publicity pertaining to distribution of the software without specific, |
|||
* written prior permission. |
|||
* |
|||
* THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" |
|||
* AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, |
|||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR |
|||
* FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON |
|||
* GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, |
|||
* SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY |
|||
* KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, |
|||
* LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF |
|||
* THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN |
|||
* ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON |
|||
* ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE |
|||
* POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. |
|||
* |
|||
* US Government Users Restricted Rights |
|||
* Use, duplication, or disclosure by the Government is subject to |
|||
* restrictions set forth in FAR 52.227.19(c)(2) or subparagraph |
|||
* (c)(1)(ii) of the Rights in Technical Data and Computer Software |
|||
* clause at DFARS 252.227-7013 and/or in similar or successor |
|||
* clauses in the FAR or the DOD or NASA FAR Supplement. |
|||
* Unpublished-- rights reserved under the copyright laws of the |
|||
* United States. Contractor/manufacturer is Silicon Graphics, |
|||
* Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. |
|||
* |
|||
* OpenGL(TM) is a trademark of Silicon Graphics, Inc. |
|||
*/ |
|||
/*
|
|||
* Trackball code: |
|||
* |
|||
* Implementation of a virtual trackball. |
|||
* Implemented by Gavin Bell, lots of ideas from Thant Tessman and |
|||
* the August '88 issue of Siggraph's "Computer Graphics," pp. 121-129. |
|||
* |
|||
* Vector manip code: |
|||
* |
|||
* Original code from: |
|||
* David M. Ciemiewicz, Mark Grossman, Henry Moreton, and Paul Haeberli |
|||
* |
|||
* Much mucking with by: |
|||
* Gavin Bell |
|||
*/ |
|||
#include <math.h>
|
|||
#include "trackball.h"
|
|||
|
|||
/*
|
|||
* This size should really be based on the distance from the center of |
|||
* rotation to the point on the object underneath the mouse. That |
|||
* point would then track the mouse as closely as possible. This is a |
|||
* simple example, though, so that is left as an Exercise for the |
|||
* Programmer. |
|||
*/ |
|||
#define TRACKBALLSIZE (0.8)
|
|||
|
|||
/*
|
|||
* Local function prototypes (not defined in trackball.h) |
|||
*/ |
|||
static float tb_project_to_sphere(float, float, float); |
|||
static void normalize_quat(float[4]); |
|||
|
|||
static void vzero(float *v) { |
|||
v[0] = 0.0; |
|||
v[1] = 0.0; |
|||
v[2] = 0.0; |
|||
} |
|||
|
|||
static void vset(float *v, float x, float y, float z) { |
|||
v[0] = x; |
|||
v[1] = y; |
|||
v[2] = z; |
|||
} |
|||
|
|||
static void vsub(const float *src1, const float *src2, float *dst) { |
|||
dst[0] = src1[0] - src2[0]; |
|||
dst[1] = src1[1] - src2[1]; |
|||
dst[2] = src1[2] - src2[2]; |
|||
} |
|||
|
|||
static void vcopy(const float *v1, float *v2) { |
|||
register int i; |
|||
for (i = 0; i < 3; i++) |
|||
v2[i] = v1[i]; |
|||
} |
|||
|
|||
static void vcross(const float *v1, const float *v2, float *cross) { |
|||
float temp[3]; |
|||
|
|||
temp[0] = (v1[1] * v2[2]) - (v1[2] * v2[1]); |
|||
temp[1] = (v1[2] * v2[0]) - (v1[0] * v2[2]); |
|||
temp[2] = (v1[0] * v2[1]) - (v1[1] * v2[0]); |
|||
vcopy(temp, cross); |
|||
} |
|||
|
|||
static float vlength(const float *v) { |
|||
return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); |
|||
} |
|||
|
|||
static void vscale(float *v, float div) { |
|||
v[0] *= div; |
|||
v[1] *= div; |
|||
v[2] *= div; |
|||
} |
|||
|
|||
static void vnormal(float *v) { vscale(v, 1.0 / vlength(v)); } |
|||
|
|||
static float vdot(const float *v1, const float *v2) { |
|||
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]; |
|||
} |
|||
|
|||
static void vadd(const float *src1, const float *src2, float *dst) { |
|||
dst[0] = src1[0] + src2[0]; |
|||
dst[1] = src1[1] + src2[1]; |
|||
dst[2] = src1[2] + src2[2]; |
|||
} |
|||
|
|||
/*
|
|||
* Ok, simulate a track-ball. Project the points onto the virtual |
|||
* trackball, then figure out the axis of rotation, which is the cross |
|||
* product of P1 P2 and O P1 (O is the center of the ball, 0,0,0) |
|||
* Note: This is a deformed trackball-- is a trackball in the center, |
|||
* but is deformed into a hyperbolic sheet of rotation away from the |
|||
* center. This particular function was chosen after trying out |
|||
* several variations. |
|||
* |
|||
* It is assumed that the arguments to this routine are in the range |
|||
* (-1.0 ... 1.0) |
|||
*/ |
|||
void trackball(float q[4], float p1x, float p1y, float p2x, float p2y) { |
|||
float a[3]; /* Axis of rotation */ |
|||
float phi; /* how much to rotate about axis */ |
|||
float p1[3], p2[3], d[3]; |
|||
float t; |
|||
|
|||
if (p1x == p2x && p1y == p2y) { |
|||
/* Zero rotation */ |
|||
vzero(q); |
|||
q[3] = 1.0; |
|||
return; |
|||
} |
|||
|
|||
/*
|
|||
* First, figure out z-coordinates for projection of P1 and P2 to |
|||
* deformed sphere |
|||
*/ |
|||
vset(p1, p1x, p1y, tb_project_to_sphere(TRACKBALLSIZE, p1x, p1y)); |
|||
vset(p2, p2x, p2y, tb_project_to_sphere(TRACKBALLSIZE, p2x, p2y)); |
|||
|
|||
/*
|
|||
* Now, we want the cross product of P1 and P2 |
|||
*/ |
|||
vcross(p2, p1, a); |
|||
|
|||
/*
|
|||
* Figure out how much to rotate around that axis. |
|||
*/ |
|||
vsub(p1, p2, d); |
|||
t = vlength(d) / (2.0 * TRACKBALLSIZE); |
|||
|
|||
/*
|
|||
* Avoid problems with out-of-control values... |
|||
*/ |
|||
if (t > 1.0) |
|||
t = 1.0; |
|||
if (t < -1.0) |
|||
t = -1.0; |
|||
phi = 2.0 * asin(t); |
|||
|
|||
axis_to_quat(a, phi, q); |
|||
} |
|||
|
|||
/*
|
|||
* Given an axis and angle, compute quaternion. |
|||
*/ |
|||
void axis_to_quat(float a[3], float phi, float q[4]) { |
|||
vnormal(a); |
|||
vcopy(a, q); |
|||
vscale(q, sin(phi / 2.0)); |
|||
q[3] = cos(phi / 2.0); |
|||
} |
|||
|
|||
/*
|
|||
* Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet |
|||
* if we are away from the center of the sphere. |
|||
*/ |
|||
static float tb_project_to_sphere(float r, float x, float y) { |
|||
float d, t, z; |
|||
|
|||
d = sqrt(x * x + y * y); |
|||
if (d < r * 0.70710678118654752440) { /* Inside sphere */ |
|||
z = sqrt(r * r - d * d); |
|||
} else { /* On hyperbola */ |
|||
t = r / 1.41421356237309504880; |
|||
z = t * t / d; |
|||
} |
|||
return z; |
|||
} |
|||
|
|||
/*
|
|||
* Given two rotations, e1 and e2, expressed as quaternion rotations, |
|||
* figure out the equivalent single rotation and stuff it into dest. |
|||
* |
|||
* This routine also normalizes the result every RENORMCOUNT times it is |
|||
* called, to keep error from creeping in. |
|||
* |
|||
* NOTE: This routine is written so that q1 or q2 may be the same |
|||
* as dest (or each other). |
|||
*/ |
|||
|
|||
#define RENORMCOUNT 97
|
|||
|
|||
void add_quats(float q1[4], float q2[4], float dest[4]) { |
|||
static int count = 0; |
|||
float t1[4], t2[4], t3[4]; |
|||
float tf[4]; |
|||
|
|||
vcopy(q1, t1); |
|||
vscale(t1, q2[3]); |
|||
|
|||
vcopy(q2, t2); |
|||
vscale(t2, q1[3]); |
|||
|
|||
vcross(q2, q1, t3); |
|||
vadd(t1, t2, tf); |
|||
vadd(t3, tf, tf); |
|||
tf[3] = q1[3] * q2[3] - vdot(q1, q2); |
|||
|
|||
dest[0] = tf[0]; |
|||
dest[1] = tf[1]; |
|||
dest[2] = tf[2]; |
|||
dest[3] = tf[3]; |
|||
|
|||
if (++count > RENORMCOUNT) { |
|||
count = 0; |
|||
normalize_quat(dest); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* Quaternions always obey: a^2 + b^2 + c^2 + d^2 = 1.0 |
|||
* If they don't add up to 1.0, dividing by their magnitued will |
|||
* renormalize them. |
|||
* |
|||
* Note: See the following for more information on quaternions: |
|||
* |
|||
* - Shoemake, K., Animating rotation with quaternion curves, Computer |
|||
* Graphics 19, No 3 (Proc. SIGGRAPH'85), 245-254, 1985. |
|||
* - Pletinckx, D., Quaternion calculus as a basic tool in computer |
|||
* graphics, The Visual Computer 5, 2-13, 1989. |
|||
*/ |
|||
static void normalize_quat(float q[4]) { |
|||
int i; |
|||
float mag; |
|||
|
|||
mag = (q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]); |
|||
for (i = 0; i < 4; i++) |
|||
q[i] /= mag; |
|||
} |
|||
|
|||
/*
|
|||
* Build a rotation matrix, given a quaternion rotation. |
|||
* |
|||
*/ |
|||
void build_rotmatrix(float m[4][4], const float q[4]) { |
|||
m[0][0] = 1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2]); |
|||
m[0][1] = 2.0 * (q[0] * q[1] - q[2] * q[3]); |
|||
m[0][2] = 2.0 * (q[2] * q[0] + q[1] * q[3]); |
|||
m[0][3] = 0.0; |
|||
|
|||
m[1][0] = 2.0 * (q[0] * q[1] + q[2] * q[3]); |
|||
m[1][1] = 1.0 - 2.0 * (q[2] * q[2] + q[0] * q[0]); |
|||
m[1][2] = 2.0 * (q[1] * q[2] - q[0] * q[3]); |
|||
m[1][3] = 0.0; |
|||
|
|||
m[2][0] = 2.0 * (q[2] * q[0] - q[1] * q[3]); |
|||
m[2][1] = 2.0 * (q[1] * q[2] + q[0] * q[3]); |
|||
m[2][2] = 1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0]); |
|||
m[2][3] = 0.0; |
|||
|
|||
m[3][0] = 0.0; |
|||
m[3][1] = 0.0; |
|||
m[3][2] = 0.0; |
|||
m[3][3] = 1.0; |
|||
} |
@ -0,0 +1,75 @@ |
|||
/* |
|||
* (c) Copyright 1993, 1994, Silicon Graphics, Inc. |
|||
* ALL RIGHTS RESERVED |
|||
* Permission to use, copy, modify, and distribute this software for |
|||
* any purpose and without fee is hereby granted, provided that the above |
|||
* copyright notice appear in all copies and that both the copyright notice |
|||
* and this permission notice appear in supporting documentation, and that |
|||
* the name of Silicon Graphics, Inc. not be used in advertising |
|||
* or publicity pertaining to distribution of the software without specific, |
|||
* written prior permission. |
|||
* |
|||
* THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" |
|||
* AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, |
|||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR |
|||
* FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON |
|||
* GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, |
|||
* SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY |
|||
* KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, |
|||
* LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF |
|||
* THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN |
|||
* ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON |
|||
* ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE |
|||
* POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. |
|||
* |
|||
* US Government Users Restricted Rights |
|||
* Use, duplication, or disclosure by the Government is subject to |
|||
* restrictions set forth in FAR 52.227.19(c)(2) or subparagraph |
|||
* (c)(1)(ii) of the Rights in Technical Data and Computer Software |
|||
* clause at DFARS 252.227-7013 and/or in similar or successor |
|||
* clauses in the FAR or the DOD or NASA FAR Supplement. |
|||
* Unpublished-- rights reserved under the copyright laws of the |
|||
* United States. Contractor/manufacturer is Silicon Graphics, |
|||
* Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. |
|||
* |
|||
* OpenGL(TM) is a trademark of Silicon Graphics, Inc. |
|||
*/ |
|||
/* |
|||
* trackball.h |
|||
* A virtual trackball implementation |
|||
* Written by Gavin Bell for Silicon Graphics, November 1988. |
|||
*/ |
|||
|
|||
/* |
|||
* Pass the x and y coordinates of the last and current positions of |
|||
* the mouse, scaled so they are from (-1.0 ... 1.0). |
|||
* |
|||
* The resulting rotation is returned as a quaternion rotation in the |
|||
* first paramater. |
|||
*/ |
|||
void trackball(float q[4], float p1x, float p1y, float p2x, float p2y); |
|||
|
|||
void negate_quat(float *q, float *qn); |
|||
|
|||
/* |
|||
* Given two quaternions, add them together to get a third quaternion. |
|||
* Adding quaternions to get a compound rotation is analagous to adding |
|||
* translations to get a compound translation. When incrementally |
|||
* adding rotations, the first argument here should be the new |
|||
* rotation, the second and third the total rotation (which will be |
|||
* over-written with the resulting new total rotation). |
|||
*/ |
|||
void add_quats(float *q1, float *q2, float *dest); |
|||
|
|||
/* |
|||
* A useful function, builds a rotation matrix in Matrix based on |
|||
* given quaternion. |
|||
*/ |
|||
void build_rotmatrix(float m[4][4], const float q[4]); |
|||
|
|||
/* |
|||
* This function computes a quaternion based on an axis (defined by |
|||
* the given vector) and an angle about which to rotate. The angle is |
|||
* expressed in radians. The result is put into the third argument. |
|||
*/ |
|||
void axis_to_quat(float a[3], float phi, float q[4]); |
@ -0,0 +1,77 @@ |
|||
#include <stdio.h>
|
|||
#include <glew.h>
|
|||
#include "../common/base.h"
|
|||
#include "../common/CELLMath.hpp"
|
|||
#include "../common/GlewOpenGL.h"
|
|||
#include "tiny_obj_loader.h"
|
|||
|
|||
using namespace std; |
|||
using namespace CELL; |
|||
|
|||
class Viewer : public GlewOpenGL { |
|||
public: |
|||
|
|||
struct Vertex { |
|||
float x, y, z; |
|||
float u, v; |
|||
}; |
|||
|
|||
Viewer(int width, int height, const string& title) : GlewOpenGL(width, height, title) { |
|||
|
|||
} |
|||
|
|||
void init() { |
|||
_texture = createTexture("/home/blobt/Documents/dev/cpp/opengl2/models/chair/cloth.jpg"); |
|||
} |
|||
|
|||
void render() { |
|||
glMatrixMode(GL_PROJECTION); |
|||
glLoadIdentity(); |
|||
gluPerspective(100, double(_width) / double(_height), 0.1, 1000); |
|||
|
|||
Vertex vertex[] = { |
|||
{-1, -1.5, 0, 0, 0}, |
|||
{1, -1.5, 0, 1, 0}, |
|||
{1, 1.5, 0, 1, 1}, |
|||
{-1, 1.5, 0, 0, 1}, |
|||
}; |
|||
|
|||
glMatrixMode(GL_MODELVIEW); |
|||
glLoadIdentity(); |
|||
glTranslatef(0, 0, -2); |
|||
|
|||
|
|||
//开始深度测试,后面绘制的面就不会遮挡前面绘制的面
|
|||
glEnable(GL_DEPTH_TEST); |
|||
|
|||
//设置顶点
|
|||
glEnableClientState(GL_VERTEX_ARRAY); |
|||
glVertexPointer(3, GL_FLOAT, sizeof (Vertex), &vertex[0].x); |
|||
|
|||
//设置贴图
|
|||
glBindTexture(GL_TEXTURE_2D, _texture); |
|||
glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
|||
glTexCoordPointer(2, GL_FLOAT, sizeof (Vertex), &vertex[0].u); |
|||
|
|||
glDrawArrays(GL_QUADS, 0, 4); |
|||
} |
|||
|
|||
~Viewer() { |
|||
|
|||
} |
|||
|
|||
private: |
|||
GLuint _texture; |
|||
}; |
|||
|
|||
int main(int argc, char** argv) { |
|||
|
|||
if (argc < 2) { |
|||
|
|||
} |
|||
|
|||
Viewer viewer(1024, 768, "Viewer"); |
|||
viewer.loop(); |
|||
|
|||
return 0; |
|||
} |
@ -0,0 +1,423 @@ |
|||
#include <stdio.h>
|
|||
#include <glew.h>
|
|||
#include <iostream>
|
|||
#include <libgen.h>
|
|||
#include "../common/base.h"
|
|||
#include "../common/CELLMath.hpp"
|
|||
#include "../common/GlewOpenGL.h"
|
|||
|
|||
#define TINYOBJLOADER_IMPLEMENTATION
|
|||
#include "tiny_obj_loader.h"
|
|||
#include "trackball.h"
|
|||
|
|||
using namespace std; |
|||
using namespace CELL; |
|||
|
|||
class Viewer : public GlewOpenGL { |
|||
public: |
|||
|
|||
/**
|
|||
* 要绘画的对象 |
|||
*/ |
|||
typedef struct { |
|||
GLuint vb_id; //vertex buffer id
|
|||
int numTriangles; |
|||
size_t material_id; |
|||
} DrawObject; |
|||
|
|||
Viewer(int width, int height, const string& title) : GlewOpenGL(width, height, title) { |
|||
|
|||
} |
|||
|
|||
void init() { |
|||
trackball(curr_quat, 0, 0, 0, 0); |
|||
|
|||
eye[0] = 0.0f; |
|||
eye[1] = 0.0f; |
|||
eye[2] = 3.0f; |
|||
|
|||
lookat[0] = 0.0f; |
|||
lookat[1] = 0.0f; |
|||
lookat[2] = 0.0f; |
|||
|
|||
up[0] = 0.0f; |
|||
up[1] = 1.0f; |
|||
up[2] = 0.0f; |
|||
|
|||
maxExtent = 0.5f * (bmax[0] - bmin[0]); |
|||
if (maxExtent < 0.5f * (bmax[1] - bmin[1])) { |
|||
maxExtent = 0.5f * (bmax[1] - bmin[1]); |
|||
} |
|||
if (maxExtent < 0.5f * (bmax[2] - bmin[2])) { |
|||
maxExtent = 0.5f * (bmax[2] - bmin[2]); |
|||
} |
|||
|
|||
loadObj(); |
|||
} |
|||
|
|||
void render() { |
|||
glClearColor(0.1f, 0.2f, 0.3f, 1.0f); |
|||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
|||
|
|||
glEnable(GL_DEPTH_TEST); |
|||
glEnable(GL_TEXTURE_2D); |
|||
|
|||
// camera & rotate
|
|||
glMatrixMode(GL_MODELVIEW); |
|||
glLoadIdentity(); |
|||
GLfloat mat[4][4]; |
|||
gluLookAt(eye[0], eye[1], eye[2], lookat[0], lookat[1], lookat[2], up[0], |
|||
up[1], up[2]); |
|||
build_rotmatrix(mat, curr_quat); |
|||
glMultMatrixf(&mat[0][0]); |
|||
|
|||
// Fit to -1, 1
|
|||
glScalef(1.0f / maxExtent, 1.0f / maxExtent, 1.0f / maxExtent); |
|||
|
|||
// Centerize object.
|
|||
glTranslatef(-0.5 * (bmax[0] + bmin[0]), -0.5 * (bmax[1] + bmin[1]), |
|||
-0.5 * (bmax[2] + bmin[2])); |
|||
|
|||
Draw(drawObjects, materials, textures); |
|||
} |
|||
|
|||
bool loadObj() { |
|||
string warn; |
|||
string err; |
|||
|
|||
|
|||
char* filename = strdup("/home/blobt/Documents/dev/cpp/opengl2/models/chair/chair2.obj"); |
|||
//char* filename = strdup("/home/blobt/Documents/dev/cpp/tinyobjloader/models/cube.obj");
|
|||
|
|||
char* obj = strdup(filename); |
|||
char* basepath = dirname(filename); |
|||
|
|||
texPath = basepath; |
|||
|
|||
|
|||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, obj, basepath, true); |
|||
|
|||
free(filename); |
|||
free(obj); |
|||
|
|||
if (!warn.empty()) { |
|||
cout << "WARN: " << warn << endl; |
|||
} |
|||
|
|||
if (!err.empty()) { |
|||
cerr << "ERR: " << err << endl; |
|||
} |
|||
|
|||
if (!ret) { |
|||
die("Failed to parse .obj.\n"); |
|||
} |
|||
|
|||
convertTo(); |
|||
} |
|||
|
|||
void convertTo() { |
|||
printf("# of vertices = %d\n", (int) (attrib.vertices.size()) / 3); |
|||
printf("# of normals = %d\n", (int) (attrib.normals.size()) / 3); |
|||
printf("# of texcoords = %d\n", (int) (attrib.texcoords.size()) / 2); |
|||
printf("# of materials = %d\n", (int) materials.size()); |
|||
printf("# of shapes = %d\n", (int) shapes.size()); |
|||
|
|||
// 添加默认材质
|
|||
materials.push_back(tinyobj::material_t()); |
|||
|
|||
for (size_t i = 0; i < materials.size(); i++) { |
|||
printf("material[%d].diffuse_texname = %s\n", int(i), |
|||
materials[i].diffuse_texname.c_str()); |
|||
} |
|||
|
|||
// 加载 漫反射 纹理
|
|||
for (size_t m = 0; m < materials.size(); m++) { |
|||
tinyobj::material_t* mp = &materials[m]; |
|||
|
|||
if (mp->diffuse_texname.length() > 0) { |
|||
// 只加载没有加载的
|
|||
if (textures.find(mp->diffuse_texname) == textures.end()) { |
|||
string fullPath; |
|||
fullPath.append(texPath); |
|||
fullPath.append("/"); |
|||
fullPath.append(mp->diffuse_texname); |
|||
|
|||
GLuint texture_id = createTexture(fullPath.c_str()); |
|||
textures.insert(make_pair(mp->diffuse_texname, texture_id)); |
|||
} |
|||
} |
|||
} |
|||
|
|||
bmin[0] = bmin[1] = bmin[2] = std::numeric_limits<float>::max(); |
|||
bmax[0] = bmax[1] = bmax[2] = -std::numeric_limits<float>::max(); |
|||
|
|||
for (size_t s = 0; s < shapes.size(); s++) { |
|||
DrawObject o; |
|||
vector<float> buffer; |
|||
|
|||
// TODO 检查光滑组 和 计算光滑组法向
|
|||
|
|||
for (size_t f = 0; f < shapes[s].mesh.indices.size() / 3; f++) { |
|||
tinyobj::index_t idx0 = shapes[s].mesh.indices[3 * f + 0]; |
|||
tinyobj::index_t idx1 = shapes[s].mesh.indices[3 * f + 1]; |
|||
tinyobj::index_t idx2 = shapes[s].mesh.indices[3 * f + 2]; |
|||
|
|||
int current_material_id = shapes[s].mesh.material_ids[f]; |
|||
|
|||
//如果材质id错误,则使用默认材质id
|
|||
if (current_material_id < 0 || current_material_id >= static_cast<int> (materials.size())) { |
|||
current_material_id = materials.size() - 1; |
|||
} |
|||
|
|||
float diffuse[3]; |
|||
for (size_t i = 0; i < 3; i++) { |
|||
diffuse[i] = materials[current_material_id].diffuse[i]; |
|||
} |
|||
|
|||
//处理贴图坐标
|
|||
float tc[3][2]; |
|||
if (attrib.texcoords.size() <= 0 || idx0.texcoord_index < 0 || idx1.texcoord_index < 0 || idx2.texcoord_index < 0) { |
|||
tc[0][0] = 0.0f; |
|||
tc[0][1] = 0.0f; |
|||
tc[1][0] = 0.0f; |
|||
tc[1][1] = 0.0f; |
|||
tc[2][0] = 0.0f; |
|||
tc[2][1] = 0.0f; |
|||
} else { |
|||
assert(attrib.texcoords.size() > size_t(2 * idx0.texcoord_index + 1)); |
|||
assert(attrib.texcoords.size() > size_t(2 * idx1.texcoord_index + 1)); |
|||
assert(attrib.texcoords.size() > size_t(2 * idx2.texcoord_index + 1)); |
|||
|
|||
// 翻转 Y
|
|||
tc[0][0] = attrib.texcoords[2 * idx0.texcoord_index]; |
|||
tc[0][1] = 1.0f - attrib.texcoords[2 * idx0.texcoord_index + 1]; |
|||
tc[1][0] = attrib.texcoords[2 * idx1.texcoord_index]; |
|||
tc[1][1] = 1.0f - attrib.texcoords[2 * idx1.texcoord_index + 1]; |
|||
tc[2][0] = attrib.texcoords[2 * idx2.texcoord_index]; |
|||
tc[2][1] = 1.0f - attrib.texcoords[2 * idx2.texcoord_index + 1]; |
|||
} |
|||
|
|||
//处理顶点坐标
|
|||
float v[3][3]; |
|||
for (int k = 0; k < 3; k++) { |
|||
int f0 = idx0.vertex_index; |
|||
int f1 = idx1.vertex_index; |
|||
int f2 = idx2.vertex_index; |
|||
|
|||
assert(f0 >= 0); |
|||
assert(f1 >= 0); |
|||
assert(f2 >= 0); |
|||
|
|||
v[0][k] = attrib.vertices[3 * f0 + k]; |
|||
v[1][k] = attrib.vertices[3 * f1 + k]; |
|||
v[2][k] = attrib.vertices[3 * f2 + k]; |
|||
|
|||
bmin[k] = std::min(v[0][k], bmin[k]); |
|||
bmin[k] = std::min(v[1][k], bmin[k]); |
|||
bmin[k] = std::min(v[2][k], bmin[k]); |
|||
bmax[k] = std::max(v[0][k], bmax[k]); |
|||
bmax[k] = std::max(v[1][k], bmax[k]); |
|||
bmax[k] = std::max(v[2][k], bmax[k]); |
|||
} |
|||
|
|||
//处理法向
|
|||
float n[3][3]; |
|||
int nf0 = idx0.normal_index; |
|||
int nf1 = idx1.normal_index; |
|||
int nf2 = idx2.normal_index; |
|||
if (attrib.normals.size() <= 0 || (nf0 < 0) || (nf1 < 0) || (nf2 < 0)) { |
|||
calcNormal(n[0], v[0], v[1], v[2]); |
|||
n[1][0] = n[0][0]; |
|||
n[1][1] = n[0][1]; |
|||
n[1][2] = n[0][2]; |
|||
n[2][0] = n[0][0]; |
|||
n[2][1] = n[0][1]; |
|||
n[2][2] = n[0][2]; |
|||
} else { |
|||
for (int k = 0; k < 3; k++) { |
|||
assert(size_t(3 * nf0 + k) < attrib.normals.size()); |
|||
assert(size_t(3 * nf1 + k) < attrib.normals.size()); |
|||
assert(size_t(3 * nf2 + k) < attrib.normals.size()); |
|||
n[0][k] = attrib.normals[3 * nf0 + k]; |
|||
n[1][k] = attrib.normals[3 * nf1 + k]; |
|||
n[2][k] = attrib.normals[3 * nf2 + k]; |
|||
} |
|||
} |
|||
|
|||
for (int k = 0; k < 3; k++) { |
|||
buffer.push_back(v[k][0]); |
|||
buffer.push_back(v[k][1]); |
|||
buffer.push_back(v[k][2]); |
|||
buffer.push_back(n[k][0]); |
|||
buffer.push_back(n[k][1]); |
|||
buffer.push_back(n[k][2]); |
|||
|
|||
// Combine normal and diffuse to get color.
|
|||
float normal_factor = 0.2; |
|||
float diffuse_factor = 1 - normal_factor; |
|||
float c[3] = {n[k][0] * normal_factor + diffuse[0] * diffuse_factor, |
|||
n[k][1] * normal_factor + diffuse[1] * diffuse_factor, |
|||
n[k][2] * normal_factor + diffuse[2] * diffuse_factor}; |
|||
float len2 = c[0] * c[0] + c[1] * c[1] + c[2] * c[2]; |
|||
if (len2 > 0.0f) { |
|||
float len = sqrtf(len2); |
|||
|
|||
c[0] /= len; |
|||
c[1] /= len; |
|||
c[2] /= len; |
|||
} |
|||
buffer.push_back(c[0] * 0.5 + 0.5); |
|||
buffer.push_back(c[1] * 0.5 + 0.5); |
|||
buffer.push_back(c[2] * 0.5 + 0.5); |
|||
|
|||
buffer.push_back(tc[k][0]); |
|||
buffer.push_back(tc[k][1]); |
|||
} |
|||
} |
|||
|
|||
o.vb_id = 0; |
|||
o.numTriangles = 0; |
|||
|
|||
// OpenGL viewer does not support texturing with per-face material.
|
|||
if (shapes[s].mesh.material_ids.size() > 0 && |
|||
shapes[s].mesh.material_ids.size() > s) { |
|||
o.material_id = shapes[s].mesh.material_ids[0]; // use the material ID
|
|||
// of the first face.
|
|||
} else { |
|||
o.material_id = materials.size() - 1; // = ID for default material.
|
|||
} |
|||
|
|||
if (buffer.size() > 0) { |
|||
glGenBuffers(1, &o.vb_id); |
|||
glBindBuffer(GL_ARRAY_BUFFER, o.vb_id); |
|||
glBufferData(GL_ARRAY_BUFFER, buffer.size() * sizeof (float), |
|||
&buffer.at(0), GL_STATIC_DRAW); |
|||
o.numTriangles = buffer.size() / (3 + 3 + 3 + 2) / |
|||
3; // 3:vtx, 3:normal, 3:col, 2:texcoord
|
|||
} |
|||
|
|||
drawObjects.push_back(o); |
|||
} |
|||
|
|||
} |
|||
|
|||
~Viewer() { |
|||
shutDown(); |
|||
for (map<string, GLuint>::iterator it = textures.begin(); it != textures.end(); it++) { |
|||
//printf("%s : %d\n", it->first.c_str(), (int) it->second);
|
|||
|
|||
glDeleteTextures(1, &it->second); |
|||
} |
|||
} |
|||
|
|||
//???
|
|||
|
|||
void calcNormal(float N[3], float v0[3], float v1[3], float v2[3]) { |
|||
float v10[3]; |
|||
v10[0] = v1[0] - v0[0]; |
|||
v10[1] = v1[1] - v0[1]; |
|||
v10[2] = v1[2] - v0[2]; |
|||
|
|||
float v20[3]; |
|||
v20[0] = v2[0] - v0[0]; |
|||
v20[1] = v2[1] - v0[1]; |
|||
v20[2] = v2[2] - v0[2]; |
|||
|
|||
N[0] = v20[1] * v10[2] - v20[2] * v10[1]; |
|||
N[1] = v20[2] * v10[0] - v20[0] * v10[2]; |
|||
N[2] = v20[0] * v10[1] - v20[1] * v10[0]; |
|||
|
|||
float len2 = N[0] * N[0] + N[1] * N[1] + N[2] * N[2]; |
|||
if (len2 > 0.0f) { |
|||
float len = sqrtf(len2); |
|||
|
|||
N[0] /= len; |
|||
N[1] /= len; |
|||
N[2] /= len; |
|||
} |
|||
} |
|||
|
|||
void Draw(const std::vector<DrawObject>& drawObjects, |
|||
std::vector<tinyobj::material_t>& materials, |
|||
std::map<std::string, GLuint>& textures) { |
|||
glPolygonMode(GL_FRONT, GL_FILL); |
|||
glPolygonMode(GL_BACK, GL_FILL); |
|||
|
|||
glEnable(GL_POLYGON_OFFSET_FILL); |
|||
glPolygonOffset(1.0, 1.0); |
|||
GLsizei stride = (3 + 3 + 3 + 2) * sizeof (float); |
|||
for (size_t i = 0; i < drawObjects.size(); i++) { |
|||
DrawObject o = drawObjects[i]; |
|||
if (o.vb_id < 1) { |
|||
continue; |
|||
} |
|||
|
|||
glBindBuffer(GL_ARRAY_BUFFER, o.vb_id); |
|||
glEnableClientState(GL_VERTEX_ARRAY); |
|||
glEnableClientState(GL_NORMAL_ARRAY); |
|||
glEnableClientState(GL_COLOR_ARRAY); |
|||
glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
|||
|
|||
glBindTexture(GL_TEXTURE_2D, 0); |
|||
if ((o.material_id < materials.size())) { |
|||
std::string diffuse_texname = materials[o.material_id].diffuse_texname; |
|||
if (textures.find(diffuse_texname) != textures.end()) { |
|||
glBindTexture(GL_TEXTURE_2D, textures[diffuse_texname]); |
|||
} |
|||
} |
|||
glVertexPointer(3, GL_FLOAT, stride, (const void*) 0); |
|||
glNormalPointer(GL_FLOAT, stride, (const void*) (sizeof (float) * 3)); |
|||
glColorPointer(3, GL_FLOAT, stride, (const void*) (sizeof (float) * 6)); |
|||
glTexCoordPointer(2, GL_FLOAT, stride, (const void*) (sizeof (float) * 9)); |
|||
|
|||
glDrawArrays(GL_TRIANGLES, 0, 3 * o.numTriangles); |
|||
|
|||
glBindTexture(GL_TEXTURE_2D, 0); |
|||
} |
|||
|
|||
// draw wireframe
|
|||
glDisable(GL_POLYGON_OFFSET_FILL); |
|||
glPolygonMode(GL_FRONT, GL_LINE); |
|||
glPolygonMode(GL_BACK, GL_LINE); |
|||
|
|||
glColor3f(0.0f, 0.0f, 0.4f); |
|||
for (size_t i = 0; i < drawObjects.size(); i++) { |
|||
DrawObject o = drawObjects[i]; |
|||
if (o.vb_id < 1) { |
|||
continue; |
|||
} |
|||
|
|||
glBindBuffer(GL_ARRAY_BUFFER, o.vb_id); |
|||
glEnableClientState(GL_VERTEX_ARRAY); |
|||
glEnableClientState(GL_NORMAL_ARRAY); |
|||
glDisableClientState(GL_COLOR_ARRAY); |
|||
glDisableClientState(GL_TEXTURE_COORD_ARRAY); |
|||
glVertexPointer(3, GL_FLOAT, stride, (const void*) 0); |
|||
glNormalPointer(GL_FLOAT, stride, (const void*) (sizeof (float) * 3)); |
|||
glColorPointer(3, GL_FLOAT, stride, (const void*) (sizeof (float) * 6)); |
|||
glTexCoordPointer(2, GL_FLOAT, stride, (const void*) (sizeof (float) * 9)); |
|||
|
|||
glDrawArrays(GL_TRIANGLES, 0, 3 * o.numTriangles); |
|||
} |
|||
} |
|||
private: |
|||
vector<DrawObject> drawObjects; |
|||
float bmin[3], bmax[3]; |
|||
float eye[3], lookat[3], up[3]; |
|||
float maxExtent; |
|||
float curr_quat[4]; |
|||
|
|||
tinyobj::attrib_t attrib; |
|||
vector<tinyobj::shape_t> shapes; |
|||
vector<tinyobj::material_t> materials; |
|||
map<string, GLuint> textures; |
|||
string texPath; |
|||
}; |
|||
|
|||
int main(int argc, char** argv) { |
|||
|
|||
Viewer viewer(1024, 768, "Viewer"); |
|||
viewer.loop(); |
|||
|
|||
return 0; |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue