#include <iostream>
#include <vector>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include "SDL2/SDL.h"
#include "SDL_test_common.h"
#if defined(__IPHONEOS__) || defined(__ANDROID__)
#define HAVE_OPENGLES
#endif
#include "SDL_opengles.h"
SDLTest_CommonState *state;
SDL_Event *event;
static SDL_GLContext *context;
struct mouse_handle {
int x = 1;
int y = 1;
} mouse;
struct Vertex {
float x, y, z;
};
struct Normal {
float nx, ny, nz;
};
Normal calculateNormal(float* coord1, float* coord2, float* coord3) {
float va[3], vb[3], vr[3], val;
va[0] = coord1[0] - coord2[0];
va[1] = coord1[1] - coord2[1];
va[2] = coord1[2] - coord2[2];
vb[0] = coord1[0] - coord3[0];
vb[1] = coord1[1] - coord3[1];
vb[2] = coord1[2] - coord3[2];
// Iloczyn wektorowy
vr[0] = va[1] * vb[2] - vb[1] * va[2];
vr[1] = vb[0] * va[2] - va[0] * vb[2];
vr[2] = va[0] * vb[1] - vb[0] * va[1];
// Normalizacja
val = sqrt(vr[0] * vr[0] + vr[1] * vr[1] + vr[2] * vr[2]);
return { vr[0] / val, vr[1] / val, vr[2] / val };
}
static GLubyte color[8][4] = {{255, 0, 0, 0}};
std::vector<Vertex> vertices;
std::vector<Normal> normals;
void loadObj(const char *fname, std::vector<Vertex>& vertices, std::vector<Normal>& normals) {
int fd = open(fname, O_RDONLY);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
off_t fileSize = lseek(fd, 0, SEEK_END);
if (fileSize == -1) {
perror("lseek");
close(fd);
exit(EXIT_FAILURE);
}
void *map = mmap(NULL, fileSize, PROT_READ, MAP_PRIVATE, fd, 0);
if (map == MAP_FAILED) {
perror("mmap");
close(fd);
exit(EXIT_FAILURE);
}
close(fd);
const char *data = (const char *)map;
const char *end = data + fileSize;
std::vector<Vertex> tempVertices;
std::vector<Normal> tempNormals;
bool hasNormals = false;
while (data < end) {
if (strncmp(data, "v ", 2) == 0) {
data += 2;
float x, y, z;
if (sscanf(data, "%f %f %f", &x, &y, &z) == 3) {
tempVertices.push_back({x, y, z});
}
} else if (strncmp(data, "vn ", 3) == 0) {
data += 3;
float nx, ny, nz;
if (sscanf(data, "%f %f %f", &nx, &ny, &nz) == 3) {
tempNormals.push_back({nx, ny, nz});
/*CZY JEST NORMALNY ??*/
hasNormals = true;
//haze normalny.
}
} else if (strncmp(data, "f ", 2) == 0) {
data += 2;
int v[3], n[3];
if (hasNormals && sscanf(data, "%d//%d %d//%d %d//%d", &v[0], &n[0], &v[1], &n[1], &v[2], &n[2]) == 6) {
vertices.push_back(tempVertices[v[0] - 1]);
normals.push_back(tempNormals[n[0] - 1]);
vertices.push_back(tempVertices[v[1] - 1]);
normals.push_back(tempNormals[n[1] - 1]);
vertices.push_back(tempVertices[v[2] - 1]);
normals.push_back(tempNormals[n[2] - 1]);
} else if (sscanf(data, "%d %d %d", &v[0], &v[1], &v[2]) == 3) {
Vertex& vertex1 = tempVertices[v[0] - 1];
Vertex& vertex2 = tempVertices[v[1] - 1];
Vertex& vertex3 = tempVertices[v[2] - 1];
vertices.push_back(vertex1);
vertices.push_back(vertex2);
vertices.push_back(vertex3);
Normal normal = calculateNormal((float*)&vertex1, (float*)&vertex2, (float*)&vertex3);
normals.push_back(normal);
normals.push_back(normal);
normals.push_back(normal);
}
}
while (data < end && *data != '\n') {
++data;
}
++data;
}
if (munmap(map, fileSize) == -1) {
perror("munmap");
}
}
// Function to set perspective
void setPerspective(float fov, float aspect, float znear, float zfar) {
float ymax = znear * tanf(fov * M_PI / 360.0f);
float ymin = -ymax;
float xmin = ymin * aspect;
float xmax = ymax * aspect;
glFrustumf(xmin, xmax, ymin, ymax, znear, zfar);
}
// Rendering function
void renderScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Projection matrix
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
setPerspective(80.0f, 1.0f, 0.1f, 100.0f);
// Modelview matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -5.0f);
glRotatef(mouse.x % 360, mouse.y% 360, 1.0f, mouse.y% 360);
// Lighting settings
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
GLfloat light_position[] = {0.2f, 1.0f, 10.0f, 1.0f};
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
GLfloat mat_specular[] = {1.0f, 1.0f, 1.0f, 1.0f};
GLfloat mat_shininess[] = {50.0f};
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(Vertex), (void*)vertices.data());
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, sizeof(Normal), (void*)normals.data());
// Draw arrays
glDrawArrays(GL_TRIANGLES, 0, vertices.size());
// Draw arrays
// Disable client states
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
// Swap the window buffer
SDL_GL_SwapWindow(state->windows[0]);
}
int main(int argc, char *argv[]) {
SDL_DisplayMode mode;
state = SDLTest_CommonCreateState(argv, SDL_INIT_EVERYTHING);
SDLTest_CommonInit(state);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
bool sdlmainloop = true;
bool running = true;
loadObj("/sdcard/tea.obj", vertices,normals); // Wczytanie pliku OBJ na poczÄ…tku
SDL_GL_CreateContext(*state->windows);
while (running) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
running = false;
}
if (event.type == SDL_MOUSEMOTION) {
mouse.x = event.motion.x;
mouse.y = event.motion.y;
}
//
// Render the scene
renderScene();
// SDL_GL_SwapWindow(*state->windows);
}
}
// Cleanup
SDL_GL_DeleteContext(context);
SDLTest_CommonQuit(state);
return 0;
}
No comments:
Post a Comment