Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1737 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  donner des paramètres à CG ( en openGL )

 


 Mot :   Pseudo :  
 
 Page :   1  2
Page Précédente
Auteur Sujet :

donner des paramètres à CG ( en openGL )

n°1474137
Amonchakai
Posté le 12-11-2006 à 12:10:23  profilanswer
 

Bonjour !
   Je travaille actuellement sur mon moteur 3D perso. Alors actuellement je viens de finir la première partie de l'animation Skeletal de mes mesh (ça marche...) . Mais voilà maintenant je ne veut plus toucher a mes vertices & normals dans mon programme. Je veut passer par CG pour que ce soit la carte graphique qui s'en occupe. Et là j'ai un petit soucis avec CG. Dans un premier temp je veut juste changer la couleur de ma mesh : la faire passer de blanc à rouge.  
voilà ce que je fait :

Code :
  1. void OGLRender::LoadCgProgram(const std::string fileName)
  2. {
  3. cgContext = cgCreateContext();
  4. cgProgram = cgCreateProgramFromFile(cgContext, CG_SOURCE, fileName.data(), CG_PROFILE_ARBVP1, "main", NULL);
  5.     cgGLLoadProgram(cgProgram);
  6.     cgParameter = cgGetNamedParameter(cgProgram, "Position" );
  7. }
  8. void OGLRender::CgPaintMesh(MeshToDisplay *ptr)
  9. {
  10. if(!ptr->inBuffer)
  11. {
  12.  MessageBox(hwnd, "Attention la mesh n'a pas été stockée dans le VB...","Erreur.",MB_OK);
  13.  return;
  14. }
  15. cgGLBindProgram(cgProgram);
  16. cgGLEnableProfile(CG_PROFILE_ARBVP1);
  17. glBindBufferARB(GL_ARRAY_BUFFER, ptr->buffer);         //we select the CVertex buffer
  18. glVertexPointer(3, GL_FLOAT, 8*sizeof(float), BUFFER_OFFSET(0));    //8*sizeof(float) is the size beteen two texture data
  19. 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
  20. glTexCoordPointer(2, GL_FLOAT, 8*sizeof(float), BUFFER_OFFSET(6*sizeof(float)));
  21. cgGLEnableClientState(cgParameter);
  22.     cgGLSetParameterPointer(cgParameter, 3, GL_FLOAT, 8*sizeof(float), BUFFER_OFFSET(0)); //we send the vertex to the cg program
  23. glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, ptr->indexBuffer);   //we bind the indexBuffer
  24. glEnableClientState(GL_VERTEX_ARRAY);
  25. glEnableClientState(GL_NORMAL_ARRAY);
  26. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  27. glDrawElements(GL_TRIANGLES, ptr->index.size(), GL_UNSIGNED_SHORT, 0);  //display
  28. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  29. glDisableClientState(GL_NORMAL_ARRAY);
  30. glDisableClientState(GL_VERTEX_ARRAY);
  31. cgGLDisableClientState(cgParameter);
  32. }


mon programme cg :

Code :
  1. struct OUT
  2. {
  3.    float4 Position : POSITION;
  4.    float4 Color : COLOR;
  5. };
  6. OUT main(float3 Position : POSITION)
  7. {
  8.    OUT o;
  9.    o.Position = float4(Position, 1);
  10.    o.Color = float4(1, 0, 0, 0);
  11.    return o;
  12. }


 
Bon alors, le problème ce n'est pas que mon modèle qui deviens rouge, mais tout l'écran... Alors j'ai récupéré les erreur que cg renvoie et la il me dit "invalid parameter handle" au sujet de la ligne cgGLSetParameterPointer() . (pas d'erreur pour tout le reste). Et la je vois pas trop...
 
Si vous avez une idée...
Merci :)


Message édité par Amonchakai le 12-11-2006 à 12:19:55
mood
Publicité
Posté le 12-11-2006 à 12:10:23  profilanswer
 

n°1474139
Amonchakai
Posté le 12-11-2006 à 12:19:10  profilanswer
 

heu désolé... en relisant mon post, j'ai vu l'érreur...
j'avais oublié d'écrire : cgParameter = cgGetNamedParameter(cgProgram, "Position" );
je suis trop nul...  :pfff:  
 
bon par contre j'ai toujours mon écran rouge... si vous avez une idée.
 
(et encore désolé pour la première question...)


Message édité par Amonchakai le 12-11-2006 à 12:20:42
n°1474292
IrmatDen
Posté le 13-11-2006 à 00:05:12  profilanswer
 

Salut,
 
Il ne faut pas setter le paramètre position. Etant obligatoire, le fait d'utiliser la sémantique POSITION fait qu'il va automatiquement la chercher dans le registre matériel dédié. Tu n'as aucun paramètre dans le programme actuel que tu doives modifier en code.


---------------
.
n°1474312
Amonchakai
Posté le 13-11-2006 à 08:39:26  profilanswer
 

Salut,
 
   Tout d'abord merci de ta réponse !
   Mais j'avoue ne pas avoir compris ta réponse... Je vais relire le chapitre de mon livre sur CG qui parlait de ça. Il y a un truc auquel j'ai du passer a côté. J'ai fait un fragment program qui fait la même chose, et là ça marche... mais j'avoue ne pas comprendre pourquoi le vertex program ne marche pas (par ce que dans les exemples du livre ils faisaient bien ça...). je relis le chapitre en question, et peut être que cette fois-ci je comprendrais.
 
Merci a toi de m'avoir répondu !

n°1474746
Amonchakai
Posté le 13-11-2006 à 17:05:27  profilanswer
 

Salut !
 
   Bon, j'ai potassé mon livre ça ma permis de remettre mes idées au clair sur les différentes étapes qui ont lieu dans la graphic pipeline...
   Donc si je comprend bien ce que tu me dit, c'est que comme j'écrit un vertex program, le fait de donner les positions des vertices est obligatoire (puisque vertex program...) donc je n'ais pas à le faire manuellement via des cgGetNamedParameter(), puisque de lui même il va prendre les positions dont il a besoin pour mon programme CG. C'est bien ça ?
   
   Donc en partant de ce principe, j'ai retiré tout ce qui avait rapport aux paramètres. Et au final, j'ai toujours le même problème... (écran tout rouge) J'ai particulièrement les boules car je sais que si je fait un fragment program qui fait la même chose, ça marche (seul me modèle est rouge). Mais le truc, c'est que pour ce que je veut faire (l'animation) je vais impérativement avoir besoin que ce programme se déroule au niveau des vertices et non des fragments.
 
   Si tu as une idée... (ou du moins me confirmer si j'ai bien compris ce que tu as dit...)
 
Merci de te pencher sur mon problème !  :)

n°1474766
IrmatDen
Posté le 13-11-2006 à 17:16:35  profilanswer
 

Bon, j'aurais espéré que le résultat était un effet de bord :D
 
La seule autre solution que j'imagine là, c'est de transformer tes sommets par la matrice de modelview. Ce n'est pas démontré dans les tout premiers tutos, mais c'est nécessaire par la suite pour garder la relation entre le modèle et l'orientation/position/taille du monde.
 
J'imagine que c'est dans ton bouquin, mais au cas où, voici un autre lien où c'est expliqué.
 
Et si ce n'est pas ça, je vois plus trop après :/
(Tu ne nettoierais pas ton écran en rouge à tout hasard?? :D)
 
Edit: et c'est effectivement ça, ou du moins ce que j'en ai compris/observé aussi, au sujet des vertices que l'on ne passe pas au shader.


Message édité par IrmatDen le 13-11-2006 à 17:17:58
n°1474782
Amonchakai
Posté le 13-11-2006 à 17:37:19  profilanswer
 

  ok, je viens de vérifier : je nettoie pas l'écran en rouge  :D  (on sais jamais, valait mieux vérifier...)
 
   Bon, je vais regarder du côté de la matrice modelView. (et bien vu NeHe, j'avais oublié de regarder par là...)
 
   Merci :)

n°1475457
Amonchakai
Posté le 14-11-2006 à 21:48:19  profilanswer
 

Salut !
   Bon et bien j'avance a petit pas... déjà j'ai plus mon écran rouge depuis que j'ai rajouté la multiplication par la modelView. Maintenant j'ai juste droit à l'écran noir... (j'ai bien vérifié que mon code compile via cgc...)
 
donc voilà a quoi resssemble mon prog cg actuel :

Code :
  1. struct OUT
  2. {
  3.    float4 Position : POSITION;
  4.    float4 Color : COLOR;
  5. };
  6. OUT main(float4 pos : POSITION, uniform float4x4 matrixModelViewProj)
  7. {
  8.    OUT o;
  9.    o.Color = float4(1, 0, 0, 1);
  10.    o.Position = mul(matrixModelViewProj, pos);
  11.    return o;
  12. }


 
ce qui est entre guillemet "marrant" c'est que tu as bien raison sur le fait que si je renvois la postion tout de suite, j'ai le droit a l'écran rouge...
Donc sinon je me suis dit qu'il y avait peut-être une histoire avec la position du modèle :  en effet si je ne fais pas de translation mon modèle n'est pas dans le champ de vue. J'ai donc essayé de voir si ce n'était pas une histoire de ce genre en faisant ça :  

Code :
  1. struct OUT
  2. {
  3.    float4 Position : POSITION;
  4.    float4 Color : COLOR;
  5. };
  6. OUT main(float4 pos : POSITION, uniform float4x4 matrixModelViewProj)
  7. {
  8.    OUT o;
  9.    o.Color = float4(1, 0, 0, 1);
  10.    o.Position = mul(matrixModelViewProj, pos);
  11.    o.Position += matrixModelViewProj[0][3];
  12.    o.Position += matrixModelViewProj[1][3];
  13.    o.Position += matrixModelViewProj[2][3];
  14.    return o;
  15. }


 
histoire de rajouter la position du centre du repère après translation. Mais non, ça marche pas...
 
Si quelqu'un a une idée...
Merci :)

n°1475531
IrmatDen
Posté le 15-11-2006 à 00:31:09  profilanswer
 

Côté VS, je pense pas qu'il y ait quoi que ce soit de faux maintenant (dans la première version, pour la 2nde, je n'ai jamais testé).
 
J'imagine que ça reste tout de même une histoire de translation/échelle?
On n'obtient de toute évidence pas un écran noir quand le modèle est visible :D
Le code de dessin a-t-il changé? Dans celui du premier post, tu ne déplaces pas ton entité (ni n'y applique aucune transformation en fait).
Où se trouve la caméra? Peux-tu peut-être poster le code d'update de la scène/affichage stp? (avec quelques mots pour situer le rôle que tu assignes à chacun si nécessaire ;) )
 
Edit: Je reviens sur le VS en fait :sweat:  
Ne faudrait-il pas utiliser COLOR0 au lieu de COLOR pour la sémantique de OUT.color ?


Message édité par IrmatDen le 15-11-2006 à 00:35:57

---------------
.
n°1475550
Amonchakai
Posté le 15-11-2006 à 09:02:44  profilanswer
 

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 :
  1. #include <Cg/cg.h>
  2. #include <Cg/cgGL.h>
  3. #include "Render.h"
  4. #include "OGLExtensions.h"
  5. #define BUFFER_OFFSET(i) ((char*)NULL + (i))
  6. class OGLRender : public Render
  7. {
  8. protected:
  9. virtual void ResizeScene(int width, int height);
  10. virtual bool Initialise(HWND hwnd);
  11. virtual void BeginScene();
  12. virtual void EndScene();
  13. virtual void ConfigureEclairage(Lights &lampe);
  14. public:
  15. static CGparameter cgParameter;   //shaders...
  16. static CGcontext cgContext;
  17. static CGprogram cgProgram;
  18. static CGerror error;
  19. OGLRender(Screen &ecran, HINSTANCE hInst) : Render(ecran, hInst){};
  20. virtual ~OGLRender(){};
  21. virtual void LoadExtension(const std::string s);
  22. virtual bool Init3D();
  23. virtual void Paint();
  24. virtual void setMaterials(float *ambient, float *diffuse, float *specular, float *emissive, float radiosity);
  25. virtual void StoreMesh(MeshToDisplay *ptr);  //graphic interface
  26. virtual void PaintMesh(MeshToDisplay *ptr);
  27. virtual void ReleaseMesh(MeshToDisplay *ptr);
  28. virtual void LoadCgProgram(const std::string fileName);
  29. virtual void CgSetNameParameter(const std::string nameParam);
  30. virtual void CgStoreMesh(MeshToDisplay *ptr, std::vector<float> *matrix);     //VBO with cg
  31. virtual void CgPaintMesh(MeshToDisplay *ptr);
  32. virtual void CgReleaseMesh(MeshToDisplay *ptr);
  33. };
  34. #endif


pour les implémentation on a ça :  

Code :
  1. void OGLRender::LoadCgProgram(const std::string fileName)
  2. {
  3. cgContext = cgCreateContext();
  4. cgProgram = cgCreateProgramFromFile(cgContext, CG_SOURCE, fileName.data(), CG_PROFILE_ARBVP1, "main", NULL);
  5.     cgGLLoadProgram(cgProgram);
  6. }
  7. void OGLRender::CgSetNameParameter(const std::string nameParam)
  8. {
  9. cgParameter = cgGetNamedParameter(cgProgram, nameParam.data());     //set the parameter
  10. }
  11. void OGLRender::CgStoreMesh(MeshToDisplay *ptr, std::vector<float> *matrix)
  12. {
  13.    //it will put all matrix in a buffer
  14. }
  15. void OGLRender::CgPaintMesh(MeshToDisplay *ptr)
  16. {
  17. if(!ptr->inBuffer)
  18. {
  19.  MessageBox(hwnd, "Attention la mesh n'a pas été stockée dans le VB...","Erreur.",MB_OK);
  20.  return;
  21. }
  22. cgGLEnableProfile(CG_PROFILE_ARBVP1);           //select the cg profile
  23. cgGLBindProgram(cgProgram);              //run the cg program
  24. glBindBufferARB(GL_ARRAY_BUFFER, ptr->buffer);         //we select the CVertex buffer
  25. glVertexPointer(3, GL_FLOAT, 8*sizeof(float), BUFFER_OFFSET(0));    //8*sizeof(float) is the size beteen two texture data
  26. 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
  27. glTexCoordPointer(2, GL_FLOAT, 8*sizeof(float), BUFFER_OFFSET(6*sizeof(float)));
  28. cgGLSetStateMatrixParameter(cgParameter, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY);  //send the modelView Matrix
  29. glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, ptr->indexBuffer);      //we bind the indexBuffer
  30. glEnableClientState(GL_VERTEX_ARRAY);
  31. glEnableClientState(GL_NORMAL_ARRAY);
  32. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  33. glDrawElements(GL_TRIANGLES, ptr->index.size(), GL_UNSIGNED_SHORT, 0);  //display
  34. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  35. glDisableClientState(GL_NORMAL_ARRAY);
  36. glDisableClientState(GL_VERTEX_ARRAY);
  37. }
  38. void OGLRender::CgReleaseMesh(MeshToDisplay *ptr)
  39. {
  40. //will release the matrix's buffer
  41. }


 
Maintenant pour ce que est de l'appel des méthodes de OGLRender, j'ai une classe ModelInstance qui ressemble a ça :

Code :
  1. #ifndef _ModelInstance_
  2. #define _ModelInstance_
  3. #include <boost/shared_ptr.hpp>
  4. #include "Model.h"
  5. #include "OGLRender.h"
  6. #include "TextureLoader.h"
  7. #include "ModelCollection.h"
  8. #include "TextureCollection.h"
  9. #include "ModelLoader.h"
  10. #include "Texture.h"
  11. class ModelInstance
  12. {
  13. protected:
  14. static ModelCollection modelCollection;
  15. static TextureCollection *textureCollection;
  16. static boost::shared_ptr<Render> render;
  17. static ModelLoader loader;
  18. static TextureLoader *textureLoader;
  19. static int countInstance;
  20. boost::shared_ptr<Model> model;
  21. bool load;
  22. public:
  23. ModelInstance(const std::string fileName);
  24. virtual ~ModelInstance();
  25. static void Init(Render *render, TextureLoader *textLoader);
  26. virtual void Display();
  27. virtual void StoreInBuffers();
  28. virtual void ReleaseBuffers();
  29. };
  30. #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 :
  1. #ifndef _DynamicInstance_
  2. #define _DynamicInstance_
  3. #include "ModelInstance.h"
  4. #include <boost/timer.hpp>
  5. #define PI 3.141592653
  6. class DynamicInstance : public ModelInstance
  7. {
  8. boost::timer time;
  9. public:
  10. DynamicInstance(const std::string fileName);
  11. void computeMatrix(std::vector<Joint> &tabJoint, int jointIndex, float t);
  12. void play();
  13. void initCg();
  14. virtual void Display();
  15. virtual void StoreInBuffers();
  16. virtual void ReleaseBuffers();
  17. };
  18. #endif


et les implémentation des affichages :

Code :
  1. void DynamicInstance::play()
  2. {
  3. ReleaseBuffers();
  4. float t = time.elapsed()/10000.0f;
  5. glPushMatrix();
  6. glLoadIdentity();
  7. computeMatrix(model->animations.at(0).joints, 0, t);
  8. Sleep(100);
  9. glPopMatrix();
  10. /*  
  11. for(int i = 0 ; i < model->donnee_Array.size() ; i++)
  12.  for(int j = 0 ; j < model->donnee_Array.at(i).data.size() ; j++)
  13.  {
  14.   float *m = model->animations.at(0).joints.at(model->donnee_Array.at(i).boneIndex.at(j)).mat_absolute;
  15.   float x, y, z, nx, ny, nz;
  16.   x = model->donnee_Array.at(i).data.at(j).x;
  17.   y = model->donnee_Array.at(i).data.at(j).y;
  18.   z = model->donnee_Array.at(i).data.at(j).z;
  19.   nx = model->donnee_Array.at(i).data.at(j).nx;
  20.   ny = model->donnee_Array.at(i).data.at(j).ny;
  21.   nz = model->donnee_Array.at(i).data.at(j).nz;
  22.   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];
  23.   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];
  24.   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];
  25.   model->donnee_Array.at(i).data.at(j).nx = (nx)*m[0]+(ny)*m[4]+(nz)*m[8];
  26.   model->donnee_Array.at(i).data.at(j).ny = (nx)*m[1]+(ny)*m[5]+(nz)*m[9];
  27.   model->donnee_Array.at(i).data.at(j).nz = (nx)*m[2]+(ny)*m[6]+(nz)*m[10];
  28.  }*/
  29. StoreInBuffers();
  30. Display();
  31. }
  32. void DynamicInstance::initCg()
  33. {
  34. render->LoadCgProgram("data/anim.txt" );
  35. render->CgSetNameParameter("matrixModelView" );
  36. }
  37. void DynamicInstance::StoreInBuffers()
  38. {
  39. if(!load)
  40.  return;
  41. for(int i = 0 ; i < model->donnee_Array.size() ; i++)
  42. {
  43.  std::vector<float> matrix;
  44.  matrix.reserve(model->donnee_Array.at(i).data.size()*16);
  45.  for(int j = 0 ; j < model->donnee_Array.at(i).data.size() ; j++)
  46.   for(int k = 0 ; k < 16 ; k++)
  47.    matrix.push_back(model->animations.at(0).joints.at(model->donnee_Array.at(i).boneIndex.at(j)).mat_absolute[k]);
  48.  ModelInstance::render->CgReleaseMesh(&model->donnee_Array.at(i));
  49.  ModelInstance::render->CgStoreMesh(&model->donnee_Array.at(i), &matrix);
  50.  ModelInstance::render->StoreMesh(&model->donnee_Array.at(i));
  51. }
  52. }
  53. void DynamicInstance::Display()
  54. {
  55. if(!load)
  56.  return;
  57. int prevTextIndex = -1;
  58. prevTextIndex = model->donnee_Array.at(0).matIndex;           //store the index of the first texture used
  59. if(prevTextIndex >= 0)
  60.  textureLoader->bindTexture(model->donnee_Array.at(0).texture);
  61. for(int i = 0 ; i < model->donnee_Array.size() ; i++)
  62. {
  63.  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.
  64.  {
  65.   prevTextIndex = model->donnee_Array.at(i).matIndex;
  66.   ModelInstance::render->setMaterials(model->material.at(prevTextIndex).m_ambient,
  67.    model->material.at(prevTextIndex).m_diffuse,
  68.    model->material.at(prevTextIndex).m_specular,
  69.    model->material.at(prevTextIndex).m_emissive,
  70.    model->material.at(prevTextIndex).m_luminosite);
  71.   textureLoader->bindTexture(model->donnee_Array.at(i).texture);
  72.  }
  73.  ModelInstance::render->CgPaintMesh(&model->donnee_Array.at(i));
  74. }
  75. }
  76. void DynamicInstance::ReleaseBuffers()
  77. {
  78. if(load)
  79. {
  80.  for(int i = 0 ; i < model->donnee_Array.size() ; i++)
  81.  {
  82.   ModelInstance::render->CgReleaseMesh(&model->donnee_Array.at(i));
  83.   ModelInstance::render->ReleaseMesh(&model->donnee_Array.at(i));
  84.  }
  85. }
  86. }


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 :D)...
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 :
  1. #ifndef _Model_
  2. #define _Model_
  3. #include <vector>
  4. #include <string>
  5. #include <boost/noncopyable.hpp>
  6. #include <boost/shared_ptr.hpp>
  7. #include <fstream>
  8. #include "Texture.h"
  9. struct CVertex
  10. {
  11. float x, y, z,
  12.    nx, ny, nz,
  13.    u, v;
  14. };
  15. struct Joint
  16. {
  17. float localRotation[3];
  18. float localTranslation[3];
  19. float mat_absolute[16];
  20. float mat_relative[16];
  21. int   numRotationKeyframes;
  22. int   numTranslationKeyframes;
  23. std::vector<Keyframe> pTranslationKeyframes;
  24. std::vector<Keyframe> pRotationKeyframes;
  25. int   currentTranslationKeyframe;
  26. int   currentRotationKeyframe;
  27. float mat_final[16];
  28. int   parent;
  29. std::vector<int> child;
  30. };
  31. struct MeshToDisplay
  32. {
  33. std::vector<CVertex> data;
  34. std::vector<unsigned short> index;
  35. std::vector<short> boneIndex;
  36. boost::shared_ptr<Texture> texture;
  37. int matIndex;
  38. bool inBuffer;      //flag that indiquate that the mesh is store in a vertex buffer
  39. unsigned int buffer;
  40. unsigned int indexBuffer;
  41. unsigned int matrixBuffer;
  42. };
  43. struct Animation
  44. {
  45. float totalTime;
  46. std::vector<Joint> joints;
  47. };
  48. class Model : boost::noncopyable
  49. {
  50. public:
  51. ~Model();
  52. std::vector<MeshToDisplay> donnee_Array;
  53. std::vector<Material> material;
  54. std::vector<Animation> animations;
  55. int playAnimNumber;
  56. };
  57. #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... :D) qui hérite de la classe OGLRender qui donne ça :
 

Code :
  1. #ifndef _Sonic_
  2. #define _Sonic_
  3. #include <string>
  4. #include <boost/lexical_cast.hpp>
  5. #include "OGLRender.h"
  6. #include "OGLTextureLoader.h"
  7. #include "DynamicInstance.h"
  8. class Sonic : public OGLRender
  9. {
  10. float LightAmbient[4];
  11. float LightDiffuse[4];
  12. float LightPosition[4];
  13. DynamicInstance *model2;
  14. ModelInstance *model;
  15. public:
  16. Sonic(Screen &ecran, HINSTANCE hInst) : OGLRender(ecran, hInst) {};
  17. virtual void Paint();
  18. virtual bool Init3D();
  19. };
  20. #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 :
  1. #include "Sonic.h"
  2. struct
  3. {
  4. __int64 frequency;
  5. float resolution;
  6. __int64 start;
  7. __int64 elapsed;
  8. }timer;
  9. void Sonic::Paint()
  10. {
  11. /*calcul de fps...*/
  12. __int64 time;
  13. glLoadIdentity();
  14. std::string s;
  15. QueryPerformanceCounter((LARGE_INTEGER *)&time);
  16. fps = 1.0/((time-timer.start)*timer.resolution);
  17. timer.start = time;
  18. /*fin de calcul de fps..*/
  19. // s = "FPS : "+boost::lexical_cast<std::string>(fps);  
  20. // TextOut(hDC, 10, 10, s.data(), s.length()-1);
  21. glTranslatef(-3.f,-100.f,-100.f);
  22. glTranslatef(0.f,+90.f,-20.f);
  23. glRotatef(45,0,1,0);
  24. model2->play();
  25. }
  26. bool Sonic::Init3D()
  27. {
  28. /*initialisation du calcul de fps..*/
  29. memset(&timer, 0, sizeof(timer));
  30. QueryPerformanceFrequency((LARGE_INTEGER *)&timer.frequency);
  31. QueryPerformanceCounter((LARGE_INTEGER *)&timer.start);
  32. timer.resolution = (1.0f)/timer.frequency;
  33. /*fin d'initialisation...*/
  34. SetBkMode(hDC, TRANSPARENT);
  35. SetTextColor(hDC, 0x000000FF);
  36. ModelInstance::Init(this, new OGLTextureLoader());
  37. model2 = new DynamicInstance("data/cylindre.xero3D" );
  38. model2->initCg();
  39. LightAmbient[0] = 0.5f;
  40. LightAmbient[1] = 0.5f;
  41. LightAmbient[2] = 0.5f;
  42. LightAmbient[3] = 1.0f;
  43. LightDiffuse[0] = 1.0f;
  44. LightDiffuse[1] = 1.0f;
  45. LightDiffuse[2] = 1.0f;
  46. LightDiffuse[3] = 1.0f;
  47. LightPosition[0] = 0.0f;
  48. LightPosition[1] = 0.0f;
  49. LightPosition[2] = 2.0f;
  50. LightPosition[3] = 1.0f;
  51. Lights lampe(LightAmbient, LightDiffuse, LightPosition);
  52. lumieres.push_back(lampe);
  53. glEnable(GL_TEXTURE_2D);
  54.     glShadeModel(GL_SMOOTH);
  55.     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
  56.     glClearDepth(1.0f);
  57. glEnable(GL_DEPTH_TEST);
  58. glDepthFunc(GL_LEQUAL);
  59. glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  60.     return true;
  61. }


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 :
  1. #include "Sonic.h"
  2. int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  3. {
  4. Screen ecran;
  5. ecran.angleDeVue = 45;
  6. ecran.clipping = 1000;
  7. ecran.distance=0.1;
  8. ecran.nCmdShow=nCmdShow;
  9. ecran.xSize=800;
  10. ecran.ySize=600;
  11. Sonic SonicRender(ecran, hInst);
  12. SonicRender.Run();
  13. return 0;
  14. }


et ça marchait jusqu'au shaders...
 
( je pense que là j'ai fait le post le plus long du monde :D )

mood
Publicité
Posté le 15-11-2006 à 09:02:44  profilanswer
 

n°1475562
_darkalt3_
Proctopathe
Posté le 15-11-2006 à 09:22:46  profilanswer
 

[:drapal]

n°1475931
bjone
Insert booze to continue
Posté le 15-11-2006 à 16:21:49  profilanswer
 

bin ça progresse à ce que je vois :D
 
bon j'ai un peu de mal à voir ton problème (là pour le coup :/).
 
par contre quelques petites remarques de principe:
 
- "const std::string fileName" à remplaçer par "const std::string &fileName"
 
- les .at() à la limite fait un alias style:
 
const classe_material &Mat = model->material.at(prevTextIndex);
 
comme ça le test des bornes n'est fait qu'une seule fois.  
plus économique et plus lisible lors de l'appel de setMaterials().
 
ndlr, peut être placer plus de try/catchs proche des zones d'exception, mais bon personnellement je préfèrerai vérifier les "données" au moment de leur "assimilation" (lecture disque etc...), que d'avoir des tonnes de vérifications à l'éxécution temps réel.
 
genre quand tu charges le modèle depuis le disque, tu vérifies la cohérences des données et des dépendances, comme ça en principe pas besoin de tout vérifier à chaque fois.
 
- évite le franglais:   Sonic SonicRender(ecran, hInst);
 
- classes & instances un peu plus explicites:
   DynamicInstance *model2;  
   ModelInstance *model;
 
- le type _int64 doit être dégageable par le type "long long"


Message édité par bjone le 15-11-2006 à 16:25:01
n°1475993
IrmatDen
Posté le 15-11-2006 à 18:00:14  profilanswer
 

Désolé, je vois pas là :(
 
Si tu es d'accord, j'aimerais bien jeter un oeil aux sources, si tu peux mettre ça en ligne (sources+données, bref, près à compiler et tourner :) ).

n°1476009
Amonchakai
Posté le 15-11-2006 à 18:37:59  profilanswer
 

>bjone
   
   Salut !
   
   Oui, c'est vrai que ça avance bien : je me fais bien plaisir :) (sauf quand ça marche pas...). Donc je prend bien noté les améliorations à faire. Le coup des .at() ça va être marrant : plein de lignes à changer...
   Pour ce qui est du franglais, j'avais pourtant fait des efforts  :D ... mais il y en a quelques un qui m'ont échappés... :p  
   Une petie question : c'est quoi le problème avec __int64 ? je veu bien mettre des long long à la place, mais pourquoi ? problème de portabilité ? (visual avait l'air de le reconnaitre comme un type standard donc je ne pensais pas qu'il pouvait poser problème...)
 
   Toujours est-il Merci de m'avoir signalé les trucs que tu trouve pas beau !  :jap:  
 
>IrmatDen
 
   Salut !
 
   Pas de problème, je veut bien poster mon projet prêt à compiler. Comme j'ai déjà posté presque toute les lignes de code, je vois pas ce que je pourrais vouloir cacher :D. Il me faut juste le temp de trouver le moyen de d'hoster l'archive .rar en question. (pour le moment je connais juste des host d'images gratuits). Des que j'ai trouvé je te l'envois.

n°1476012
IrmatDen
Posté le 15-11-2006 à 18:59:57  profilanswer
 

Amonchakai a écrit :

Il me faut juste le temp de trouver le moyen de d'hoster l'archive .rar en question. (pour le moment je connais juste des host d'images gratuits). Des que j'ai trouvé je te l'envois.


Megaupload fonctionne pas mal; même s'il faut patienter, y'a des pubs etc... C'est gratuit :)

n°1476023
bjone
Insert booze to continue
Posté le 15-11-2006 à 19:54:28  profilanswer
 

Amonchakai a écrit :

>bjone
   
   Salut !
   
   Oui, c'est vrai que ça avance bien : je me fais bien plaisir :) (sauf quand ça marche pas...). Donc je prend bien noté les améliorations à faire. Le coup des .at() ça va être marrant : plein de lignes à changer...
   Pour ce qui est du franglais, j'avais pourtant fait des efforts  :D ... mais il y en a quelques un qui m'ont échappés... :p  
   Une petie question : c'est quoi le problème avec __int64 ? je veu bien mettre des long long à la place, mais pourquoi ? problème de portabilité ? (visual avait l'air de le reconnaitre comme un type standard donc je ne pensais pas qu'il pouvait poser problème...)
 
   Toujours est-il Merci de m'avoir signalé les trucs que tu trouve pas beau !  :jap:  


 
__int64 me fait penser à un hack propriétaire.
 
"long long" viens du C99 si je ne m'abuse (bon okay c'est pas du C++ le C99), mais bon en plus je trouves le type "long long" plus homogène vis à vis des autres types de base.

n°1476027
Amonchakai
Posté le 15-11-2006 à 20:15:10  profilanswer
 

ok, merci !
  mais voilà, je comprend pas comment il marche (oui, je sais là je suis un gros boulet....) donc j'ai uploadé le truc et j'arrive a ça :
http://www.megaupload.com/fr/?d=QB51GL8L
et là je vois pas où je récupère l'adresse de ce que j'ai envoyé... Si tu trouve, ben tant mieux :D
je vais continuer a chercher voir aller chercher un autre ébergeur...

n°1476029
IrmatDen
Posté le 15-11-2006 à 20:24:27  profilanswer
 

C'est exactement ce lien, pas besoin de chercher plus loin :D
J'y jetterais un oeil en rentrant ce soir.

n°1476034
Amonchakai
Posté le 15-11-2006 à 20:29:06  profilanswer
 

ok, en fait ça y est j'ai compris comment on télécharge ensuite... :D  
 
Merci a toi pour ton aide :jap:

n°1476036
Amonchakai
Posté le 15-11-2006 à 20:31:39  profilanswer
 

bjone a écrit :

__int64 me fait penser à un hack propriétaire.
 
"long long" viens du C99 si je ne m'abuse (bon okay c'est pas du C++ le C99), mais bon en plus je trouves le type "long long" plus homogène vis à vis des autres types de base.


 
ok, merci pour cette précision :) donc va pour long long

n°1476038
bjone
Insert booze to continue
Posté le 15-11-2006 à 20:33:42  profilanswer
 

là c'est plus du feeling :/

n°1476042
Amonchakai
Posté le 15-11-2006 à 20:39:57  profilanswer
 

oui, mais je pense que tu doit pas être bien loin car quand je regarde winNT.h on trouve ça : typedef __int64 LONGLONG; donc je pense que ça doit pas loin du long long. Et c'est vrai que dans tous les livres que j'ai lu j'ai pas  vu de __int64. Donc je vais faire comme tu dit et prendre un long long.


Message édité par Amonchakai le 15-11-2006 à 20:40:36
n°1476101
IrmatDen
Posté le 15-11-2006 à 22:41:29  profilanswer
 

Tout va bien au final :D
Ca marche nickel sur mon poste (j'ai rendu vert au lieu de rouge pour vérifier) ;)
 
Essaie voir un rebuild all, tu dois avoir quelque chose de foiré qui traîne, parce que c'est tout bon :)
 
Par contre, une petite remarque au passage: dans les profils debug, évite de désactiver les infos de debug et d'activer les optims, ça, c'est le boulot du profil release.


---------------
.
n°1476110
Amonchakai
Posté le 15-11-2006 à 23:33:48  profilanswer
 

tu dit que tu n'as pas touché au code et ça marche...  :??:  
j'ai fait un "rebuild solution" et ça change rien... je vois pas le model : l'écran est désespérément noir....
 
tu croit que c'est ma carte graphique une Radeon X700m 128Mo sur PCI Express elle doit être capable de gérer ça non ? (surtout que le fragment program marche...)
 
mais u dit que tu as rien touché ?

n°1476115
IrmatDen
Posté le 16-11-2006 à 00:16:30  profilanswer
 

Rien du tout :/
Tu peux toujours essayer en crééant une nouvelle solution. Juste à tout hasard...
 
Par contre, tu n'as pas parlé de fragment shader jusqu'ici, ni dans l'archive. Réessaie en le virant éventuellement.
 
Et pour ta CG, rassures-toi, c'est pas ça qui va la mettre à genoux :D


---------------
.
n°1476455
Amonchakai
Posté le 16-11-2006 à 14:53:11  profilanswer
 

ça y est, je commence a arriver au bout de mon problème : j'ai essayé de lancer mon exécutable sur les portables de mes copains et ho miracle, ça marche chez tout le monde ! Sauf chez moi  :D  là c'est un comble...
   Donc il me reste plus qu'a mettre a jour toutes mes dll relative a openGL, mettre a jour les drivers de ma carte graphique et j'espère que ça marchera :)
   Par contre il y a un truc qui me fait peur c'est que j'ai un copain qui a plusieurs OS sur son portable et sous Vista, pas moyen de faire fonctionner les extensions ARB  :fou: .... donc pas de vertex buffers en openGL.... Heu, il y a un soucis dut au fait que vista est en version béta pour le moment ou tout ce que je fais ça sera plus utilisable quand les gens seront sous Vista ?

n°1476475
bjone
Insert booze to continue
Posté le 16-11-2006 à 15:04:24  profilanswer
 

ça sera utilisable pour la finale.
 
de base Vista émule un OpenGl basique via D3D.
ensuite ATI & nVidia fournissent des drivers avec un support amélioré.
 
les betas ayant le cul entre plein de chaises, ça doit être de l'OpenGl 1.1.

n°1476478
Zeross
Posté le 16-11-2006 à 15:05:53  profilanswer
 

Amonchakai a écrit :

ça y est, je commence a arriver au bout de mon problème : j'ai essayé de lancer mon exécutable sur les portables de mes copains et ho miracle, ça marche chez tout le monde ! Sauf chez moi  :D  là c'est un comble...
   Donc il me reste plus qu'a mettre a jour toutes mes dll relative a openGL, mettre a jour les drivers de ma carte graphique et j'espère que ça marchera :)
   Par contre il y a un truc qui me fait peur c'est que j'ai un copain qui a plusieurs OS sur son portable et sous Vista, pas moyen de faire fonctionner les extensions ARB  :fou: .... donc pas de vertex buffers en openGL.... Heu, il y a un soucis dut au fait que vista est en version béta pour le moment ou tout ce que je fais ça sera plus utilisable quand les gens seront sous Vista ?


 
J'ai pas testé mais sous Vista je crois que pour l'instant ni ATI, ni NVIDIA n'ont porté leur ICD, par conséquent les applications OpenGL utilisent le wrapper fournit par Microsoft qui doit s'arrêter à OpenGL 1.4 si je ne m'abuse. A terme les ICD seront disponibles sous Vista ne t'inquiètes pas ;)
 
edit et merde grillé  :o mais c'est du 1.4 maintenant le wrapper MS a fournit un effort surhumain :D


Message édité par Zeross le 16-11-2006 à 15:06:35
n°1476479
Amonchakai
Posté le 16-11-2006 à 15:06:37  profilanswer
 

ok, merci je suis tout de suite plus rassuré. :) j'arrais été dégouté que ça marche plus sous Vista

n°1476591
bjone
Insert booze to continue
Posté le 16-11-2006 à 15:57:53  profilanswer
 

oki, en fait j'ai dis 1.1 mais j'en étais pas sûr :D


Message édité par bjone le 16-11-2006 à 15:58:05
n°1476602
Amonchakai
Posté le 16-11-2006 à 16:02:41  profilanswer
 

une petie question vous avez quoi comme version pour vos DLL ?
Moi j'ai :
opengl32.dll 5.1.2600.2180
opengl.dll 4.5.7.36
glu32.dll 4.0.336.1
 
et glut32.dll et glaux.dll qui n'ont pas ne n° de version
 
j'ai été voir les pilotes de ma carte graphique et ça ne change rien.....
 
Merci a ceux qui prendrons le temp de regarder :)

n°1476726
Amonchakai
Posté le 16-11-2006 à 17:33:31  profilanswer
 

ok, c'est bon même chez moi ça marche maintenant :)

n°1476745
IrmatDen
Posté le 16-11-2006 à 17:50:14  profilanswer
 

As-tu compris ce qui n'allait pas? C'est quoi qui foirait?

n°1476751
Amonchakai
Posté le 16-11-2006 à 18:26:04  profilanswer
 

ben, disons que ça s'est mis a marcher après avoir changé les pilotes de ma carte graphique... tout a l'heure quand je les avais changé j'avais pas réussit a trouver les dernier pilote . Le site d'ATI me donnais un petit prog qui ne voulais pas reconnaitre ma carte graphique donc je pouvais pas installer leurs drivers via ce prog. j'ai donc du chercher les driver a un autre endroit, et ceux que j'avais trouvé n'était pas les derniers...  
J'ai donc ensuite finalement réussit a trouver les derniers en date, et là ça marche niquel !
en gros le problème se trouvait au niveau des divers...
enfin toujours est-il maintenant ça marche :)   (comme quoi, quand ça marche pas c'est pas forcément ma faute :D)

n°1476754
Amonchakai
Posté le 16-11-2006 à 18:29:27  profilanswer
 

Au fait, je le redirais jamais assez. Mais MERCI de votre aide a tous ! :)

n°1478058
Amonchakai
Posté le 19-11-2006 à 12:28:25  profilanswer
 

Salut !
   De retour avec une petite question : Est ce que vous connaitreriez pas le moyen d'utiliser une sorte d'index buffer pour les paramètres de CG ?
 
   Car mon problème c'est que pour l'animation de mes personnages je ne voulais pas toucher à mes buffer qui contiennent toutes les positions, normales, coordonnée de texture,... donc pour ça je pensais passer par CG, lui envoyer les différentes matrices et qu'ensuite dans mon programme CG, je fais la multiplication de mes différentes données par les matrices. jusque là OK, mais le problème c'est qu'il est vraiment plus que dérésonable d'envoyer autant de matrices que de vertices... sachant qu'en réalité il n'existe pas plus d'une dizaine de matrice différente. Donc c'est pour ça que je cherche à trouver un index buffer pour les paramètres. Mon livre n'en parle pas et les différentes doc sur CGGL que j'ai trouvé n'en parle pas également... Pire : quand je regarde le chapitre de mon livre consacré a l'animation je vois qu'en réalité, il modifient leurs buffer toutes les t secondes avec t le temp entre deux keyframes. Oui, car eux en fait ils donne en paramètre à CG la position A ,la position B et le temp. Et ensuite il font l'interpolation entre les deux position dans le programme CG via la fonction "lerp" (pour une interpolation linéaire ). Donc en réalité, eux ils ne donnent pas les matrices... Donc c'est pour ça que je me demande si en réalité cela est est possible. D'où j'aimerais bien savoir si vous connaissez le moyen d'utilier un index buffer pour les paramètres. Sinon il va falloir que je passe comme ils font dans le livre. A savoir que je vais vider très féquament mes buffers.
 
Merci :)

Message cité 1 fois
Message édité par Amonchakai le 19-11-2006 à 12:30:24
n°1478076
IrmatDen
Posté le 19-11-2006 à 13:30:17  profilanswer
 

Salut,
 
Je suis pas sûr de bien te comprendre :D
 

Amonchakai a écrit :

Oui, car eux en fait ils donne en paramètre à CG la position A ,la position B et le temp


Là, c'est un exemple d'animation par keyframe; pas d'utilisation de tableau possible effectivement.
 

Amonchakai a écrit :

lui envoyer les différentes matrices et qu'ensuite dans mon programme CG, je fais la multiplication de mes différentes données par les matrices.


Et là, tu as l'air de parler de skinning (utilisation d'un squelette)...
Si tu utilises bien cette méthode, alors, oui, tu peux faire de l'animation par matrice.
 
Alors, tout dépend de ton choix ;)
Et c'est quoi ton bouquin?? J'ai Cg Tutorial, et y'a le chapitre Vertex Skinning qui est collé à celui des keyframes (et j'en connais pas encore vu d'autres sur Cg :))


---------------
.
n°1478083
Amonchakai
Posté le 19-11-2006 à 14:09:26  profilanswer
 

Salut !
 
   En ce qui conserne le livre on a bien le même :D celui là : http://www.amazon.fr/Cg-Tutorial-D [...] 0321194969    
 
   Donc, en fait tu as raison ;) : je me suis un peu embrouillé.
   
   Donc au final j'ai même la réponse a ma question (quand je regarde le bon paragraphe :) ) : ils envoient toutes les matrices plus un paramètre qui donne l'indice de quel matrice est utilisée. Je trouve que ça fait un peu bidoulliage mais bon... Mais ça permet de les mettre dans un même buffer, et de les envoyer via un cgGLSetParameterPointer().
 
Ok, Merci

n°1478091
bjone
Insert booze to continue
Posté le 19-11-2006 à 14:49:14  profilanswer
 

la philosophie avec une animation par bone, c'est d'avoir comme élément de chaque vertex, un tableau de 4 indices indexant les matrices influencant le vertex et les 4 flottants associés pour les poids de chaque matrice.
 
tu prends par exemple 4 entiers 8 bits, ça te donne 256 matrices différentes max par un modèle, tes N matrices utiles (pas forcément 256) sont soit placées en registre de constante, soit stoquée dans un autre VertexBuffer si tu utilises le GeometryInstancing (pas forcément remarque).

n°1478098
Amonchakai
Posté le 19-11-2006 à 15:05:41  profilanswer
 

oki, le truc c'est que pour le moment j'avais pas fait de smooth skining car mon éditeur 3D ne le suporte pas :( Donc je fais du rigid skining. Bon je pense de plus en plus a faire un exporteur pour récupérer des modèles fait sous 3DS comme ça je pourrais améliorer ce genre de trucs.


Message édité par Amonchakai le 19-11-2006 à 15:06:29
mood
Publicité
Posté le   profilanswer
 

 Page :   1  2
Page Précédente

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  donner des paramètres à CG ( en openGL )

 

Sujets relatifs
[C++ OpenGL] probleme avec les callback du glutessOpengl+Qt impossible de charger une texture
Matrices & openGLconvertir du opengl en 'off-line rendering' (povray, pbrt, pixie...)
Donner comme valeur a une variable le mot d'un fichier .txt[OpenGL] ¨Probleme pour compiler
[openGL] Rotation d'un objet face a un pointOperateur "|" dans les parametres d'une fonction
[C#] linkbutton - paramètres dans l'url ?pb de parametres en C...
Plus de sujets relatifs à : donner des paramètres à CG ( en openGL )


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR