I am against one problem with my C++ code. I am using the Assimp library, and I have one class that has one attribute of type const aiScene*. In the constructor of the class, I assign this value and all works fine, but when I exit the constructor code, the parameter const aiScene* does not have any data assigned
I paste you here the code.
Model.h
class Model
{
public:
Model(std::string objectLoc, std::string vertexLoc, std::string fragmentLoc,
glm::vec3 position, glm::vec3 scale, glm::vec3 rotation,
Camera* camera);
void render();
~Model();
private:
std::string objectLoc, vertexLoc, fragmentLoc;
Shader* shader;
glm::mat4 model;
glm::vec3 position, scale, rotation;
Camera* camera;
std::vector<Mesh*> meshes;
std::vector<Texture*> textures;
std::vector<unsigned int> meshToTex;
std::unordered_map<std::string, GLuint> boneMapping;
std::vector<glm::mat4> bonesTransformations;
const aiScene* scene;
glm::mat4 globalInverseTransform;
GLuint boneCount;
};
Model.cpp
Model::Model(std::string objectLoc, std::string vertexLoc, std::string fragmentLoc, glm::vec3
position, glm::vec3 scale, glm::vec3 rotation, Camera* camera)
: objectLoc(objectLoc), vertexLoc(vertexLoc), fragmentLoc(fragmentLoc),
position(position), scale(scale), rotation(rotation),
camera(camera),
boneCount(0)
{
shader = new Shader(vertexLoc, fragmentLoc,
DirectionalLight(glm::vec3(1.0f, 1.0f, 1.0f), 0.4f, 0.1f, glm::vec3(0.0f, 0.0f, -1.0f)),
SpecularLight(1.0f, 250.0f),
SpotLight(glm::vec3(1.0f, 1.0f, 1.0f), 0.0f, 1.0f, glm::vec3(0.0f, 0.0f, 0.0f), 1.0f, 0.0f, 0.0f,
glm::vec3(0.0f, 0.0f, -1.0f), glm::radians(10.0f)));
shader->addPointLight(PointLight(glm::vec3(1.0f, 0.0f, 0.0f), 0.2f, 0.2f, glm::vec3(0.0f, 0.0f,
-15.0f), 0.3f, 0.2f, 0.1f));
shader->addPointLight(PointLight(glm::vec3(0.0f, 1.0f, 0.0f), 0.2f, 0.2f, glm::vec3(10.0f, 0.0f,
-15.0f), 0.3f, 0.2f, 0.1f));
shader->addPointLight(PointLight(glm::vec3(0.0f, 0.0f, 1.0f), 0.2f, 1.2f, glm::vec3(-10.0f, 0.0f,
-15.0f), 0.8f, 0.2f, 0.1f));
model = glm::translate(glm::mat4(1.0f), position)
* glm::scale(glm::mat4(1.0f), scale)
* glm::rotate(glm::mat4(1.0f), glm::radians(rotation.x), glm::vec3(1, 0, 0))
* glm::rotate(glm::mat4(1.0f), glm::radians(rotation.y), glm::vec3(0, 1, 0))
* glm::rotate(glm::mat4(1.0f), glm::radians(rotation.z), glm::vec3(0, 0, 1));
Assimp::Importer importer;
scene = importer.ReadFile(objectLoc,
aiProcess_Triangulate |
aiProcess_FlipUVs |
aiProcess_GenSmoothNormals |
aiProcess_JoinIdenticalVertices);
if (!scene)
{
printf("Cannot load model %s: %s\n", objectLoc.c_str(), importer.GetErrorString());
return;
}
aiNode* rootNode = scene->mRootNode;
globalInverseTransform = aiMatrix4x4ToGlm(rootNode->mTransformation.Inverse());
loadNode(rootNode);
loadTextures();
}
I have tried everything, from copy one by one the attributes to the object scene, to make a clone method in all classes involved, but nothing. Even, I have thought that the problem could be the const identifier in the scene attribute, but if I make the object not constant, it works wrongly the same.
I am not modifying that attribute in any of the methods of the Model class.
I paste you here some photos of the problem.
Good result in the constructor
Bad result out of the constructor
If you could help me it would be great.
The documentation says
The returned data is intended to be read-only, the importer object keeps ownership of the data and will destroy it upon destruction.
[Assimp::Importer::ReadFile]
When the constructor is left Assimp::Importer importer; and the object scene is pointing to are destroyed.
You have to make a copy of it before you leave the constructor or
Use GetOrphanedScene() to take ownership of it.
[Assimp::Importer::ReadFile]
aiScene* Assimp::Importer::GetOrphanedScene ( )
Returns the scene loaded by the last successful call to ReadFile() and releases the scene from the ownership of the Importer instance.
The application is now responsible for deleting the scene. Any further calls to GetScene() or GetOrphanedScene() will return NULL - until a new scene has been loaded via ReadFile().
Returns:
Current scene or NULL if there is currently no scene loaded
Note:
Use this method with maximal caution, and only if you have to. By design, aiScene's are exclusively maintained, allocated and deallocated by Assimp and no one else. The reasoning behind this is the golden rule that deallocations should always be done by the module that did the original allocation because heaps are not necessarily shared. GetOrphanedScene() enforces you to delete the returned scene by yourself, but this will only be fine if and only if you're using the same heap as assimp. On Windows, it's typically fine provided everything is linked against the multithreaded-dll version of the runtime library. It will work as well for static linkage with Assimp.
[Assimp::Importer::GetOrphanedScene]
Related
I am using Bullet Physics to simulate a box fixed two meters above the ground, and another one hanging down from it with a spring (or maybe better a rubberband of equilibrium length 0) simulated by a btGeneric6DofSpringConstraint.
btCollisionShape *shape = createBoxShape(0.2f, 0.2f, 0.2f);
btRigidBody *bodies[] = {
createStaticStatic(shape),
createDynamic(10 * getVolume(shape), shape),
};
bodies[0]->getWorldTransform().setOrigin({ 0.0f, 2.0f, 1.0f });
bodies[1]->getWorldTransform().setOrigin({ 0.0f, 1.0f, 1.0f });
// We can use 'btGeneric6DofSpring2Constraint' instead
btGeneric6DofSpringConstraint *spring = new btGeneric6DofSpringConstraint(
*bodies[0], *bodies[1],
{ 0.0f, -0.2f, 0.0f }, { 0.0f, 0.2f, 0.0f },
true
);
// Disable limits
spring->setLinearLowerLimit({ 1.0f, 1.0f, 1.0f });
spring->setLinearUpperLimit({ -1.0f, -1.0f, -1.0f });
// Enable spring behavior
for (int i = 0; i < 3; ++i)
{
spring->enableSpring(i, true);
spring->setStiffness(i, 35.0f);
spring->setDamping(i, 1.0f);
spring->setEquilibriumPoint(i, 0);
}
world->addConstraint(spring);
Now I enounter the problem that no damping is applied to the spring, no matter what value I use in setDamping. I read that this can be fixed by using btGeneric6DofSpring2Constraint instead (note the 2 after the Spring). But now the spring behaves unpredictable (generates energy, changes direction, etc.) whenever the spring is not attached to the bodies centers of mass (as in the example above).
Has anybody any idea what could be the problem? What is the difference between btGeneric6DofSpringConstraint and btGeneric6DofSpring2Constraint anyway?
I used memcpy to copy a struct Vertex comprised of glm::vec3 objects.
It worked to copy the struct in a class function.
It did not work in the copy constructor that was called when that function returned the class object.
Why?
Class function returning object
ShapeData ShapeGenerator::drawTriangle() {
ShapeData ret;
Vertex verts[] = {
glm::vec3(0.0f, 1.0f, 0.0f),
glm::vec3(1.0f, 0.0f, 0.0f),
glm::vec3(-1.0f, -1.0f, 0.0f),
glm::vec3(0.0f, 1.0f, 0.0f),
glm::vec3(1.0f, -1.0f, 0.0f),
glm::vec3(0.0f, 0.0f, 1.0f),
};
ret.numVerts = NUM_ARRAY_ELEMENTS(verts);
ret.verts = new Vertex[ret.numVerts];
memcpy(ret.verts, verts, sizeof(verts)); //WORKS
GLushort indicies[] = {0,1,2};
ret.numIndicies = NUM_ARRAY_ELEMENTS(indicies);
ret.indicies = new GLushort[ret.numIndicies];
memcpy(ret.indicies, indicies, sizeof(indicies));
return ret;
}
Copy Constructor
ShapeData(const ShapeData& data) {
verts = new Vertex[data.numVerts];
//memcpy(verts, data.verts, sizeof(data.verts)); //DOES NOT WORK
std::copy( data.verts, data.verts + data.numVerts, verts);
indicies = new GLushort[data.numIndicies];
memcpy(indicies, data.indicies, sizeof(data.indicies));
numVerts = data.numVerts;
numIndicies = data.numIndicies;
std::cout << numVerts << std::endl;
}
Vertex:
#ifndef VERTEX_H
#define VERTEX_H
#include <glm/glm.hpp>
struct Vertex {
glm::vec3 position;
glm::vec3 color;
};
#endif
memcpy(verts, data.verts, sizeof(data.verts)); //DOES NOT WORK
does not work since verts is a pointer, not an array. sizeof(data.verts) does not evaluate to the size of the array the pointer points to. It simply evaluates to the size of a pointer on your platform.
You should be able to use:
size_t n = sizeof(*data.verts)*data.numVerts;
memcpy(verts, data.verts, n);
Im trying to draw a triangle on screen using openGL on cocos2dx. Currently i have subclassed cocos' Node object inside which i do my drawing.
In the latest version of cocos2dx i cannot override the draw() function instead im trying to override draw(Renderer* renderer, const Mat4 &transform, uint32_t flags) and add Custom commands to the renderer, like so.
const GLfloat vertices[9] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
void MyNodeSubclass::draw(Renderer* renderer, const Mat4 &transform, uint32_t flags){
CustomCommand *_customCommand = new CustomCommand();
_customCommand->init(_globalZOrder);
_customCommand->func = CC_CALLBACK_0(MyNodeSubclass::drawTriangle, this);
renderer->addCommand(_customCommand);
}
void MyNodeSubclass::drawTriangle(){
glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE,0, vertices);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
And My Load Shader method
void MyNodeSubclass::loadOurShaders(){
GLProgram* myShader = new GLProgram();
myShader->initWithFilenames("shader.vert", "shader.frag");
myShader->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_POSITION, GLProgram::VERTEX_ATTRIB_POSITION);
myShader->link();
myShader->updateUniforms();
}
I dont see the triangle on screen. But I'm able to draw cocos2dx primitive objects (polygons , points , lines) by just swapping out whats in my drawTriangle function but not my vertices using openGL.
What am i missing here?
So I have begun learning OpenGL, reading from the book "OpenGL Super Bible 5 ed.". It's explains things really well, and I have been able to create my first gl program myself! Just something simple, a rotating 3d pyramid.
Now for some reason one of the faces are not rendering. I checked the vertecies (plotted it on paper first) and it seemed to be right. Found out if I changed the shader to draw a line loop, it would render. However it would not render a triangle. Can anyone explain why?
void setupRC()
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
shaderManager.InitializeStockShaders();
M3DVector3f vVerts1[] = {-0.5f,0.0f,-0.5f,0.0f,0.5f,0.0f,0.5f,0.0f,-0.5f};
M3DVector3f vVerts2[] = {-0.5f,0.0f,-0.5f,0.0f,0.5f,0.0f,-0.5f,0.0f,0.5f};
M3DVector3f vVerts3[] = {-0.5f,0.0f,0.5f,0.0f,0.5f,0.0f,0.5f,0.0f,0.5f};
M3DVector3f vVerts4[] = {0.5f,0.0f,0.5f,0.0f,0.5f,0.0f,0.5f,0.0f,-0.5f};
triangleBatch1.Begin(GL_LINE_LOOP, 3);
triangleBatch1.CopyVertexData3f(vVerts1);
triangleBatch1.End();
triangleBatch2.Begin(GL_TRIANGLES, 3);
triangleBatch2.CopyVertexData3f(vVerts2);
triangleBatch2.End();
triangleBatch3.Begin(GL_TRIANGLES, 3);
triangleBatch3.CopyVertexData3f(vVerts3);
triangleBatch3.End();
triangleBatch4.Begin(GL_TRIANGLES, 3);
triangleBatch4.CopyVertexData3f(vVerts4);
triangleBatch4.End();
glEnable(GL_CULL_FACE);
}
float rot = 1;
void renderScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
GLfloat vRed[] = {1.0f, 0.0f, 0.0f, 0.5f};
GLfloat vBlue[] = {0.0f, 1.0f, 0.0f, 0.5f};
GLfloat vGreen[] = {0.0f, 0.0f, 1.0f, 0.5f};
GLfloat vWhite[] = {1.0f, 1.0f, 1.0f, 0.5f};
M3DMatrix44f transformMatrix;
if (rot >= 360)
rot = 0;
else
rot = rot + 1;
m3dRotationMatrix44(transformMatrix,m3dDegToRad(rot),0.0f,1.0f,0.0f);
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformMatrix, vRed);
triangleBatch1.Draw();
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformMatrix, vBlue);
triangleBatch2.Draw();
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformMatrix, vGreen);
triangleBatch3.Draw();
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformMatrix, vWhite);
triangleBatch4.Draw();
glutSwapBuffers();
glutPostRedisplay();
Sleep(10);
}
You've most likely defined the vertices in clockwise order for the triangle that isn't showing, and in counterclockwise order (normally the default) for those that are. Clockwise winding essentially creates an inward facing normal and thus OpenGL won't bother to render it when culling is enabled.
The easiest way to check this is to set glCullFace(GL_FRONT)--that should toggle it so you see the missing triangle and no longer see the other three.
The only thing I see that affects polygons here is glEnable(GL_CULL_FACE);.
You shouldn't have that, because if you plot your vertices backwards, the polygon won't render.
Remove it or actually call glDisable(GL_CULL_FACE); to be sure.
In your case, it's not likely that you want to draw a polygon that you can see from one side only.
This is a simple issue that I'm somewhat ashamed to ask for help on.
I'm making a simple call to gluSphere to render a sphere, however, it does not light properly even though I'm pretty sure I added the normals and lighting correctly. If, however, I add a texture, the model lights normally, except it seems to be always SMOOTH, and I cannot change it to flat.
This is the lighting code in my init() function:
gl.glLightfv( GL.GL_LIGHT0, GL.GL_AMBIENT , AMBIENT_LIGHT, 0 );
gl.glLightfv( GL.GL_LIGHT0, GL.GL_DIFFUSE , DIFFUSE_LIGHT, 0 );
gl.glLightfv( GL.GL_LIGHT0, GL.GL_POSITION, light_pos , 0 );
gl.glEnable ( GL.GL_LIGHT0 );
gl.glEnable ( GL.GL_LIGHTING );
this is my sphere code in my display() function:
gl.glColor3d(1.0, 1.0, 1.0);
glu.gluQuadricDrawStyle (quad, GLU.GLU_FILL);
glu.gluQuadricNormals (quad, GLU.GLU_FLAT);
glu.gluQuadricOrientation(quad, GLU.GLU_OUTSIDE);
glu.gluSphere(quad, 1.0, lat, lon);
Please advise.
EDIT:
light values:
public final static float[] DIFFUSE_LIGHT = { 1.0f, 1.0f, 1.0f, 1.0f };
public final static float[] AMBIENT_LIGHT = { 0.3f, 0.3f, 0.3f, 1.0f };
public float[] light_pos = { -2.0f, 2.0f, 10.0f, 0.0f };
added materials, no change:
gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT , new float[]{0.5f, 0.5f, 0.5f, 1.0f}, 0);
gl.glMaterialfv(GL.GL_FRONT, GL.GL_DIFFUSE , new float[]{1.0f, 1.0f, 1.0f, 1.0f}, 0);
gl.glMaterialfv(GL.GL_FRONT, GL.GL_SPECULAR, new float[]{0.7f, 0.7f, 0.7f, 1.0f}, 0);
gl.glMaterialf (GL.GL_FRONT, GL.GL_SHININESS, 0.5f);
gl.glMaterialfv(GL.GL_FRONT, GL.GL_EMISSION, new float[]{0.3f, 0.3f, 0.3f, 0.0f}, 0);
EDIT2:
Blah, I figured i had a:
gl.glEnable(GL.GL_TEXTURE_2D);
active somewhere and it was causing my model not to have shading if there was no texture associated with it. -_- carry on good people, carry on.
I encountered lighting problem too and figured out that i need to add glEnable(GL_NORMALIZE).
What kind of lighting are you expecting? The third parameter to glLightfv is supposed to be the values of the light you are setting.
Are there any translations/rotations you do that may affect the position of the light?
Is GL_COLOR_MATERIAL enabled or disabled? It may overwrite your material settings if it is.
Even if your code is not enabling GL_TEXTURE_2D, you should try disabling it manually right before the line is reached, just in case.
If you wish to ignore gluSphere completely, there's some code in this thread that you can use.