Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anterior Revisión previa Próxima revisión | Revisión previa | ||
|
wiki2:cpp:libraries:openframeworks:creating_graphics [2015/10/08 17:25] alfred [ofCamera] |
wiki2:cpp:libraries:openframeworks:creating_graphics [2020/05/09 09:25] (actual) |
||
|---|---|---|---|
| Línea 118: | Línea 118: | ||
| ''path.setMode(ofPath::POLYLINES)'' which will make that path override the creation of primitives and work directly with ofPolylines which can be slightly faster in certain cases, mostly if you are creating a really high number of paths and modifying them frequently. | ''path.setMode(ofPath::POLYLINES)'' which will make that path override the creation of primitives and work directly with ofPolylines which can be slightly faster in certain cases, mostly if you are creating a really high number of paths and modifying them frequently. | ||
| + | |||
| + | === Notes === | ||
| + | |||
| + | * If you do not close the path then the last point won't join the first one. | ||
| ===== 3D ===== | ===== 3D ===== | ||
| Línea 128: | Línea 132: | ||
| ofRect(20,20,20,20); | ofRect(20,20,20,20); | ||
| </code> | </code> | ||
| - | ... enclosed that between ofPush/PopMatrix. But they are also deprecated. Each call to them, or the gl equivalents for that matter, are doing a multiplication of 4x4 matrices. But we can avoid it somehow. Instead of doing all of the multiplications of the matrices every frame, we can use an ofMatrix4x4 for each shape we use, do all of that shape's transformations once (or every time the shape moves), and apply them later when we want to draw that frame: | + | ... enclosed that between ''ofPushMatrix'' or ''ofPopMatrix''. But they are also deprecated. Each call to them, or the gl equivalents for that matter, are doing a multiplication of 4x4 matrices. But we can avoid it somehow. Instead of doing all of the multiplications of the matrices every frame, we can use an ofMatrix4x4 for each shape we use, do all of that shape's transformations once (or every time the shape moves), and apply them later when we want to draw that frame: |
| <code cpp> | <code cpp> | ||
| ofPath path | ofPath path | ||
| Línea 179: | Línea 183: | ||
| ==== ofMesh ==== | ==== ofMesh ==== | ||
| + | The ofMesh class allows us to represent a 3D model. Internally, it's just a bunch of vectors. Each vector represents one mesh attribute. Those attributes are: vertices, colors, texture coordinates and normals. | ||
| + | <code cpp> | ||
| + | ofMesh mesh; | ||
| + | |||
| + | void ofApp::setup(){ | ||
| + | mesh.addVertex(ofVec3f(20,20)); | ||
| + | mesh.addColor(ofColor::red); | ||
| + | mesh.addVertex(ofVec3f(40,20)); | ||
| + | mesh.addColor(ofColor::red); | ||
| + | mesh.addVertex(ofVec3f(40,40)); | ||
| + | mesh.addColor(ofColor::red); | ||
| + | mesh.addVertex(ofVec3f(20,40)); | ||
| + | mesh.addColor(ofColor::red); | ||
| + | mesh.setMode(OF_PRIMITIVE_TRIANGLE_FAN); | ||
| + | } | ||
| + | |||
| + | void ofApp::draw(){ | ||
| + | mesh.draw(); | ||
| + | } | ||
| + | </code> | ||
| + | Is the same than... | ||
| + | <code cpp> | ||
| + | ofMesh mesh; | ||
| + | |||
| + | // ofApp.cpp | ||
| + | |||
| + | void ofApp::setup(){ | ||
| + | mesh.addVertex(ofVec3f(20,20)); | ||
| + | mesh.addVertex(ofVec3f(40,20)); | ||
| + | mesh.addVertex(ofVec3f(40,40)); | ||
| + | mesh.addVertex(ofVec3f(20,40)); | ||
| + | mesh.addColor(ofColor::red); | ||
| + | mesh.addColor(ofColor::red); | ||
| + | mesh.addColor(ofColor::red); | ||
| + | mesh.addColor(ofColor::red); | ||
| + | mesh.setMode(OF_PRIMITIVE_TRIANGLE_FAN); | ||
| + | } | ||
| + | |||
| + | void ofApp::draw(){ | ||
| + | mesh.draw(); | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | |||
| + | When we add texture coordinates, we probably want to use a texture while drawing that mesh, to use a texture we use bind() on an ofImage or ofTexture and call unbind() when we are done using it. We can even draw several meshes that use the same texture by calling bind/unbind once and drawing all of them. We could even combine color and texture tinting the texture with the color we apply to each vertex. | ||
| + | |||
| + | <code cpp> | ||
| + | ofMesh mesh; | ||
| + | ofImage img; | ||
| + | |||
| + | mesh.addVertex(ofVec3f(200,200)); | ||
| + | mesh.addTexCoord(ofVec2f(0,0)); | ||
| + | mesh.addVertex(ofVec3f(400,200)); | ||
| + | mesh.addTexCoord(ofVec2f(20,0)); | ||
| + | mesh.addVertex(ofVec3f(400,400)); | ||
| + | mesh.addTexCoord(ofVec2f(20,20)); | ||
| + | mesh.addVertex(ofVec3f(200,400)); | ||
| + | mesh.addTexCoord(ofVec2f(0,20)); | ||
| + | mesh.setMode(OF_PRIMITIVE_TRIANGLE_FAN); | ||
| + | img.loadImage("img.png"); | ||
| + | |||
| + | img.bind(); | ||
| + | mesh.draw(); | ||
| + | img.unbind(); | ||
| + | </code> | ||
| + | |||
| + | ==== ofVboMesh ==== | ||
| + | |||
| + | ofVboMesh is a simple class that encapsulates a vbo and inherits from ofMesh. When it's drawn, instead of uploading all the vertices to the graphics card every time call draw on it, it uploads them once when we draw for the first time and only uploads them again if they change. Usually when working with openGL it is advised to use ofVboMesh instead of ofMesh. | ||
| + | |||
| + | There's a case where using an ofVboMesh might be slower, and that's if we want to draw an ofVboMesh, modify it's vertices and then draw it again in the same frame. The problem here is that openGL doesn't really draw things as soon as we tell it to draw. Instead, it stores all the drawing commands and then draws all of them at once and in parallel with the execution of our program. When we try to draw a vbo, modify it's contents and then draw it again in the same frame, openGL would need to really draw the vbo at that exact moment, which means drawing everything else up to that point. That would slow things down a lot. If you need to do something like this, make a copy of the vbo and modify the copy instead of the original. In general don't draw, modify and redraw a vbo in the same frame. So do not do this: | ||
| + | <code cpp> | ||
| + | // ofApp.h | ||
| + | |||
| + | ofVboMesh mesh; | ||
| + | |||
| + | // ofApp.cpp | ||
| + | |||
| + | void ofApp::setup(){ | ||
| + | mesh.addVertex(ofVec3f(20,20)); | ||
| + | mesh.addVertex(ofVec3f(40,20)); | ||
| + | mesh.addVertex(ofVec3f(40,40)); | ||
| + | mesh.addVertex(ofVec3f(20,40)); | ||
| + | mesh.setMode(OF_PRIMITIVE_TRIANGLE_FAN); | ||
| + | } | ||
| + | |||
| + | void ofApp::draw(){ | ||
| + | mesh.draw(); | ||
| + | mesh.getVertices()[1].x+=0.1; | ||
| + | mesh.draw(); // slow!! | ||
| + | } | ||
| + | </code> | ||
| + | ... And do: | ||
| + | <code cpp> | ||
| + | // ofApp.h | ||
| + | |||
| + | ofVboMesh mesh; | ||
| + | ofVboMesh mesh2; | ||
| + | |||
| + | // ofApp.cpp | ||
| + | |||
| + | void ofApp::setup(){ | ||
| + | mesh.addVertex(ofVec3f(20,20)); | ||
| + | mesh.addVertex(ofVec3f(40,20)); | ||
| + | mesh.addVertex(ofVec3f(40,40)); | ||
| + | mesh.addVertex(ofVec3f(20,40)); | ||
| + | mesh.setMode(OF_PRIMITIVE_TRIANGLE_FAN); | ||
| + | mesh2 = mesh; | ||
| + | } | ||
| + | |||
| + | void ofApp::update(){ | ||
| + | mesh.getVertices()[1].x+=0.1; | ||
| + | mesh2.getVertices()[1].x=mesh.getVertices()[1].x + 0.1; | ||
| + | } | ||
| + | |||
| + | void ofApp::draw(){ | ||
| + | mesh.draw(); | ||
| + | mesh2.draw(); // fast!! | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | You can change the way the mesh is drawn using the next constants for the ''setMode'' method: OF_PRIMITIVE_TRIANGLES, OF_PRIMITIVE_TRIANGLE_STRIP, OF_PRIMITIVE_TRIANGLE_FAN, OF_PRIMITIVE_LINES, OF_PRIMITIVE_LINE_STRIP, OF_PRIMITIVE_LINE_LOOP, OF_PRIMITIVE_POINTS. | ||
| + | |||
| + | You can draw the wireframe, the points using the ''drawWireframe()'' and ''drawVertices()'' methods. | ||
| + | |||
| + | ==== of3dPrimitive ==== | ||
| + | of3dPrimitive is a helper class that encapsulates an ofVboMesh and inherits from ofNode. You can call any method you would call on an ofNode, because of how inheritance works, it is actually an ofNode so we can change it's position, rotate it, make it look to some other node, add it to a node hierarchy... And when you call draw on it, it'll draw the mesh it contains applying the transformation defined by it's node. | ||
| + | |||
| + | There's several predefined 3D primitives, like... | ||
| + | * ofPlanePrimitive | ||
| + | * ofSpherePrimitive | ||
| + | * ofIcoSpherePrimitive | ||
| + | * ofCylinderPrimitive | ||
| + | |||
| + | Also you can create your own: | ||
| + | <code cpp> | ||
| + | of3dPrimitive primitive; | ||
| + | |||
| + | // ofApp.cpp | ||
| + | |||
| + | void ofApp::setup(){ | ||
| + | primitive.getMesh().addVertex(ofVec3f(20,20)); | ||
| + | primitive.getMesh().addVertex(ofVec3f(40,20)); | ||
| + | primitive.getMesh().addVertex(ofVec3f(40,40)); | ||
| + | primitive.getMesh().addVertex(ofVec3f(20,40)); | ||
| + | primitive.getMesh().setMode(OF_PRIMITIVE_TRIANGLE_FAN); | ||
| + | } | ||
| + | |||
| + | void ofApp::update(){ | ||
| + | primitive.move(ofVec3f(10,0,0)); | ||
| + | } | ||
| + | |||
| + | void ofApp::draw(){ | ||
| + | primitive.draw(); | ||
| + | } | ||
| + | </code> | ||