mirror of
https://github.com/rwengine/openrw.git
synced 2024-11-09 12:22:34 +01:00
Added basic OpenGL rendering of models with -r flag etc
This commit is contained in:
parent
519c51f7ce
commit
06f7af92c2
@ -1,3 +1,5 @@
|
|||||||
add_executable(datadump main.cpp)
|
add_executable(datadump main.cpp)
|
||||||
|
|
||||||
|
target_link_libraries( datadump sfml-graphics sfml-window sfml-system GL GLEW )
|
||||||
|
|
||||||
install(TARGETS datadump RUNTIME DESTINATION bin)
|
install(TARGETS datadump RUNTIME DESTINATION bin)
|
||||||
|
@ -1,3 +1,14 @@
|
|||||||
|
#define GLEW_STATIC
|
||||||
|
#include <GL/glew.h>
|
||||||
|
|
||||||
|
#include <SFML/Window.hpp>
|
||||||
|
#include <SFML/Graphics.hpp>
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include "../framework/rwbinarystream.h"
|
#include "../framework/rwbinarystream.h"
|
||||||
@ -9,6 +20,32 @@ using RW::BSClump;
|
|||||||
|
|
||||||
using namespace RW;
|
using namespace RW;
|
||||||
|
|
||||||
|
sf::Window *window;
|
||||||
|
|
||||||
|
constexpr int WIDTH = 800,
|
||||||
|
HEIGHT = 600;
|
||||||
|
|
||||||
|
const char *vertexShaderSource = "#version 130\n"
|
||||||
|
"in vec3 position;"
|
||||||
|
"in vec2 texCoords;"
|
||||||
|
"out vec2 TexCoords;"
|
||||||
|
"uniform mat4 model;"
|
||||||
|
"uniform mat4 view;"
|
||||||
|
"uniform mat4 proj;"
|
||||||
|
"void main()"
|
||||||
|
"{"
|
||||||
|
" TexCoords = texCoords;"
|
||||||
|
" gl_Position = proj * model * vec4(position, 1.0);"
|
||||||
|
"}";
|
||||||
|
const char *fragmentShaderSource = "#version 130\n"
|
||||||
|
"in vec2 TexCoords;"
|
||||||
|
"uniform sampler2D texture;"
|
||||||
|
"void main()"
|
||||||
|
"{"
|
||||||
|
// " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);"
|
||||||
|
" gl_FragColor = texture2D(texture, TexCoords);"
|
||||||
|
"}";
|
||||||
|
|
||||||
template<class T> T readStructure(char* data, size_t& dataI)
|
template<class T> T readStructure(char* data, size_t& dataI)
|
||||||
{
|
{
|
||||||
size_t orgoff = dataI; dataI += sizeof(T);
|
size_t orgoff = dataI; dataI += sizeof(T);
|
||||||
@ -20,7 +57,29 @@ BSSectionHeader readHeader(char* data, size_t& dataI)
|
|||||||
return readStructure<BSSectionHeader>(data, dataI);
|
return readStructure<BSSectionHeader>(data, dataI);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dumpModelFile(char* data, size_t& dataI)
|
GLuint compileShader(GLenum type, const char *source)
|
||||||
|
{
|
||||||
|
GLuint shader = glCreateShader(type);
|
||||||
|
glShaderSource(shader, 1, &source, NULL);
|
||||||
|
glCompileShader(shader);
|
||||||
|
|
||||||
|
GLint status;
|
||||||
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
|
||||||
|
if (status != GL_TRUE) {
|
||||||
|
GLint len;
|
||||||
|
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
|
||||||
|
GLchar *buffer = new GLchar[len];
|
||||||
|
glGetShaderInfoLog(shader, len, NULL, buffer);
|
||||||
|
|
||||||
|
std::cerr << "ERROR compiling shader: " << buffer << std::endl;
|
||||||
|
delete[] buffer;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dumpModelFile(char* data, size_t dataI)
|
||||||
{
|
{
|
||||||
auto header = readHeader(data, dataI);
|
auto header = readHeader(data, dataI);
|
||||||
|
|
||||||
@ -196,7 +255,7 @@ void dumpModelFile(char* data, size_t& dataI)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dumpTextureDictionary(char* data, size_t& dataI)
|
void dumpTextureDictionary(char* data, size_t dataI)
|
||||||
{
|
{
|
||||||
auto header = readHeader(data, dataI);
|
auto header = readHeader(data, dataI);
|
||||||
|
|
||||||
@ -229,42 +288,246 @@ void dumpTextureDictionary(char* data, size_t& dataI)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void renderModel(char *data, size_t dataI)
|
||||||
|
{
|
||||||
|
window = new sf::Window({WIDTH, HEIGHT}, "GTA Model Viewer", sf::Style::Close);
|
||||||
|
|
||||||
|
glewExperimental = GL_TRUE;
|
||||||
|
glewInit();
|
||||||
|
|
||||||
|
readHeader(data, dataI); // Header
|
||||||
|
readHeader(data, dataI); // ?
|
||||||
|
readStructure<BSClump>(data, dataI); // Clump
|
||||||
|
readHeader(data, dataI); // Frame header
|
||||||
|
readHeader(data, dataI); // ?
|
||||||
|
BSFrameList frames = readStructure<BSFrameList>(data, dataI); // Frames
|
||||||
|
for (size_t i = 0; i < frames.numframes; ++i)
|
||||||
|
readStructure<BSFrameListFrame>(data, dataI);
|
||||||
|
|
||||||
|
auto nextHeader = readHeader(data, dataI);
|
||||||
|
while (nextHeader.id == RW::SID_Extension) {
|
||||||
|
for (size_t i = 0; i < 2; ++i) {
|
||||||
|
auto firstHeader = readHeader(data, dataI);
|
||||||
|
dataI += firstHeader.size;
|
||||||
|
}
|
||||||
|
nextHeader = readHeader(data, dataI);
|
||||||
|
}
|
||||||
|
|
||||||
|
readHeader(data, dataI); // Structure Header..
|
||||||
|
|
||||||
|
// OpenGL
|
||||||
|
glClearColor(0.2, 0.2, 0.2, 1.0);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
// glDepthFunc(GL_GEQUAL);
|
||||||
|
// glDisable(GL_CULL_FACE);
|
||||||
|
|
||||||
|
GLuint vertexShader = compileShader(GL_VERTEX_SHADER, vertexShaderSource);
|
||||||
|
GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragmentShaderSource);
|
||||||
|
GLuint shaderProgram = glCreateProgram();
|
||||||
|
glAttachShader(shaderProgram, vertexShader);
|
||||||
|
glAttachShader(shaderProgram, fragmentShader);
|
||||||
|
glLinkProgram(shaderProgram);
|
||||||
|
glUseProgram(shaderProgram);
|
||||||
|
|
||||||
|
sf::Image uvgridTexture;
|
||||||
|
uvgridTexture.loadFromFile("../datadump/uvgrid.jpg");
|
||||||
|
// sf::Texture::bind(&uvgridTexture);
|
||||||
|
|
||||||
|
GLuint VBO;
|
||||||
|
GLuint EBO;
|
||||||
|
GLuint textures[1];
|
||||||
|
glGenBuffers(1, &VBO);
|
||||||
|
glGenBuffers(1, &EBO);
|
||||||
|
glGenTextures(1, textures);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, textures[0]);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, uvgridTexture.getSize().x, uvgridTexture.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, uvgridTexture.getPixelsPtr());
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
|
||||||
|
auto geomlist = readStructure<BSGeometryList>(data, dataI);
|
||||||
|
for (size_t i = 0; i < geomlist.numgeometry; ++i) {
|
||||||
|
auto geomHeader = readHeader(data, dataI);
|
||||||
|
size_t basedata = dataI;
|
||||||
|
readHeader(data, dataI);
|
||||||
|
auto geom = readStructure<BSGeometry>(data, dataI);
|
||||||
|
|
||||||
|
if (geomHeader.versionid < 0x1003FFFF)
|
||||||
|
auto colors = readStructure<BSGeometryColor>(data, dataI);
|
||||||
|
|
||||||
|
if (geom.flags & BSGeometry::VertexColors) {
|
||||||
|
for (size_t v = 0; v < geom.numverts; ++v) {
|
||||||
|
readStructure<BSColor>(data, dataI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float *texcoords;
|
||||||
|
size_t numTexcoords = 0;
|
||||||
|
if (geom.flags & BSGeometry::TexCoords1 || geom.flags & BSGeometry::TexCoords2) {
|
||||||
|
texcoords = new float[geom.numverts * 2];
|
||||||
|
numTexcoords = geom.numverts * 2 * sizeof(float);
|
||||||
|
|
||||||
|
for (size_t v = 0; v < geom.numverts; ++v) {
|
||||||
|
auto coords = readStructure<BSGeometryUV>(data, dataI);
|
||||||
|
|
||||||
|
texcoords[v*2] = coords.u;
|
||||||
|
texcoords[v*2 + 1] = coords.v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t indicies[geom.numtris * 3];
|
||||||
|
for (int j = 0; j < geom.numtris; ++j) {
|
||||||
|
auto tri = readStructure<BSGeometryTriangle>(data, dataI);
|
||||||
|
|
||||||
|
indicies[j*3] = tri.first;
|
||||||
|
indicies[j*3 + 1] = tri.second;
|
||||||
|
indicies[j*3 + 2] = tri.third;
|
||||||
|
}
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indicies), indicies, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
auto bounds = readStructure<BSGeometryBounds>(data,dataI);
|
||||||
|
|
||||||
|
float *vertices = new float[geom.numverts * 3];
|
||||||
|
size_t numVertices = geom.numverts * 3 * sizeof(float);
|
||||||
|
for (size_t v = 0; v < geom.numverts; ++v) {
|
||||||
|
auto p = readStructure<BSTVector3>(data, dataI);
|
||||||
|
|
||||||
|
vertices[v*3] = p.x;
|
||||||
|
vertices[v*3 + 1] = p.y;
|
||||||
|
vertices[v*3 + 2] = p.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
float *normals;
|
||||||
|
size_t numNormals = 0;
|
||||||
|
if (geom.flags & BSGeometry::StoreNormals) {
|
||||||
|
normals = new float[geom.numverts * 3];
|
||||||
|
numNormals = geom.numverts * 3 * sizeof(float);
|
||||||
|
|
||||||
|
for (size_t v = 0; v < geom.numverts; ++v) {
|
||||||
|
auto p = readStructure<BSTVector3>(data, dataI);
|
||||||
|
|
||||||
|
normals[v*3] = p.x;
|
||||||
|
normals[v*3 + 1] = p.y;
|
||||||
|
normals[v*3 + 2] = p.z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jump to the start of the next geometry
|
||||||
|
dataI = basedata + geomHeader.size;
|
||||||
|
|
||||||
|
/** CHANGE THIS NUMBER TO SELECT A SPECIFIC MODEL! **/
|
||||||
|
if (i <= 11)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Buffer stuff
|
||||||
|
size_t bufferSize = numVertices + numTexcoords + numNormals;
|
||||||
|
std::cout << "BUFFER SIZE IS " << bufferSize << std::endl;
|
||||||
|
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, bufferSize, NULL, GL_STATIC_DRAW);
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, 0, numVertices, vertices);
|
||||||
|
if (numTexcoords > 0)
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, numVertices, numTexcoords, texcoords);
|
||||||
|
if (numNormals > 0)
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, numVertices+numTexcoords, numNormals, normals);
|
||||||
|
|
||||||
|
GLuint posAttrib = glGetAttribLocation(shaderProgram, "position");
|
||||||
|
GLuint texAttrib = glGetAttribLocation(shaderProgram, "texCoords");
|
||||||
|
glEnableVertexAttribArray(posAttrib);
|
||||||
|
glEnableVertexAttribArray(texAttrib);
|
||||||
|
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0);
|
||||||
|
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 0, (void *) numVertices);
|
||||||
|
|
||||||
|
GLuint uniModel = glGetUniformLocation(shaderProgram, "model");
|
||||||
|
GLuint uniView = glGetUniformLocation(shaderProgram, "view");
|
||||||
|
GLuint uniProj = glGetUniformLocation(shaderProgram, "proj");
|
||||||
|
|
||||||
|
glm::mat4 proj = glm::perspective(80.f, (float) WIDTH/HEIGHT, 0.1f, 10.f);
|
||||||
|
glUniformMatrix4fv(uniProj, 1, GL_FALSE, glm::value_ptr(proj));
|
||||||
|
|
||||||
|
int j = 0;
|
||||||
|
while (window->isOpen()) {
|
||||||
|
glm::mat4 model;
|
||||||
|
model = glm::translate(model, glm::vec3(0, 0, -0.5));
|
||||||
|
model = glm::rotate(model, (float) j, glm::vec3(2, 1, 1));
|
||||||
|
glUniformMatrix4fv(uniModel, 1, GL_FALSE, glm::value_ptr(model));
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
glDrawElements(GL_TRIANGLES, geom.numverts, GL_UNSIGNED_SHORT, NULL);
|
||||||
|
|
||||||
|
window->display();
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool loadFile(const char *filename, char **data)
|
||||||
|
{
|
||||||
|
std::ifstream dfile(filename);
|
||||||
|
if ( ! dfile.is_open()) {
|
||||||
|
std::cerr << "Error opening file " << filename << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
dfile.seekg(0, std::ios_base::end);
|
||||||
|
size_t length = dfile.tellg();
|
||||||
|
dfile.seekg(0);
|
||||||
|
*data = new char[length];
|
||||||
|
dfile.read(*data, length);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
for(int i = 1; i < argc; ++i)
|
bool render = false;
|
||||||
{
|
int c;
|
||||||
std::ifstream dfile(argv[i]);
|
while ((c = getopt (argc, argv, "r")) != -1) {
|
||||||
if(!dfile.is_open()) {
|
switch (c) {
|
||||||
std::cerr << "Error opening file " << argv[i] << std::endl;
|
case 'r':
|
||||||
continue;
|
render = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dfile.seekg(0, std::ios_base::end);
|
char *data;
|
||||||
size_t length = dfile.tellg();
|
|
||||||
dfile.seekg(0);
|
|
||||||
char* data = new char[length];
|
|
||||||
dfile.read(data, length);
|
|
||||||
size_t dataI = 0;
|
|
||||||
|
|
||||||
std::string fname = argv[i];
|
if (render) {
|
||||||
auto ext = fname.substr(fname.size()-3);
|
if (loadFile(argv[2], &data)) {
|
||||||
|
renderModel(data, 0);
|
||||||
|
|
||||||
if(ext == "dff" || ext == "DFF")
|
delete[] data;
|
||||||
{
|
|
||||||
std::cout << "Dumping model file" << std::endl;
|
|
||||||
dumpModelFile(data, dataI);
|
|
||||||
}
|
|
||||||
else if(ext == "txd" || ext == "TXD")
|
|
||||||
{
|
|
||||||
std::cout << "Dumping texture archive" << std::endl;
|
|
||||||
dumpTextureDictionary(data, dataI);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << "I'm not sure what that is" << std::endl;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 1; i < argc; ++i) {
|
||||||
|
if ( ! loadFile(argv[i], &data))
|
||||||
|
continue;
|
||||||
|
|
||||||
delete[] data;
|
std::string fname = argv[i];
|
||||||
|
auto ext = fname.substr(fname.size()-3);
|
||||||
|
|
||||||
|
if(ext == "dff" || ext == "DFF")
|
||||||
|
{
|
||||||
|
std::cout << "Dumping model file" << std::endl;
|
||||||
|
dumpModelFile(data, 0);
|
||||||
|
}
|
||||||
|
else if(ext == "txd" || ext == "TXD")
|
||||||
|
{
|
||||||
|
std::cout << "Dumping texture archive" << std::endl;
|
||||||
|
dumpTextureDictionary(data, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "I'm not sure what that is" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
BIN
datadump/uvgrid.jpg
Normal file
BIN
datadump/uvgrid.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 122 KiB |
Loading…
Reference in New Issue
Block a user