This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.
16
Graphics and Video / Re: [WIP] Collada (.dae) 3d Animated Model Loader
« on: September 14, 2017, 04:11:19 pm »
Yeah, for the purpose of the game I'm making, I don't care about dropping GL1 and older computer support. But for the purpose of making the code accessible to other ENIGMA users, I'm trying to be mindful of it. I'm assuming shader words like "in/out/texture" are ok to use in place of "attribute/varying/texture2d", too?
17
Graphics and Video / Re: [WIP] Collada (.dae) 3d Animated Model Loader
« on: September 12, 2017, 05:21:15 pm »
Just wanted to give a quick little update.
The way that the java project that I'm porting this from does the animation is by using shaders, so I've taken a bit of time to learn about GLSL and have a pretty good grasp on it now, and also understand why it does this.
I believe shaders are GL2+ (mainly GL3), meaning that if I were to do a direct port, I'd probably have to drop OpenGL1 and target OpenGL3 in ENIGMA? Since everything is shaders these days, this seems like the way to go.
There's 3 alternatives I can think of:
0) The aforementioned shaders path.
1) Generate vertex models for every animation frame. This would use a huge amount of memory.
2) Handle all the vertex calculations through the CPU. This would require porting the shader's responsibilities into C++ code. Not sure how much ENIGMA's engine can support me along this way, but if I end up writing my own GL calls, GL3.1+ isn't going to like it unless you stick it in compat mode.
So yeah. For the time being, I'm forging ahead and porting option 0.
The way that the java project that I'm porting this from does the animation is by using shaders, so I've taken a bit of time to learn about GLSL and have a pretty good grasp on it now, and also understand why it does this.
I believe shaders are GL2+ (mainly GL3), meaning that if I were to do a direct port, I'd probably have to drop OpenGL1 and target OpenGL3 in ENIGMA? Since everything is shaders these days, this seems like the way to go.
There's 3 alternatives I can think of:
0) The aforementioned shaders path.
1) Generate vertex models for every animation frame. This would use a huge amount of memory.
2) Handle all the vertex calculations through the CPU. This would require porting the shader's responsibilities into C++ code. Not sure how much ENIGMA's engine can support me along this way, but if I end up writing my own GL calls, GL3.1+ isn't going to like it unless you stick it in compat mode.
So yeah. For the time being, I'm forging ahead and porting option 0.
18
Graphics and Video / Re: [WIP] Collada (.dae) 3d Animated Model Loader
« on: September 06, 2017, 02:39:28 pm »
To answer that, let's break it down into 4 parts:
1: Pugixml
Pugixml is its own thing, so you'd have to consult with their website or such for more information, but since all you have to include is just two source files (.cpp and .h) and don't need a dll or anything, it should be relatively platform independent, aside from Windows Line Endings1
2: Interpreting the XML nodes
As far as I can tell, all of my code is standard C++ stuff, nothing fancy or platform dependant. I don't make any direct GL calls, window calls, or filesystem calls, or anything of the sort. Just be platform aware with the path/filename that you pass in.
3: Transferring that data into an ENIGMA mesh
This is just transferring memory to memory, and only depends on ENIGMA's Mesh struct, which appears to have an equivalent in DirectX9, OpenGL1, and so on
4: ENIGMA's GL calls
Again, this is up to ENIGMA. I don't make any GL calls myself, I just offload the Mesh to ENIGMA, and leave it up to the selected GL to make the appropriate calls. I'm on Windows, and ENIGMA is defaulting to OpenGL1, and it works fine.
1 Windows Line Endings don't even seem to play any part in this. I opened up a collada file in notepad and saw no rhyme or reason to line endings - I kinda don't think it uses any. My code also doesn't do anything that would necessarily care about line endings. The only strings I deal with are node names - which should be short identifiers - and space-separated number lists which I simply split on any whitespace.
tl;dr: It's as portable as ENIGMA's GL and Pugixml are. So yes, it should be quite portable. Just copy the code to each GL you intend to use it on.
1: Pugixml
Pugixml is its own thing, so you'd have to consult with their website or such for more information, but since all you have to include is just two source files (.cpp and .h) and don't need a dll or anything, it should be relatively platform independent, aside from Windows Line Endings1
2: Interpreting the XML nodes
As far as I can tell, all of my code is standard C++ stuff, nothing fancy or platform dependant. I don't make any direct GL calls, window calls, or filesystem calls, or anything of the sort. Just be platform aware with the path/filename that you pass in.
3: Transferring that data into an ENIGMA mesh
This is just transferring memory to memory, and only depends on ENIGMA's Mesh struct, which appears to have an equivalent in DirectX9, OpenGL1, and so on
4: ENIGMA's GL calls
Again, this is up to ENIGMA. I don't make any GL calls myself, I just offload the Mesh to ENIGMA, and leave it up to the selected GL to make the appropriate calls. I'm on Windows, and ENIGMA is defaulting to OpenGL1, and it works fine.
1 Windows Line Endings don't even seem to play any part in this. I opened up a collada file in notepad and saw no rhyme or reason to line endings - I kinda don't think it uses any. My code also doesn't do anything that would necessarily care about line endings. The only strings I deal with are node names - which should be short identifiers - and space-separated number lists which I simply split on any whitespace.
tl;dr: It's as portable as ENIGMA's GL and Pugixml are. So yes, it should be quite portable. Just copy the code to each GL you intend to use it on.
19
Graphics and Video / Re: [WIP] Collada (.dae) 3d Animated Model Loader
« on: September 05, 2017, 06:03:38 pm »
I've updated the first post. You'll find that it's now uses ENIGMA's built in mesh/modelling system, and is able to utilize textures. I've also made it a lot easier to stick into ENIGMA with instructions.
(I also found out the texture was applying incorrectly because OpenGL inverts the y coordinates "t" of the texture, so once I accounted for that in the code with 1.0f - t, it worked amazing)
Next I'll be working on animation. This may take a while, but in the meantime, enjoy the ability to read in static collada models!
And if anybody who works on ENIGMA wants to either make this official or figure out how to make this an Extension, that'd be awesome.
(I also found out the texture was applying incorrectly because OpenGL inverts the y coordinates "t" of the texture, so once I accounted for that in the code with 1.0f - t, it worked amazing)
Next I'll be working on animation. This may take a while, but in the meantime, enjoy the ability to read in static collada models!
And if anybody who works on ENIGMA wants to either make this official or figure out how to make this an Extension, that'd be awesome.
20
Graphics and Video / Re: [WIP] Collada (.dae) 3d Animated Model Loader
« on: September 03, 2017, 12:05:02 pm »
Yeah, that's what happens here too. As you see in the GeometryLoader->readPositions loop, I correct the Z-up from the modeller to Y-up. To do this, we can either multiply each vertex vector by a rotated correction matrix (as we kinda do here, I just simplified all the matrix math to y = -z and z = y) OR we can perform a rotational transform of the model after it is set up.
The correction matrix used in the java program is:
And then I set the camera up to be 0,5,15, 0,5,0, 0,1,0 (looking down the Z-axis with Y-up).
I'm currently struggling to get the texture applied. Here's the code I use, which is pretty standard:
I'm also poking at porting this to Enigma's "mesh" used by other models.
The correction matrix used in the java program is:
Code: [Select]
new Matrix4f().rotate((float) Math.toRadians(-90), new Vector3f(1, 0, 0))
which I believe simplifies to:Code: [Select]
{ 1,0,0,0,
0,0,-1,0,
0,1,0,0,
0,0,0,1 }
which again simplifies to:Code: [Select]
//x = x;
tmp = y;
y = -z;
z = tmp;
//w = w;
And then I set the camera up to be 0,5,15, 0,5,0, 0,1,0 (looking down the Z-axis with Y-up).
I'm currently struggling to get the texture applied. Here's the code I use, which is pretty standard:
Code: [Select]
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_RGBA, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, &img[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
but it doesn't applyI'm also poking at porting this to Enigma's "mesh" used by other models.
21
Graphics and Video / Re: [WIP] Collada (.dae) 3d Animated Model Loader
« on: September 02, 2017, 01:01:39 pm »
Like I said, I hacked it into ENIGMA, so it's not as simple as posting a .gmk file. In fact, for testing/developing it, I've actually got my own independent C++ program running on glew and glfw3. I may post that, but you'd need to set up glew and glfw (which is not fun).
UPDATE OP updated to include instructions, so the rest of this post is outdated.
As far as the ENIGMA route goes, typically I just wrap that code in a function and stick it in one of the files in enigma-dev\ENIGMAsystem\SHELL\Graphics_Systems\OpenGL1, call the function something like
int readCollada(std::string fname)
and have it return indices.size();
Then another function:
In a create event:
//General d3d setup code goes here.
vertNum = readCollada("C:/model.dae") //or wherever you put your model
In the draw event:
drawCollada(vertNum)
//don't forget to set up the camera/projection. For the model from the java example, I found the best camera position/orientation to be 0,5,15, 0,5,0, 0,1,0
UPDATE OP updated to include instructions, so the rest of this post is outdated.
As far as the ENIGMA route goes, typically I just wrap that code in a function and stick it in one of the files in enigma-dev\ENIGMAsystem\SHELL\Graphics_Systems\OpenGL1, call the function something like
int readCollada(std::string fname)
and have it return indices.size();
Then another function:
Code: [Select]
void drawCollada(int inds) {
glDrawElements(GL_TRIANGLES, inds, GL_UNSIGNED_INT, 0);
}
In a create event:
//General d3d setup code goes here.
vertNum = readCollada("C:/model.dae") //or wherever you put your model
In the draw event:
drawCollada(vertNum)
//don't forget to set up the camera/projection. For the model from the java example, I found the best camera position/orientation to be 0,5,15, 0,5,0, 0,1,0
22
Graphics and Video / [WIP] Collada (.dae) 3d Animated Model Loader
« on: September 01, 2017, 03:48:24 pm »
Before I start, just let me say that I didn't see any existing code in enigma for loading Collada models, so I started writing my own. I also didn't see any in-built xml readers (aside from the skeletal remains of RapidXML), so I used pugixml. If I missed something, please be nice :-)
I'm aware that ENIGMA is already capable of reading .obj models, which is awesome, but Collada has animation and such.
Collada is an industry standard format (ISO/PAS 17506) for animated 3d models, utilizing skeletal joints for animation (it does some other things too, but this is what I'm using it for here). It stores data in XML.
This, then, is my ENIGMA/C++ reader for said format. It is a work in progress, so be patient and I'll continue to share my progress on it, and feel free to share feedback along the way (this is why I've shared it here). I'm developing this for a game idea that I'm poking at in ENIGMA.
I'm aware that other Collada readers exist, but they tend to be extremely bulky, easily reaching up into multiple MBs, so I figured something much smaller could be achieved and could easily be added to ENIGMA.
I'll provide steps for adding this to ENIGMA, but please ADD AT YOUR OWN RISK. Everything should be easily reversible by just undoing these changes (or if you're familiar with git, there's a git path).
First, pick up a copy of pugixml (not pugxml). Copy the .cpp and .hpp files into ENIGMAsystem/SHELL/Universal_System/ and rename the .hpp to .h
Edit both and add the following lines near the top:
Next, edit ENIGMAsystem/SHELL/Graphics_Systems/General/GSmodel.h and add the following function def:
Finally, edit ENIGMAsystem/SHELL/Graphics_Systems/OpenGL1/GSmodel.cpp (only tested for OpenGL1, but shouldn't require much if any modification for other systems) and on line 41 add the following includes:
So the code will only read the base model right now. Animation will come eventually. It will then push the base model VNT (Vertex, Normal, Texture) and indices into an ENIGMA mesh. Code ported from this java example and AnimatedModelLoader.java
Also, if you need a model/texture to test with, it has one.
Here's an example of it used in a game, if you can get it to compile:
Create a background called tex_dude and load in the texture (diffuse.png in the java example)
Create event:
Draw event:
Updates:
Sept 2 @ 1500est: included a few missing functions
Sept 2 @ 1600est: and a few missing structs
Sept 4 @ 2200est: replaced with instructions for inserting into ENIGMA and an example
Sept 5 @ 1900est: textures now apply correctly
Sept 16 @ 2300est: removed unused skeletal data and recursive function. Should now load a little faster and static models no longer have a dependency on having a skeleton.
Sept 29 @ 1800est: fixed memory leak
Oct 7 @ 1500est: removed unused joint weight data. Should now load a little faster and static models no longer have a dependency on having joint weights.
I'm aware that ENIGMA is already capable of reading .obj models, which is awesome, but Collada has animation and such.
Collada is an industry standard format (ISO/PAS 17506) for animated 3d models, utilizing skeletal joints for animation (it does some other things too, but this is what I'm using it for here). It stores data in XML.
This, then, is my ENIGMA/C++ reader for said format. It is a work in progress, so be patient and I'll continue to share my progress on it, and feel free to share feedback along the way (this is why I've shared it here). I'm developing this for a game idea that I'm poking at in ENIGMA.
I'm aware that other Collada readers exist, but they tend to be extremely bulky, easily reaching up into multiple MBs, so I figured something much smaller could be achieved and could easily be added to ENIGMA.
I'll provide steps for adding this to ENIGMA, but please ADD AT YOUR OWN RISK. Everything should be easily reversible by just undoing these changes (or if you're familiar with git, there's a git path).
First, pick up a copy of pugixml (not pugxml). Copy the .cpp and .hpp files into ENIGMAsystem/SHELL/Universal_System/ and rename the .hpp to .h
Edit both and add the following lines near the top:
Code: [Select]
#define PUGIXML_NO_EXCEPTIONS
#define PUGIXML_NO_STL
Next, edit ENIGMAsystem/SHELL/Graphics_Systems/General/GSmodel.h and add the following function def:
Code: [Select]
void d3d_collada_load(int id, std::string fname);
Finally, edit ENIGMAsystem/SHELL/Graphics_Systems/OpenGL1/GSmodel.cpp (only tested for OpenGL1, but shouldn't require much if any modification for other systems) and on line 41 add the following includes:
Code: [Select]
#include <sstream> //used to split strings
#include <algorithm> //needed for find(), used kinda like indexof
#include "Universal_System/pugixml.h"
And on line 107 or thereabouts (I chose between d3d_model_save and d3d_model_load) add the following code:Code: [Select]
//temporarily stores the vertex data with texture/normal ids to construct unique VNTs
class Vertex {
public:
unsigned int index;
float x, y, z;
int texId = -1;
int normId = -1;
Vertex *next = NULL;
Vertex(int id, float x, float y, float z) :
index(id), x(x), y(y), z(z) {}
};
// I don't like enigma's split functions, so I made my own
template <class T>
std::vector<T> cppsplit(const pugi::char_t* slist) {
std::stringstream ss(slist);
std::vector<T> tlist;
T token;
while (ss >> token)
tlist.push_back(token);
return tlist;
}
//This workhorse reads a collada xml file (.dae) into an enigma model "mesh"
void d3d_collada_load(int id, string fname)
{
pugi::xml_document doc;
doc.load_file(fname.c_str());
pugi::xml_node rootNode = doc.child("COLLADA");
//////////////////
//GeometryLoader//
//////////////////
pugi::xml_node meshData = rootNode.child("library_geometries").child("geometry").child("mesh");
//readPositions
const pugi::char_t* posId = meshData.child("vertices").child("input").attribute("source").value();
pugi::xml_node posData = meshData.find_child_by_attribute("source","id",posId + 1).child("float_array");
int posCount = posData.attribute("count").as_int();
const pugi::char_t* sposList = posData.text().get();
std::stringstream sspos(sposList);
std::vector<Vertex*> vertices;
for(int i = 0; i < posCount / 3; i++) {
float x,y,z;
sspos >> x >> y >> z;
//correct Collada's z-up to y-up with (x,z,-y)
vertices.push_back(new Vertex(i, x,y,z));
}
//readNormals
pugi::xml_node poly = meshData.child("polylist");
const pugi::char_t* normId = poly.find_child_by_attribute("input","semantic","NORMAL").attribute("source").value();
pugi::xml_node normData = meshData.find_child_by_attribute("source","id",normId + 1).child("float_array");
int normCount = normData.attribute("count").as_int();
const pugi::char_t* snormList = normData.text().get();
std::stringstream ssnorm(snormList);
std::vector<std::array<float,3>> normList;
for(int i = 0; i < normCount / 3; i++) {
float x,y,z;
ssnorm >> x >> y >> z;
std::array<float,3> row = {x,y,z}; //correct Collada's z-up to y-up
normList.push_back(row);
}
//readTextureCoords
const pugi::char_t* texcId = poly.find_child_by_attribute("input","semantic","TEXCOORD").attribute("source").value();
pugi::xml_node texcData = meshData.find_child_by_attribute("source","id",texcId + 1).child("float_array");
int texcCount = texcData.attribute("count").as_int();
const pugi::char_t* stexcList = texcData.text().get();
std::stringstream sstexc(stexcList);
std::vector<std::array<float,2>> texcList;
for(int i = 0; i < texcCount / 2; i++) {
float s,t;
sstexc >> s >> t;
std::array<float,2> row = {s, 1.0f - t}; //in OpenGL, texture's y coordinate "t" is inverted
texcList.push_back(row);
}
//assembleVertices
const pugi::char_t* indexData = poly.child("p").text().get();
std::stringstream ssp(indexData);
std::vector<unsigned int> indices;
int idVert, idNorm, idTexc, idCol; //I'm assuming it's just these 4
while (ssp >> idVert >> idNorm >> idTexc >> idCol) {
//processVertex
Vertex *v = vertices[idVert];
if (v->texId == -1 || v->normId == -1) {
v->texId = idTexc;
v->normId = idNorm;
} else if (v->texId != idTexc || v->normId != idNorm) {
//modified dealWithAlreadyProcessedVertex
Vertex *newv = v;
while (newv != NULL) {
if (newv->texId == idTexc && newv->normId == idNorm)
break;
v = newv;
newv = newv->next;
}
if (newv == NULL) {
Vertex *nv = new Vertex(vertices.size(), v->x,v->y,v->z);
nv->texId = idTexc;
nv->normId = idNorm;
vertices.push_back(nv); //this is why we can't just vector<tex,norm>
newv = nv;
v->next = newv;
v = newv;
}
}
indices.push_back(v->index);
}
// Close the xml file
// delete doc;
//"removeUnusedVertices", or in this case we just link them to first texture and normal
for (Vertex *vertex : vertices) {
//tangents aren't used, otherwise we'd average them
if (vertex->normId == -1) vertex->normId = 0;
if (vertex->texId == -1) vertex->texId = 0;
}
// Convert to ENIGMA model/mesh.
meshes[id]->Begin(pr_trianglelist);
for (const Vertex *ov : vertices) {
meshes[id]->AddVertex(ov->x, ov->y, ov->z);
meshes[id]->AddNormal(normList[ov->normId][0],normListov->normId][1],normList[ov->normId][2]);
meshes[id]->AddTexture(texcList[ov->texId][0],texcList[ov->texId][1]);
delete ov;
}
for (unsigned int i = 0; i < indices.size(); i++) {
meshes[id]->AddIndex(indices[i]);
}
meshes[id]->End();
}
So the code will only read the base model right now. Animation will come eventually. It will then push the base model VNT (Vertex, Normal, Texture) and indices into an ENIGMA mesh. Code ported from this java example and AnimatedModelLoader.java
Also, if you need a model/texture to test with, it has one.
Here's an example of it used in a game, if you can get it to compile:
Create a background called tex_dude and load in the texture (diffuse.png in the java example)
Create event:
Code: [Select]
file = "C:/path/to/model.dae" //please point this to a valid collada .dae file
d3d_start();
d3d_set_perspective(true);
d3d_set_hidden(true);
d3d_set_lighting(false);
draw_set_color(c_white);
d3d_set_fog(true,c_white,1,1024);
d3d_set_culling(false)
d3d_set_shading(false);
texture_set_interpolation(true);
//here we load in the model and store it in the "mdl" variable
mdl = d3d_model_create(0); //0 means its static, for now
d3d_collada_load(mdl,file);
Draw event:
Code: [Select]
d3d_set_projection(0,-20,0, 0,0,0, 0,0,1); //feel free to tweak these numbers as needed to point the camera at your model
d3d_model_draw(mdl,0,0,0,background_get_texture(tex_dude));
Updates:
Sept 2 @ 1500est: included a few missing functions
Sept 2 @ 1600est: and a few missing structs
Sept 4 @ 2200est: replaced with instructions for inserting into ENIGMA and an example
Sept 5 @ 1900est: textures now apply correctly
Sept 16 @ 2300est: removed unused skeletal data and recursive function. Should now load a little faster and static models no longer have a dependency on having a skeleton.
Sept 29 @ 1800est: fixed memory leak
Oct 7 @ 1500est: removed unused joint weight data. Should now load a little faster and static models no longer have a dependency on having joint weights.
23
Issues Help Desk / SOLVED - Invalid Memory Address (invokePointer) on startup
« on: August 26, 2017, 02:31:38 pm »
Windows 10
So enigma was working fine yesterday, but today I added a new hard drive and moved my Desktop folder (which contained enigma) and some other folders (Documents, etc - but not Program Files or ProgramData) to the new E: drive. It started throwing this error, so I reinstalled enigma to C:\gamedev\ENIGMA and tweaked the usual things:
settings.ini
enigma-dev/settings.ey
Unfortunately, after the long build process, it's still throwing the exact same error as above.
I also did a "git pull", in case something was outdated, but after it rebuilt the necessary pieces, it still threw the exact same error.
This is quite bizarre since it just worked yesterday.
What exactly happens is I open ENIGMA.exe, the console appears and LateralGM appears, and the console text scrolls for a little bit, and then stops with the aforementioned error - and LateralGM shows the error in a popup.
In other words, it's during startup.
I can close the error and continue to use LateralGM without ENIGMA, but I kinda need ENIGMA, lol.
Update: Forgot to Run as administrator. It used to automatically run as admin, but the move must have changed that. Ran as admin again and it all works again.
Code: [Select]
java.lang.Error: Invalid memory access
at com.sun.jna.Native.invokePointer(Native Method)
at com.sun.jna.Function.invokePointer(Function.java:470)
at com.sun.jna.Function.invoke(Function.java:415)
at com.sun.jna.Function.invoke(Function.java:315)
at com.sun.jna.Library$Handler.invoke(Library.java:212)
at com.sun.proxy.$Proxy0.definitionsModified(Unknown Source)
at org.enigma.backend.EnigmaSettings.commitToDriver(EnigmaSettings.java:247)
at org.enigma.EnigmaRunner$3.run(EnigmaRunner.java:208)
So enigma was working fine yesterday, but today I added a new hard drive and moved my Desktop folder (which contained enigma) and some other folders (Documents, etc - but not Program Files or ProgramData) to the new E: drive. It started throwing this error, so I reinstalled enigma to C:\gamedev\ENIGMA and tweaked the usual things:
settings.ini
Code: [Select]
...
redirectoutput=0
closecmd=0
...
idecommand="C:\Program Files (x86)\Java\jre1.8.0_74\bin\java.exe -jar -Xms256m -Xmx1000m"
(I do java dev, so I needed to explicitly point it to my 32-bit java. I also told the console to stay around so I can see what's going on)enigma-dev/settings.ey
Code: [Select]
...
-make-directory:
...
Default-Windows: "C:/ProgramData/ENIGMA/"
(That directory does exist). As per the usual solution to Invalid Memory Address problems. Doesn't seem to make a difference if I change this or not, though.Unfortunately, after the long build process, it's still throwing the exact same error as above.
I also did a "git pull", in case something was outdated, but after it rebuilt the necessary pieces, it still threw the exact same error.
This is quite bizarre since it just worked yesterday.
What exactly happens is I open ENIGMA.exe, the console appears and LateralGM appears, and the console text scrolls for a little bit, and then stops with the aforementioned error - and LateralGM shows the error in a popup.
In other words, it's during startup.
I can close the error and continue to use LateralGM without ENIGMA, but I kinda need ENIGMA, lol.
Update: Forgot to Run as administrator. It used to automatically run as admin, but the move must have changed that. Ran as admin again and it all works again.