Amonchakai | Ok, merci de t'occuper de mon cas . j'ai regardé le coup de mettre la sémantique COLOR0 et malheureusement ça ne change rien...
Pour ce qui est de mon code pour l'affichage, voilà :
j'ai tout d'abord une classe OGLRender qui hérite de la classe Render. La classe Render est une classe abstraite qui contient de façon implémenté la création d'une fenêtre win32 + traitement des messages, et des méthodes virtuelle pure pour tout ce qui conserne la 3D (j'ai l'intention de faire une implémentation directX plus tard...)
voilà le header de OGLRender :
Code :
- #include <Cg/cg.h>
- #include <Cg/cgGL.h>
- #include "Render.h"
- #include "OGLExtensions.h"
- #define BUFFER_OFFSET(i) ((char*)NULL + (i))
- class OGLRender : public Render
- {
- protected:
- virtual void ResizeScene(int width, int height);
- virtual bool Initialise(HWND hwnd);
- virtual void BeginScene();
- virtual void EndScene();
- virtual void ConfigureEclairage(Lights &lampe);
- public:
- static CGparameter cgParameter; //shaders...
- static CGcontext cgContext;
- static CGprogram cgProgram;
- static CGerror error;
- OGLRender(Screen &ecran, HINSTANCE hInst) : Render(ecran, hInst){};
- virtual ~OGLRender(){};
- virtual void LoadExtension(const std::string s);
- virtual bool Init3D();
- virtual void Paint();
- virtual void setMaterials(float *ambient, float *diffuse, float *specular, float *emissive, float radiosity);
- virtual void StoreMesh(MeshToDisplay *ptr); //graphic interface
- virtual void PaintMesh(MeshToDisplay *ptr);
- virtual void ReleaseMesh(MeshToDisplay *ptr);
- virtual void LoadCgProgram(const std::string fileName);
- virtual void CgSetNameParameter(const std::string nameParam);
- virtual void CgStoreMesh(MeshToDisplay *ptr, std::vector<float> *matrix); //VBO with cg
- virtual void CgPaintMesh(MeshToDisplay *ptr);
- virtual void CgReleaseMesh(MeshToDisplay *ptr);
- };
- #endif
|
pour les implémentation on a ça :
Code :
- void OGLRender::LoadCgProgram(const std::string fileName)
- {
- cgContext = cgCreateContext();
- cgProgram = cgCreateProgramFromFile(cgContext, CG_SOURCE, fileName.data(), CG_PROFILE_ARBVP1, "main", NULL);
- cgGLLoadProgram(cgProgram);
- }
- void OGLRender::CgSetNameParameter(const std::string nameParam)
- {
- cgParameter = cgGetNamedParameter(cgProgram, nameParam.data()); //set the parameter
- }
- void OGLRender::CgStoreMesh(MeshToDisplay *ptr, std::vector<float> *matrix)
- {
- //it will put all matrix in a buffer
- }
- void OGLRender::CgPaintMesh(MeshToDisplay *ptr)
- {
- if(!ptr->inBuffer)
- {
- MessageBox(hwnd, "Attention la mesh n'a pas été stockée dans le VB...","Erreur.",MB_OK);
- return;
- }
- cgGLEnableProfile(CG_PROFILE_ARBVP1); //select the cg profile
- cgGLBindProgram(cgProgram); //run the cg program
- glBindBufferARB(GL_ARRAY_BUFFER, ptr->buffer); //we select the CVertex buffer
- glVertexPointer(3, GL_FLOAT, 8*sizeof(float), BUFFER_OFFSET(0)); //8*sizeof(float) is the size beteen two texture data
- glNormalPointer(GL_FLOAT, 8*sizeof(float), BUFFER_OFFSET(3*sizeof(float))); //BUFFER_OFFSET(2*sizeof(float)) give information about the position of the begining of the data
- glTexCoordPointer(2, GL_FLOAT, 8*sizeof(float), BUFFER_OFFSET(6*sizeof(float)));
- cgGLSetStateMatrixParameter(cgParameter, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY); //send the modelView Matrix
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, ptr->indexBuffer); //we bind the indexBuffer
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_NORMAL_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glDrawElements(GL_TRIANGLES, ptr->index.size(), GL_UNSIGNED_SHORT, 0); //display
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- glDisableClientState(GL_NORMAL_ARRAY);
- glDisableClientState(GL_VERTEX_ARRAY);
- }
- void OGLRender::CgReleaseMesh(MeshToDisplay *ptr)
- {
- //will release the matrix's buffer
- }
|
Maintenant pour ce que est de l'appel des méthodes de OGLRender, j'ai une classe ModelInstance qui ressemble a ça :
Code :
- #ifndef _ModelInstance_
- #define _ModelInstance_
- #include <boost/shared_ptr.hpp>
- #include "Model.h"
- #include "OGLRender.h"
- #include "TextureLoader.h"
- #include "ModelCollection.h"
- #include "TextureCollection.h"
- #include "ModelLoader.h"
- #include "Texture.h"
- class ModelInstance
- {
- protected:
- static ModelCollection modelCollection;
- static TextureCollection *textureCollection;
- static boost::shared_ptr<Render> render;
- static ModelLoader loader;
- static TextureLoader *textureLoader;
- static int countInstance;
- boost::shared_ptr<Model> model;
- bool load;
- public:
- ModelInstance(const std::string fileName);
- virtual ~ModelInstance();
- static void Init(Render *render, TextureLoader *textLoader);
- virtual void Display();
- virtual void StoreInBuffers();
- virtual void ReleaseBuffers();
- };
- #endif
|
bon comme tu peut le remarquer modelInstance utilise deux classes TextureCollection et ModelCollection qui sont en fait deux classe qui héritent d'une std::map pour associer une std::string a un boost::shared_ptr sur la texture/Model. C'est là que tous mes modèles sont conservés en mémoire.
ModelLoader et TextureLoader sont comme leurs nom indique des loader qui me renvoient le smart_ptr après lecture sur un fichier (et donc le met ensuite dans les collections correspondante.)
je te donne aucunne implémentation la dessus, si tu estime avoir besoin de qqch n'hésite pas a demander
(ps : cette classe passera bientôt abstraite...)
donc ensuite j'ai ensuite deux autres classe : StaticInstance et DynamicInstance qui toutes deux héritent de ModelInstance. Et mes shaders que j'essaient de metre sont au niveau de DynamicInstance. Voilà a quoi celà ressemble :
Code :
- #ifndef _DynamicInstance_
- #define _DynamicInstance_
- #include "ModelInstance.h"
- #include <boost/timer.hpp>
- #define PI 3.141592653
- class DynamicInstance : public ModelInstance
- {
- boost::timer time;
- public:
- DynamicInstance(const std::string fileName);
- void computeMatrix(std::vector<Joint> &tabJoint, int jointIndex, float t);
- void play();
- void initCg();
- virtual void Display();
- virtual void StoreInBuffers();
- virtual void ReleaseBuffers();
- };
- #endif
|
et les implémentation des affichages :
Code :
- void DynamicInstance::play()
- {
- ReleaseBuffers();
- float t = time.elapsed()/10000.0f;
- glPushMatrix();
- glLoadIdentity();
- computeMatrix(model->animations.at(0).joints, 0, t);
- Sleep(100);
- glPopMatrix();
- /*
- for(int i = 0 ; i < model->donnee_Array.size() ; i++)
- for(int j = 0 ; j < model->donnee_Array.at(i).data.size() ; j++)
- {
- float *m = model->animations.at(0).joints.at(model->donnee_Array.at(i).boneIndex.at(j)).mat_absolute;
- float x, y, z, nx, ny, nz;
-
- x = model->donnee_Array.at(i).data.at(j).x;
- y = model->donnee_Array.at(i).data.at(j).y;
- z = model->donnee_Array.at(i).data.at(j).z;
-
- nx = model->donnee_Array.at(i).data.at(j).nx;
- ny = model->donnee_Array.at(i).data.at(j).ny;
- nz = model->donnee_Array.at(i).data.at(j).nz;
-
- model->donnee_Array.at(i).data.at(j).x = (x-m[12])*m[0]+(y-m[13])*m[4]+(z-m[14])*m[8]+m[12];
- model->donnee_Array.at(i).data.at(j).y = (x-m[12])*m[1]+(y-m[13])*m[5]+(z-m[14])*m[9]+m[13];
- model->donnee_Array.at(i).data.at(j).z = (x-m[12])*m[2]+(y-m[13])*m[6]+(z-m[14])*m[10]+m[14];
-
- model->donnee_Array.at(i).data.at(j).nx = (nx)*m[0]+(ny)*m[4]+(nz)*m[8];
- model->donnee_Array.at(i).data.at(j).ny = (nx)*m[1]+(ny)*m[5]+(nz)*m[9];
- model->donnee_Array.at(i).data.at(j).nz = (nx)*m[2]+(ny)*m[6]+(nz)*m[10];
- }*/
- StoreInBuffers();
- Display();
- }
- void DynamicInstance::initCg()
- {
- render->LoadCgProgram("data/anim.txt" );
- render->CgSetNameParameter("matrixModelView" );
- }
- void DynamicInstance::StoreInBuffers()
- {
- if(!load)
- return;
- for(int i = 0 ; i < model->donnee_Array.size() ; i++)
- {
- std::vector<float> matrix;
- matrix.reserve(model->donnee_Array.at(i).data.size()*16);
- for(int j = 0 ; j < model->donnee_Array.at(i).data.size() ; j++)
- for(int k = 0 ; k < 16 ; k++)
- matrix.push_back(model->animations.at(0).joints.at(model->donnee_Array.at(i).boneIndex.at(j)).mat_absolute[k]);
- ModelInstance::render->CgReleaseMesh(&model->donnee_Array.at(i));
- ModelInstance::render->CgStoreMesh(&model->donnee_Array.at(i), &matrix);
- ModelInstance::render->StoreMesh(&model->donnee_Array.at(i));
- }
- }
- void DynamicInstance::Display()
- {
- if(!load)
- return;
- int prevTextIndex = -1;
- prevTextIndex = model->donnee_Array.at(0).matIndex; //store the index of the first texture used
- if(prevTextIndex >= 0)
- textureLoader->bindTexture(model->donnee_Array.at(0).texture);
- for(int i = 0 ; i < model->donnee_Array.size() ; i++)
- {
- if(model->donnee_Array.at(i).matIndex != prevTextIndex && model->donnee_Array.at(i).matIndex >= 0) //if the texture is the same than the last it is no necessary to bind it.
- {
- prevTextIndex = model->donnee_Array.at(i).matIndex;
- ModelInstance::render->setMaterials(model->material.at(prevTextIndex).m_ambient,
- model->material.at(prevTextIndex).m_diffuse,
- model->material.at(prevTextIndex).m_specular,
- model->material.at(prevTextIndex).m_emissive,
- model->material.at(prevTextIndex).m_luminosite);
- textureLoader->bindTexture(model->donnee_Array.at(i).texture);
- }
- ModelInstance::render->CgPaintMesh(&model->donnee_Array.at(i));
- }
- }
- void DynamicInstance::ReleaseBuffers()
- {
- if(load)
- {
- for(int i = 0 ; i < model->donnee_Array.size() ; i++)
- {
- ModelInstance::render->CgReleaseMesh(&model->donnee_Array.at(i));
- ModelInstance::render->ReleaseMesh(&model->donnee_Array.at(i));
- }
- }
- }
|
Donc en fait tu peut remarquer que l'affichage a ce niveau consite a rappeler les methodes de OGLRender en donnant toutes les mesh du modèle. Donc ça me parrait plutôt explicite... si tu as une question (ou plus )...
La méthode computeMatrix() est une méthode récursive qui me permet de calculer toutes les matrices pour l'affichage d'un object annimé. comme tu peut voir sur la méthode Play(), j'avais juste a toucher aux postion des vertices en utilisant les matrices calculées pour réaliser mon animation.
Bon je suis en train de me dire que je t'ai pas encore donné la classe Model. Donc elle ressemble a ça :
Code :
- #ifndef _Model_
- #define _Model_
- #include <vector>
- #include <string>
- #include <boost/noncopyable.hpp>
- #include <boost/shared_ptr.hpp>
- #include <fstream>
- #include "Texture.h"
- struct CVertex
- {
- float x, y, z,
- nx, ny, nz,
- u, v;
- };
- struct Joint
- {
- float localRotation[3];
- float localTranslation[3];
- float mat_absolute[16];
- float mat_relative[16];
- int numRotationKeyframes;
- int numTranslationKeyframes;
- std::vector<Keyframe> pTranslationKeyframes;
- std::vector<Keyframe> pRotationKeyframes;
- int currentTranslationKeyframe;
- int currentRotationKeyframe;
- float mat_final[16];
- int parent;
- std::vector<int> child;
- };
- struct MeshToDisplay
- {
- std::vector<CVertex> data;
- std::vector<unsigned short> index;
- std::vector<short> boneIndex;
- boost::shared_ptr<Texture> texture;
- int matIndex;
- bool inBuffer; //flag that indiquate that the mesh is store in a vertex buffer
- unsigned int buffer;
- unsigned int indexBuffer;
- unsigned int matrixBuffer;
- };
- struct Animation
- {
- float totalTime;
- std::vector<Joint> joints;
- };
- class Model : boost::noncopyable
- {
- public:
- ~Model();
- std::vector<MeshToDisplay> donnee_Array;
- std::vector<Material> material;
- std::vector<Animation> animations;
- int playAnimNumber;
- };
- #endif
|
Bon le destructeur me sert juste a renvoyer un messsage d'erreur si un modèle est détruit alors qu'il est encore présent dans un buffer...
Bon, maintenant reste plus qu'a apeller tout ce beau monde : donc j'ai une classe Sonic (pourquoi pas... ) qui hérite de la classe OGLRender qui donne ça :
Code :
- #ifndef _Sonic_
- #define _Sonic_
- #include <string>
- #include <boost/lexical_cast.hpp>
- #include "OGLRender.h"
- #include "OGLTextureLoader.h"
- #include "DynamicInstance.h"
- class Sonic : public OGLRender
- {
- float LightAmbient[4];
- float LightDiffuse[4];
- float LightPosition[4];
- DynamicInstance *model2;
- ModelInstance *model;
- public:
- Sonic(Screen &ecran, HINSTANCE hInst) : OGLRender(ecran, hInst) {};
- virtual void Paint();
- virtual bool Init3D();
- };
- #endif
|
dans laquelle je surcharge la méthode Paint() qui définit ce qui doit être affiché. (elle est apellée dans la classe Render dans la boucle d'affichage).
donc voila les implémentations :
Code :
- #include "Sonic.h"
- struct
- {
- __int64 frequency;
- float resolution;
- __int64 start;
- __int64 elapsed;
- }timer;
- void Sonic::Paint()
- {
- /*calcul de fps...*/
- __int64 time;
- glLoadIdentity();
- std::string s;
- QueryPerformanceCounter((LARGE_INTEGER *)&time);
- fps = 1.0/((time-timer.start)*timer.resolution);
- timer.start = time;
- /*fin de calcul de fps..*/
- // s = "FPS : "+boost::lexical_cast<std::string>(fps);
- // TextOut(hDC, 10, 10, s.data(), s.length()-1);
- glTranslatef(-3.f,-100.f,-100.f);
- glTranslatef(0.f,+90.f,-20.f);
- glRotatef(45,0,1,0);
- model2->play();
- }
- bool Sonic::Init3D()
- {
- /*initialisation du calcul de fps..*/
- memset(&timer, 0, sizeof(timer));
- QueryPerformanceFrequency((LARGE_INTEGER *)&timer.frequency);
- QueryPerformanceCounter((LARGE_INTEGER *)&timer.start);
- timer.resolution = (1.0f)/timer.frequency;
- /*fin d'initialisation...*/
- SetBkMode(hDC, TRANSPARENT);
- SetTextColor(hDC, 0x000000FF);
- ModelInstance::Init(this, new OGLTextureLoader());
- model2 = new DynamicInstance("data/cylindre.xero3D" );
- model2->initCg();
- LightAmbient[0] = 0.5f;
- LightAmbient[1] = 0.5f;
- LightAmbient[2] = 0.5f;
- LightAmbient[3] = 1.0f;
- LightDiffuse[0] = 1.0f;
- LightDiffuse[1] = 1.0f;
- LightDiffuse[2] = 1.0f;
- LightDiffuse[3] = 1.0f;
- LightPosition[0] = 0.0f;
- LightPosition[1] = 0.0f;
- LightPosition[2] = 2.0f;
- LightPosition[3] = 1.0f;
- Lights lampe(LightAmbient, LightDiffuse, LightPosition);
- lumieres.push_back(lampe);
- glEnable(GL_TEXTURE_2D);
- glShadeModel(GL_SMOOTH);
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- glClearDepth(1.0f);
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_LEQUAL);
- glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
- return true;
- }
|
bon je sais j'ai mis un peu a la crade le calcul des fps... je rendrais ça plus propre après...
voili voilou, reste plus qu'a tout lancer a partir de main comme ça...
Code :
- #include "Sonic.h"
- int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
- {
- Screen ecran;
- ecran.angleDeVue = 45;
- ecran.clipping = 1000;
- ecran.distance=0.1;
- ecran.nCmdShow=nCmdShow;
- ecran.xSize=800;
- ecran.ySize=600;
- Sonic SonicRender(ecran, hInst);
- SonicRender.Run();
- return 0;
- }
|
et ça marchait jusqu'au shaders...
( je pense que là j'ai fait le post le plus long du monde ) |