You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
321 lines
10 KiB
321 lines
10 KiB
|
7 months ago
|
/**
|
||
|
|
********************************************************************************
|
||
|
|
* Copyright (C) 2024 NEXTCHIP Inc. All rights reserved.
|
||
|
|
* This software is the confidential and proprietary information of
|
||
|
|
* NEXTCHIP, Inc. ("Confidential Information"). You shall not disclose such
|
||
|
|
* Confidential Information and shall use it only in accordance with
|
||
|
|
* the terms of the license agreement you entered into with NEXTCHIP.
|
||
|
|
********************************************************************************
|
||
|
|
|
||
|
|
********************************************************************************
|
||
|
|
* @file : nc_opengl_init.c
|
||
|
|
*
|
||
|
|
* @brief : nc_opengl_init source
|
||
|
|
*
|
||
|
|
* @author : Software Development Team. NextChip Inc.
|
||
|
|
*
|
||
|
|
* @date : 2024.08.09.
|
||
|
|
*
|
||
|
|
* @version : 1.0.0
|
||
|
|
********************************************************************************
|
||
|
|
* @note
|
||
|
|
*
|
||
|
|
********************************************************************************
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include "nc_opengl_init.h"
|
||
|
|
|
||
|
|
GLuint nc_loadTexture(const char * imagepath)
|
||
|
|
{
|
||
|
|
//printf("Loading image %s\n", imagepath);
|
||
|
|
|
||
|
|
int width, height, channels;
|
||
|
|
unsigned char* image_data = SOIL_load_image(imagepath, &width, &height, &channels, SOIL_LOAD_AUTO);
|
||
|
|
if (!image_data) {
|
||
|
|
printf("Failed to load DDS image: %s\n", imagepath);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Create one OpenGL texture
|
||
|
|
GLuint textureID;
|
||
|
|
glGenTextures(1, &textureID);
|
||
|
|
glBindTexture(GL_TEXTURE_2D, textureID);
|
||
|
|
|
||
|
|
// Set image data to texture
|
||
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data);
|
||
|
|
|
||
|
|
// Setting filtering options
|
||
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||
|
|
|
||
|
|
// TEXTURE MEMORY OFF
|
||
|
|
SOIL_free_image_data(image_data);
|
||
|
|
|
||
|
|
// Return the ID of the texture we just created
|
||
|
|
return textureID;
|
||
|
|
}
|
||
|
|
|
||
|
|
GLuint nc_loadBMP_custom(const char * imagepath)
|
||
|
|
{
|
||
|
|
printf("Loading Bmp image %s\n", imagepath);
|
||
|
|
|
||
|
|
// Data read from the header of the BMP file
|
||
|
|
unsigned char header[54];
|
||
|
|
unsigned int dataPos;
|
||
|
|
unsigned int imageSize;
|
||
|
|
unsigned int width, height;
|
||
|
|
// Actual RGB data
|
||
|
|
unsigned char * data;
|
||
|
|
|
||
|
|
// Open the file
|
||
|
|
FILE * file = fopen(imagepath,"rb");
|
||
|
|
if (!file)
|
||
|
|
{
|
||
|
|
printf("Image could not be opened\n");
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Read the header, i.e. the 54 first bytes
|
||
|
|
// If less than 54 byes are read, problem
|
||
|
|
if ( fread(header, 1, 54, file)!=54 ){
|
||
|
|
printf("Not a correct BMP file\n");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
// A BMP files always begins with "BM"
|
||
|
|
if ( header[0]!='B' || header[1]!='M' ){
|
||
|
|
printf("Not a correct BMP file\n");
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
// Make sure this is a 24bpp file
|
||
|
|
if ( *(int*)&(header[0x1E])!=0 )
|
||
|
|
{
|
||
|
|
printf("Not a correct BMP file\n");
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
if ( *(int*)&(header[0x1C])!=24 )
|
||
|
|
{
|
||
|
|
printf("Not a correct BMP file\n");
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Read the information about the image
|
||
|
|
dataPos = *(int*)&(header[0x0A]);
|
||
|
|
imageSize = *(int*)&(header[0x22]);
|
||
|
|
width = *(int*)&(header[0x12]);
|
||
|
|
height = *(int*)&(header[0x16]);
|
||
|
|
|
||
|
|
// Some BMP files are misformatted, guess missing information
|
||
|
|
if (imageSize==0)
|
||
|
|
imageSize=width*height*3; // 3 : one byte for each Red, Green and Blue component
|
||
|
|
if (dataPos==0)
|
||
|
|
dataPos=54; // The BMP header is done that way
|
||
|
|
|
||
|
|
// Create a buffer
|
||
|
|
data = new unsigned char [imageSize];
|
||
|
|
|
||
|
|
// Read the actual data from the file into the buffer
|
||
|
|
fread(data,1,imageSize,file);
|
||
|
|
|
||
|
|
// Everything is in memory now, the file wan be closed
|
||
|
|
fclose (file);
|
||
|
|
|
||
|
|
// Create one OpenGL texture
|
||
|
|
GLuint textureID;
|
||
|
|
glGenTextures(1, &textureID);
|
||
|
|
|
||
|
|
// "Bind" the newly created texture : all future texture functions will modify this texture
|
||
|
|
glBindTexture(GL_TEXTURE_2D, textureID);
|
||
|
|
|
||
|
|
// Give the image to OpenGL
|
||
|
|
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
|
||
|
|
|
||
|
|
// Poor filtering, or ...
|
||
|
|
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||
|
|
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||
|
|
|
||
|
|
// ... nice trilinear filtering.
|
||
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||
|
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||
|
|
|
||
|
|
// Return the ID of the texture we just created
|
||
|
|
return textureID;
|
||
|
|
}
|
||
|
|
|
||
|
|
int nc_loadOBJ(const char * path, Vector3 **pVertices, Vector2 **pUvs, Vector3 **pNormals, int *pObjCount)
|
||
|
|
{
|
||
|
|
printf("Loading OBJ file %s...\n", path);
|
||
|
|
|
||
|
|
int obj_count=0;
|
||
|
|
GLuint *vertexIndices, *uvIndices, *normalIndices;
|
||
|
|
|
||
|
|
Vector3 *temp_vertices;
|
||
|
|
Vector2 *temp_uvs;
|
||
|
|
Vector3 *temp_normals;
|
||
|
|
|
||
|
|
int numVertices = 0;
|
||
|
|
int numNormals = 0;
|
||
|
|
int numUvs = 0;
|
||
|
|
int numIndices = 0;
|
||
|
|
|
||
|
|
FILE * fp = fopen(path, "r");
|
||
|
|
if( fp == NULL ){
|
||
|
|
printf("Impossible to open the file ! Are you in the right path ? See Tutorial 1 for details\n");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Count the number of vertices, normals, and indices in the file
|
||
|
|
char line[256];
|
||
|
|
while (fgets(line, sizeof(line), fp)) {
|
||
|
|
if (line[0] == 'v') {
|
||
|
|
if (line[1] == ' ') {
|
||
|
|
numVertices++;
|
||
|
|
} else if (line[1] == 'n') {
|
||
|
|
numNormals++;
|
||
|
|
} else if (line[1] == 't') {
|
||
|
|
numUvs++;
|
||
|
|
}
|
||
|
|
} else if (line[0] == 'f') {
|
||
|
|
numIndices++;
|
||
|
|
pObjCount[obj_count-1]=numIndices;
|
||
|
|
}else if (line[0] == 'g') {
|
||
|
|
obj_count++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
for(int i=obj_count-1;i>0;i--)
|
||
|
|
{
|
||
|
|
pObjCount[i]=pObjCount[i]-pObjCount[i-1];
|
||
|
|
}
|
||
|
|
|
||
|
|
*pVertices = (Vector3 *)malloc(numIndices * 3 * sizeof(Vector3));
|
||
|
|
*pNormals = (Vector3 *)malloc(numIndices * 3 * sizeof(Vector3));
|
||
|
|
*pUvs = (Vector2 *)malloc(numIndices * 3 * sizeof(Vector2));
|
||
|
|
|
||
|
|
// Allocate memory for vertices, normals, and indices
|
||
|
|
temp_vertices = (Vector3 *)malloc(numVertices * sizeof(Vector3));
|
||
|
|
temp_normals = (Vector3 *)malloc(numNormals * sizeof(Vector3));
|
||
|
|
temp_uvs = (Vector2 *)malloc(numUvs * sizeof(Vector2));
|
||
|
|
|
||
|
|
vertexIndices = (GLuint *)malloc(numIndices * sizeof(GLuint)*3);
|
||
|
|
uvIndices = (GLuint *)malloc(numIndices * sizeof(GLuint)*3);
|
||
|
|
normalIndices = (GLuint *)malloc(numIndices * sizeof(GLuint)*3);
|
||
|
|
|
||
|
|
// Read vertices, normals, and indices from the file
|
||
|
|
rewind(fp);
|
||
|
|
|
||
|
|
int vertexIndex = 0;
|
||
|
|
int uvsIndex = 0;
|
||
|
|
int normalIndex = 0;
|
||
|
|
unsigned int indexIndex = 0;
|
||
|
|
while (fgets(line, sizeof(line), fp))
|
||
|
|
{
|
||
|
|
if (line[0] == 'v')
|
||
|
|
{
|
||
|
|
if (line[1] == ' ')
|
||
|
|
{
|
||
|
|
sscanf(line, "v %f %f %f", &temp_vertices[vertexIndex].x, &temp_vertices[vertexIndex].y, &temp_vertices[vertexIndex].z);
|
||
|
|
vertexIndex++;
|
||
|
|
}else if (line[1] == 't')
|
||
|
|
{
|
||
|
|
GLfloat uv_x, uv_y;
|
||
|
|
sscanf(line, "vt %f %f\n", &uv_x, &uv_y );
|
||
|
|
|
||
|
|
uv_y = -uv_y;// Invert V coordinate since we will only use DDS texture, which are inverted. Remove if you want to use TGA or BMP loaders.
|
||
|
|
|
||
|
|
temp_uvs[uvsIndex].x=uv_x;
|
||
|
|
temp_uvs[uvsIndex].y=uv_y;
|
||
|
|
uvsIndex++;
|
||
|
|
}else if (line[1] == 'n')
|
||
|
|
{
|
||
|
|
sscanf(line, "vn %f %f %f\n", &temp_normals[normalIndex].x, &temp_normals[normalIndex].y, &temp_normals[normalIndex].z);
|
||
|
|
normalIndex++;
|
||
|
|
}
|
||
|
|
}else if (line[0] == 'f')
|
||
|
|
{
|
||
|
|
sscanf(line, "f %u/%u/%u %u/%u/%u %u/%u/%u\n", &vertexIndices[indexIndex], &uvIndices[indexIndex], &normalIndices[indexIndex], &vertexIndices[indexIndex+1], &uvIndices[indexIndex+1], &normalIndices[indexIndex+1], &vertexIndices[indexIndex+2], &uvIndices[indexIndex+2], &normalIndices[indexIndex+2] );
|
||
|
|
indexIndex += 3;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// For each vertex of each triangle
|
||
|
|
for( unsigned int i=0; i<indexIndex; i++ ){
|
||
|
|
// Get the indices of its attributes
|
||
|
|
unsigned int vIndex = vertexIndices[i]-1;
|
||
|
|
unsigned int uIndex = uvIndices[i]-1;
|
||
|
|
unsigned int nIndex = normalIndices[i]-1;
|
||
|
|
|
||
|
|
// Get the attributes thanks to the index
|
||
|
|
(*pVertices)[i] = temp_vertices[ vIndex ];
|
||
|
|
(*pUvs)[i] = temp_uvs[ uIndex ];
|
||
|
|
(*pNormals)[i] = temp_normals[ nIndex ];
|
||
|
|
}
|
||
|
|
|
||
|
|
fclose(fp);
|
||
|
|
|
||
|
|
free(temp_vertices);
|
||
|
|
free(temp_uvs);
|
||
|
|
free(temp_normals);
|
||
|
|
|
||
|
|
free(vertexIndices);
|
||
|
|
free(uvIndices);
|
||
|
|
free(normalIndices);
|
||
|
|
|
||
|
|
return obj_count;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Compiles the OpenGL ES shader.
|
||
|
|
GLuint compileShader(GLenum shaderType, const char* source)
|
||
|
|
{
|
||
|
|
GLuint shader = glCreateShader(shaderType);
|
||
|
|
glShaderSource(shader, 1, &source, NULL);
|
||
|
|
glCompileShader(shader);
|
||
|
|
|
||
|
|
GLint compileStatus;
|
||
|
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
|
||
|
|
if (compileStatus != GL_TRUE) {
|
||
|
|
GLint infoLogLength;
|
||
|
|
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
|
||
|
|
GLchar* infoLog = (GLchar*)malloc(infoLogLength + 1);
|
||
|
|
glGetShaderInfoLog(shader, infoLogLength, NULL, infoLog);
|
||
|
|
printf("Shader compilation failed:\n%s\n", infoLog);
|
||
|
|
free(infoLog);
|
||
|
|
glDeleteShader(shader);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
return shader;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Create an OpenGLES program.
|
||
|
|
GLuint nc_createProgram(const char* vertexSource, const char* fragmentSource)
|
||
|
|
{
|
||
|
|
GLuint vertexShader = compileShader(GL_VERTEX_SHADER, vertexSource);
|
||
|
|
GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragmentSource);
|
||
|
|
|
||
|
|
GLuint program = glCreateProgram();
|
||
|
|
glAttachShader(program, vertexShader);
|
||
|
|
glAttachShader(program, fragmentShader);
|
||
|
|
glLinkProgram(program);
|
||
|
|
|
||
|
|
GLint linkStatus;
|
||
|
|
glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
|
||
|
|
if (linkStatus != GL_TRUE) {
|
||
|
|
GLint infoLogLength;
|
||
|
|
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
|
||
|
|
GLchar* infoLog = (GLchar*)malloc(infoLogLength + 1);
|
||
|
|
glGetProgramInfoLog(program, infoLogLength, NULL, infoLog);
|
||
|
|
printf("Program link failed:\n%s\n", infoLog);
|
||
|
|
free(infoLog);
|
||
|
|
glDeleteProgram(program);
|
||
|
|
program = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
glDeleteShader(vertexShader);
|
||
|
|
glDeleteShader(fragmentShader);
|
||
|
|
|
||
|
|
return program;
|
||
|
|
}
|