HomeHome  CalendarCalendar  FAQFAQ  SearchSearch  MemberlistMemberlist  UsergroupsUsergroups  RegisterRegister  Log inLog in  

Share | 
 

 version 2 sujet à questions en vrac XD

View previous topic View next topic Go down 
Go to page : Previous  1, 2, 3, 4, 5
AuthorMessage
Darktib
Committer


Messages : 389
Date d'inscription : 2009-07-20
Localisation : A coté de Paris

PostSubject: Re: version 2 sujet à questions en vrac XD   Sat Feb 04, 2012 3:17 pm

J'ai récemment regardé le sujet des contrôleurs, et j'ai pas mal d'idées dessus, qui me paraissent pas mauvaises. Le système serait très flexible et puissant, et les attributs d'objets seraient utilisés.

Je reviens donc dessus. Actuellement, on doit faire (exemple):
Code:

SPK_START_DESCRIPTION
   SPK_PARENT_ATTRIBUTES(SPK::Emitter)
   SPK_ATTRIBUTE("radius",ATTRIBUTE_TYPE_FLOAT)
   // ...
SPK_END_DESCRIPTION

Je pense qu'il y a une ligne en trop, celle des attributs parent. Je pense qu'il serait mieux de la fusionner avec la macro SPK_START_DESCRIPTION. Du coup, la description de SPKObject sera faite manuellement (ce qui n'est pas un problème), et cela raccourcira la taille de la description dans les sous-classes. L'autre raison (la plus importante), est qu'en plus on contrôle l'ordre des attributs dans la liste, et commençant par les attributs des classes mères. Ceci est important pour avoir des perfs avec les contrôleurs : il devient alors possible de numéroter les attributs de manière fiable (et de rendre cette numérotation transparente pour l'utilisateur), par leur index dans la liste des attributs. La clef du système des contrôleurs sera la fonction:
Code:
void setAttribute(int attrNum, Variant value);
=> Pas de recherche d'attribut mais accès direct (Variant est un type que je dois encore imaginer un peu plus).

Dans la même logique, on utilise actuellement la macro SPK_IMPLEMENT_OBJECT. Pourquoi ne pas la fusionner avec SPK_START_DESCRIPTION, qui prendrait alors 2 paramètres ? Tu vas me dire que certaines classes n'ont pas de description (comme SPK::Point). Dans ce cas, le mieux serait de créer une macro SPK_NO_DESCRIPTION(classe) qui ne ferais que ce que SPK_IMPLEMENT_OBJECT fait (je pense qu'un meilleur nom de macro est possible Wink ), mais en étant plus explicite. Ainsi, l'implémentation de l'objet serait complètement transparente. Je pense qu'il est aussi possible d'adapter cette logique pour les classes à template.

______________________________________________________________________

Pour le système de contrôleurs:
On aurait des SPKObject de type "AttributeController", lesquels seraient mis à jour juste avant l'update du système. Ces objets possèderaient des connections (ie, "attributs sortants") et seraient connectés à des attributs d'autres SPKObjects, éventuellement d'autres contrôleurs. Le workflow serait le suivant:
Code:

-> system::update:
  -> AttributeController::update // Calcule les valeurs des connections
    -> setAttribute(num,value) sur les objets connectés // Met à jour les attributs cibles en fonction de la valeur de la connection concernée

Chaque attribut d'un SPKObject (ou dérivé) possèderait un pointeur vers un setter membre de la classe. En fonction du type de l'attribut, la signature de ce setter serait déterminée. Par exemple, pour ATTRIBUTE_TYPE_INT le setter sera forcément de la forme void setMyValue(int v). Le problème reste le flou autour des types d'attributs. En effet, ATTRIBUTE_TYPE_FLOAT (par ex) est on ne peut plus clair, mais pas sa variante ATTRIBUTE_TYPE_FLOATS: est-ce un tableau de taille fixée (par exemple, l'attribut "force" des émetteurs, 2 valeurs) ou complètement variable ? Actuellement, les types ne posent pas de problème insurmontable, mais forcent un code lourd à cause de l'incertitude (genre: setForce(std::vector<float> values) comme setter pour la force d'un émetteur...). La solution serait de préciser la taille du tableau pour les valeurs les plus utilisées: paire, triplet, quadruplet, matrice 3x3, matrice 4x4 (pour les matrice 2x2 on utilise le quadruplet) (si tu vois d'autres tailles utiles, dis-le moi). D'où un truc du genre:
Code:

// Types simples
ATTRIBUTE_TYPE_CHAR
ATTRIBUTE_TYPE_BOOL
ATTRIBUTE_TYPE_INT32
ATTRIBUTE_TYPE_UINT32
ATTRIBUTE_TYPE_FLOAT
ATTRIBUTE_TYPE_VECTOR
ATTRIBUTE_TYPE_COLOR
ATTRIBUTE_TYPE_STRING
ATTRIBUTE_TYPE_REF

// Tableaux de taille pas forcément fixe
ATTRIBUTE_TYPE_CHARS
ATTRIBUTE_TYPE_BOOLS
ATTRIBUTE_TYPE_INT32S
ATTRIBUTE_TYPE_UINT32S
ATTRIBUTE_TYPE_FLOATS
ATTRIBUTE_TYPE_VECTORS
ATTRIBUTE_TYPE_COLORS
ATTRIBUTE_TYPE_STRINGS
ATTRIBUTE_TYPE_REFS

// Paires
ATTRIBUTE_TYPE_CHAR_PAIR
ATTRIBUTE_TYPE_BOOL_PAIR
ATTRIBUTE_TYPE_INT32_PAIR
ATTRIBUTE_TYPE_UINT32_PAIR
ATTRIBUTE_TYPE_FLOAT_PAIR
ATTRIBUTE_TYPE_VECTOR_PAIR
ATTRIBUTE_TYPE_COLOR_PAIR
ATTRIBUTE_TYPE_STRING_PAIR
ATTRIBUTE_TYPE_REF_PAIR

// Triplets
ATTRIBUTE_TYPE_CHAR_TRIPLET
ATTRIBUTE_TYPE_BOOL_TRIPLET
ATTRIBUTE_TYPE_INT32_TRIPLET
ATTRIBUTE_TYPE_UINT32_TRIPLET
ATTRIBUTE_TYPE_FLOAT_TRIPLET
ATTRIBUTE_TYPE_VECTOR_TRIPLET
ATTRIBUTE_TYPE_COLOR_TRIPLET
ATTRIBUTE_TYPE_STRING_TRIPLET
ATTRIBUTE_TYPE_REF_TRIPLET

// Quadruplets
ATTRIBUTE_TYPE_CHAR_QUADRUPLET
ATTRIBUTE_TYPE_BOOL_QUADRUPLET
ATTRIBUTE_TYPE_INT32_QUADRUPLET
ATTRIBUTE_TYPE_UINT32_QUADRUPLET
ATTRIBUTE_TYPE_FLOAT_QUADRUPLET
ATTRIBUTE_TYPE_VECTOR_QUADRUPLET
ATTRIBUTE_TYPE_COLOR_QUADRUPLET
ATTRIBUTE_TYPE_STRING_QUADRUPLET
ATTRIBUTE_TYPE_REF_QUADRUPLET

// 9 valeurs (3x3) (sauf si tu connais le nom des 9-uplets;) )
ATTRIBUTE_TYPE_CHAR_9_UPLET
ATTRIBUTE_TYPE_BOOL_9_UPLET
ATTRIBUTE_TYPE_INT32_9_UPLET
ATTRIBUTE_TYPE_UINT32_9_UPLET
ATTRIBUTE_TYPE_FLOAT_9_UPLET
ATTRIBUTE_TYPE_VECTOR_9_UPLET
ATTRIBUTE_TYPE_COLOR_9_UPLET
ATTRIBUTE_TYPE_STRING_9_UPLET
ATTRIBUTE_TYPE_REF_9_UPLET

// 16 valeurs (4x4)
ATTRIBUTE_TYPE_CHAR_16_UPLET
ATTRIBUTE_TYPE_BOOL_16_UPLET
ATTRIBUTE_TYPE_INT32_16_UPLET
ATTRIBUTE_TYPE_UINT32_16_UPLET
ATTRIBUTE_TYPE_FLOAT_16_UPLET
ATTRIBUTE_TYPE_VECTOR_16_UPLET
ATTRIBUTE_TYPE_COLOR_16_UPLET
ATTRIBUTE_TYPE_STRING_16_UPLET
ATTRIBUTE_TYPE_REF_16_UPLET

Je ne sais pas si c'est très clair. Pour les connections il faut s'imaginer un graphe style

(image tirée de l'udk. Y a des trucs très similaires avec l'éditeur de graphe de Blender, Maya, ...)

Dis moi ce que tu en penses (si tu as des idées d'amélioration, je suis preneur Wink ). Je peut commiter la modification sur la description des objets très rapidement. Pour le système de contrôleurs, je pense que je le ferait et le testerait sur une branche locale avant de le commit.

_________________
Back to top Go down
View user profile
Juff
Developer


Messages : 539
Date d'inscription : 2009-07-14
Age : 34

PostSubject: Re: version 2 sujet à questions en vrac XD   Mon Feb 06, 2012 5:56 am

Cool, vas y lance toi dans le truc.

Juste un truc pour les tableaux, on peut avoir de la taille variable. Un exemple c'est le Graph Interpolator.

Je répondrai plus en détail a ton post plus tard.
Back to top Go down
View user profile http://spark.developpez.com
Darktib
Committer


Messages : 389
Date d'inscription : 2009-07-20
Localisation : A coté de Paris

PostSubject: Re: version 2 sujet à questions en vrac XD   Mon Feb 06, 2012 1:24 pm

OK, je me lance dans les contrôleurs. Pour les tableaux, les types suivants: ATTRIBUTE_TYPE_*S sont des tableaux de taille variable au niveau technique, comme actuellement, même s'ils peuvent être utilisés comme des tableaux de taille fixe. En gros: pas de changement pour les types existants, juste ajout de types qui permettent d'affiner la description et l'utilisation des attributs.

J'ai juste une question: pourquoi la fonction fillAttributeList est définie hors du corps de la classe dans le cas d'une classe template ? Est-ce vital ?

_________________
Back to top Go down
View user profile
Juff
Developer


Messages : 539
Date d'inscription : 2009-07-14
Age : 34

PostSubject: Re: version 2 sujet à questions en vrac XD   Mon Feb 06, 2012 3:56 pm

Darktib wrote:
pourquoi la fonction fillAttributeList est définie hors du corps de la classe dans le cas d'une classe template ? Est-ce vital ?

Ca doit être un relicat. Je pense que ca devait être a la base pour pouvoir spécialiser un template sans avoir à toucher a sa définition mais c'est de toute façon pas possible d'utiliser la macro telle qu'elle est faite. Tu peux les remettre dans le corps si tu veux.

Par contre les SPK_IMPLEMENT_OBJECT_TEMPLATE doivent rester dehors justement pour cette raison.
Back to top Go down
View user profile http://spark.developpez.com
Darktib
Committer


Messages : 389
Date d'inscription : 2009-07-20
Localisation : A coté de Paris

PostSubject: Re: version 2 sujet à questions en vrac XD   Tue Feb 07, 2012 3:55 pm

OK.

Pour ce qui est de la description, je pense qu'elle va changer un peu:
- La macro SPK_ATTRIBUTE prendra un paramètre supplémentaire, la fonction chargée de setter l'attribut en question (seul changement visible de l'utilisateur). Par exemple, pour la zone Sphere, l'attribut "radius" a pour setter 'setRadius' (fonction déjà existante). Le type du setter sera vérifié à la compilation pour être en accord avec le type de l'attribut (type-safety)
- Pour l'instant, une description n'est qu'une fonction chargée de remplir un tableau pour la sérialisation. Cela va changer: une description sera un tableau d'attributs stocké dans la classe, et initialisé par la fonction construite via SPK_ATTRIBUTE. Du coup, les attributs servant à autre chose qu'à la sérialisation uniquement, une nouvelle classe d'attribut sera créée pour que cela ait du sens (je mettrais une fonction qui pourra transformer ça en liste de SPK::IO::Attribute).

Pour l'instant, la valeur des attributs est stockée hors de la table de description. Je vais laisser ça comme ça - même si je pense qu'un changement ne me demanderais pas beaucoup d'effort.

Edit: La fonction qui crée la table de description sera virtuelle -> un objet devra être initialisé manuellement (pas d'appel de fonction virtuelle depuis un constructeur).
Les fonctions 'create' utilisées jusqu'à présent prennent tout leur interêt.

_________________


Last edited by Darktib on Wed Feb 08, 2012 5:16 pm; edited 1 time in total
Back to top Go down
View user profile
Darktib
Committer


Messages : 389
Date d'inscription : 2009-07-20
Localisation : A coté de Paris

PostSubject: Re: version 2 sujet à questions en vrac XD   Wed Feb 08, 2012 5:16 pm

OK, voici l'architecture pour les contrôleurs:

Au niveau des descriptions, elles seront maintenant stockées dans les objets, donc initialisées après la création des objets (cf post précédent)
Au niveau des types, se rajoutera:
- SPK::Controller, héritant directement de SPKObject, classe de base pour les contrôleurs
- La hiérarchie: SPK::ObjectAttributeBase -> SPK::ObjectAttribute<type> -> SPK::ObjectAttributeSpec<objectClass,type> pour stocker les attributs des descriptions
- La hiérarchie: SPK::ObjectConnectionBase -> SPK::ObjectConnection pour les connections (détaillées plus bas).
(liste pas complètement exhaustive, p-ê que je trouverais d'autres classes - beaucoup moins importantes - plus tard)

Un contrôleur sera un objet ayant des attributs et des connections, sorte d'attribut sortant. Une connection pourra être connectée à un nombre arbitraire d'attributs d'un nombre arbitraire d'objets SPARK. (par contre, pas 2 fois la même combinaison objet/attribut). De même, un attribut peut avoir autant de connections que possible.
Au niveau du nom 'connection', c'est ce que j'ai trouvé de mieux pour l'instant, si tu as des idées, dis-les moi, de mon coté je réfléchi aussi un peu pour voir si je peut trouver un nom plus explicite...

Au niveau des attributs, désormais il faudra indiquer une fonction servant de setter, ou 0 (dans ce cas on ne peut pas faire de connection sur l'attribut). Le système est à base de template, donc complètement type-safe, et même, il s'agit d'un typage fort: pas de connection de type INT pointant vers un attribut de type FLOAT, par exemple.

Pour le fonctionnement: le nerf de la guerre est les attributs.
Les connections maintiennent une liste de pointeurs vers des attributs. A l'update du groupe (ou du système ? il me faut définir si les contrôleurs vont dans un groupe ou dans un système), avant toute autre chose, les contrôleurs sont mis à jour (appel de leur fonction update(deltaTime) ). Cette fonction va leur demander de recalculer la valeur de leur(s) connection(s), puis va demander à chacune de ces connections de se mettre à jour. Celles-ci vont, pour chaque attribut dont elles connaissent l'adresse, faire un 'set(valeur)' avec la valeur de la connection. Cet 'set' va appeler le setter de l'attribut, avec la valeur passée.

J'ai un code qui montre tout ça, fonctionnel (il manque quelques trucs style déconnection automatique en cas de suppression d'objet), et qui m'a servi à tester le système (5 fichiers):
BaseObject.h
Code:
#ifndef BASE_OBJECT_H
#define BASE_OBJECT_H

#include "Types.h"
#include "Attribute.h"
#include <vector>

template<int U> class Connection;

class BaseObject
{
public:
   virtual void fillAttributeList()
   {
   }

private:
   template<int U> friend class Connection;
   template<int U>
   Attribute<U>* getAttribute(const std::string& name)
   {
      for(unsigned int t = 0; t < attributes.size(); t++)
         if(attributes[t]->getName() == name)
         {
            if(U == attributes[t]->getType())
            {
               if(attributes[t]->isModifiable())
                  return (Attribute<U>*)(attributes[t]);
               printf("Error: attribute '%s' is not modifiable\n",name.c_str());
               return 0;
            }
            printf("Error: type mismatch for attribute '%s'\n",name.c_str());
            return 0;
         }

      printf("Error: attribute '%s' not found\n",name.c_str());
      return 0;
   }

protected:
   std::vector<AttributeBase*> attributes;
};

#endif //BASE_OBJECT_H
Attribute.h
Code:
#ifndef ATTRIBUTE_H
#define ATTRIBUTE_H

#include "Types.h"

class AttributeBase
{
public:
   virtual std::string getName() const = 0;
   virtual Types getType() const = 0;
   virtual bool isModifiable() const = 0;
};

template<int U>
class Attribute : public AttributeBase
{
public:
   virtual void set(typename param_type<U>::type param) = 0;
};

template<class T, int U>
class AttributeSpec : public Attribute<U>
{
public:
   AttributeSpec(std::string n, typename member_type<T,U>::func sl, T* o)
   :name(n),slot(sl),obj(o)
   {
   }
   bool isModifiable() const { return slot != 0; }
   std::string getName() const { return name; }
   Types getType() const { return (Types)U; }
   void set(typename param_type<U>::type param)
   {
      if(slot != 0)
         (obj->*slot)(param);
   }

private:
   std::string name;
   typename member_type<T,U>::func slot;
   T* obj;
};

#endif //ATTRIBUTE_H
Types.h
Code:
#ifndef TYPES_H
#define TYPES_H

#include <string>

enum Types
{
   AT_INT = 0,
   AT_FLOAT,
   AT_STRING
};

// Type code to type
template<int T> struct param_type { typedef void type; typedef void value_type; };

template<> struct param_type<AT_INT> { typedef int type; typedef int value_type; };
template<> struct param_type<AT_FLOAT> { typedef float type; typedef float value_type; };
template<> struct param_type<AT_STRING> { typedef const std::string& type; typedef std::string value_type; };

// Type code & class to member type
template<class T, int U> struct member_type { typedef void func; };

template<class T> struct member_type<T,AT_INT> { typedef void (T::* func)(int); };
template<class T> struct member_type<T,AT_FLOAT> { typedef void (T::* func)(float); };
template<class T> struct member_type<T,AT_STRING> { typedef void (T::* func)(const std::string&); };

// Object hierarchy
class BaseObject;

#endif //TYPES_H
Controller.h
Code:
#ifndef CONTROLLER_H
#define CONTROLLER_H

#include "Types.h"
#include "Attribute.h"
#include "BaseObject.h"
#include <list>
#include <vector>

class ConnectionBase
{
public:
   virtual void update() = 0;
   virtual std::string getName() const = 0;
   virtual bool connect(BaseObject* obj, const std::string& attrName) = 0;
   virtual Types getType() const = 0;
};

template<int U>
class Connection : public ConnectionBase
{
public:
   typename param_type<U>::value_type value;

   Connection(const std::string& n):name(n),value(typename param_type<U>::value_type ()) {}
   virtual std::string getName() const { return name; }

   void update()
   {
      for(unsigned int t = 0; t < objects.size(); t++)
         objects[t].attr->set(value);
   }

   bool connect(BaseObject* obj, const std::string& attrName)
   {
      Attribute<U>* attr = obj->getAttribute<U>(attrName);
      if(attr)
      {
         pair p = { obj, attr };
         objects.push_back(p);
         return true;
      }
      return false;
   }

   virtual Types getType() const { return (Types)U; }

private:
   struct pair { BaseObject* obj; Attribute<U>* attr; };
   std::vector<pair> objects;
   std::string name;
};

class Controller
{
public:
   virtual void fillConnectionList() {}
   virtual void updateValues() = 0;
   bool connect(const std::string& connectionName, BaseObject* obj, const std::string& attrName)
   {
      for(unsigned int t = 0; t < connections.size(); t++)
         if(connections[t]->getName() == connectionName)
            return connections[t]->connect(obj,attrName);
      printf("Error: connection '%s' not found\n",connectionName.c_str());
      return false;
   }
   void updateConnections()
   {
      for(unsigned int t = 0; t < connections.size(); t++)
         connections[t]->update();
   }

protected:
   std::vector<ConnectionBase*> connections;
};

#endif //CONTROLLER_H
main.cpp
Code:
#include <string>
#include <stdio.h>
#include "Controller.h"

#define DEF_ATTRIBUTE( _class_ , _name_ , _type_ , _setter_ ) \
   attributes.push_back(new AttributeSpec<_class_,_type_>(_name_,_setter_,this));

#define DEF_CONNECTION( _name_ , _type_ ) \
   connections.push_back(new Connection<_type_>(_name_));

class TestObject : public BaseObject
{
   int num;
public:
   TestObject()
   {
      static int i = 0;
      num = ++i;
   }
   virtual void fillAttributeList()
   {
      DEF_ATTRIBUTE(TestObject,"radius",AT_FLOAT,&TestObject::setRadius)
      DEF_ATTRIBUTE(TestObject,"dim",AT_INT,0)
      DEF_ATTRIBUTE(TestObject,"name",AT_STRING,&TestObject::setName)
      DEF_ATTRIBUTE(TestObject,"num",AT_INT,0)
   }
   void setRadius(float value)
   {
      printf("(%i) Change radius: %f\n",num,value);
   }
   void setName(const std::string& value)
   {
      printf("(%i) Change name: %s\n",num,value.c_str());
   }
};

class TestController : public Controller
{
public:
   virtual void fillConnectionList()
   {
      DEF_CONNECTION("value_sin",AT_FLOAT)
      DEF_CONNECTION("random",AT_INT)
      DEF_CONNECTION("name-random",AT_STRING)
   }
   
   virtual void updateValues()
   {
      Connection<AT_FLOAT>* c = (Connection<AT_FLOAT>*)connections.at(0);
      c->value = 42;

      Connection<AT_STRING>* c2 = (Connection<AT_STRING>*)connections.at(2);
      c2->value = "THE name";
   }
};

int main()
{
   TestObject obj1,obj2;
   obj1.fillAttributeList();
   obj2.fillAttributeList();

   TestController ctrl;
   ctrl.fillConnectionList();

   ctrl.connect("value_sin",&obj1,"radius2");
   ctrl.connect("value_sin",&obj1,"radius");
   ctrl.connect("value_sin",&obj2,"radius");
   ctrl.connect("name-random",&obj2,"radius");
   ctrl.connect("name-random",&obj2,"name");

   ctrl.updateValues();
   ctrl.updateConnections();

   system("pause");
   return 0;
}


Je vais bientôt commencer l'implémentation de tout ceci dans SPARK. Je suis preneur de toute remarque Wink

edit:
1/ J'ai trouvé un nom qui colle beaucoup mieux à ce que j'entendais par class Connection: Control.
2/ Si j'ai le temps, j'ajouterais un peu de code pour plus automatiser la sérialisation. innerExport aura beaucoup moins de responsabilités, et innerImport deviendra inutile.

_________________
Back to top Go down
View user profile
Darktib
Committer


Messages : 389
Date d'inscription : 2009-07-20
Localisation : A coté de Paris

PostSubject: Re: version 2 sujet à questions en vrac XD   Sun Feb 12, 2012 9:56 am

Une petite démo pour montrer où j'en suis: http://www.mediafire.com/?ntjxuvqms0zp4xh

Pour le code utilisé:
Code:
// external libs
#include <irrlicht.h>

// SPARK lib
#include <SPARK.h>
#include <SPARK_IRR.h>

// windows only
#ifdef _WIN32
#include <windows.h>
#endif

float angleX = 0.0f;
float angleY = 0.0f;
const float CAM_POS_Z = 3.0f;
float dirX = 0.0f,dirY = 0.0f,dirZ = 0.0f;

using namespace irr;
IrrlichtDevice* device = NULL;

// Input Receiver
class MyEventReceiver : public IEventReceiver
{
    public:
        virtual bool OnEvent(const SEvent& event)
        {
            if(event.EventType==EET_KEY_INPUT_EVENT)
            {
            if(event.KeyInput.Key == KEY_ESCAPE && event.KeyInput.PressedDown==false)
            {
               device->closeDevice();
            }
            }
            return false;
        }

        int oldMouseX,oldMouseY;
};

class SinController : public SPK::Controller
{
   SPK_BEGIN_DESCRIPTION(SinController,SPK::Controller)
      SPK_CONTROL("value",SPK::SPK_TYPE_FLOAT)
   SPK_END_DESCRIPTION

   public:
      SinController(float p=0):time(0),phase(p){}

   protected:
      virtual void innerUpdateControls(float deltaTime)
      {
         float period = 2.0f;
         time = fmod(time + deltaTime,period);
         float output = sinf(phase + time * 2 * irr::core::PI / period);
         if(!setControl(0,output))
            printf("Failed to set control\n");
      }
      float time,phase;
};

class VectorMultiplexer : public SPK::Controller
{
   SPK_BEGIN_DESCRIPTION(VectorMultiplexer,SPK::Controller)
      SPK_CONTROLLABLE_ATTRIBUTE("x",SPK::SPK_TYPE_FLOAT,setX)
      SPK_CONTROLLABLE_ATTRIBUTE("y",SPK::SPK_TYPE_FLOAT,setY)
      SPK_CONTROLLABLE_ATTRIBUTE("z",SPK::SPK_TYPE_FLOAT,setZ)
      SPK_CONTROL("value",SPK::SPK_TYPE_VECTOR)
   SPK_END_DESCRIPTION

   public:
      VectorMultiplexer():x(0),y(0),z(0) {}

      void setX(float v) { x = v; dirX = x; }
      void setY(float v) { y = v; dirY = y; }
      void setZ(float v) { z = v; dirZ = z; }

   protected:
      float x,y,z;
      virtual void innerUpdateControls(float deltaTime)
      {
         SPK::Vector3D output(x,y,z);
         if(!setControl(0,output))
            printf("Vector: failed to set control\n");
         //printf("(%f,%f,%f)\n",x,y,z);
      }
};


// Main function
int main(int argc, char *argv[])
{
   //!IRRLICHT
    video::E_DRIVER_TYPE chosenDriver = video::EDT_OPENGL;
#ifdef _WIN32
   if(MessageBoxA(0,"Do you want to use DirectX 9 ? (else OpenGL)","SPARK Irrlicht test",MB_YESNO | MB_ICONQUESTION) == IDYES)
        chosenDriver = video::EDT_DIRECT3D9;
#endif

    //!IRRLICHT
   device = createDevice(chosenDriver,
      core::dimension2d<u32>(800,600),
      32,
      false,
      false,
      false,
      new MyEventReceiver);

    video::IVideoDriver* driver = device->getVideoDriver();
    scene::ISceneManager* smgr = device->getSceneManager();
    gui::IGUIEnvironment* guienv = device->getGUIEnvironment();

    device->setWindowCaption(L"SPARK Irrlicht test");
   device->getCursorControl()->setVisible(false);
    irr::scene::ICameraSceneNode* cam = smgr->addCameraSceneNodeFPS(smgr->getRootSceneNode(),100.0f,0.0005f);
    cam->setPosition(irr::core::vector3df(0.0f,0.0f,1.5f));
    cam->setTarget(irr::core::vector3df(0.0f,-0.2f,0.0f));
    cam->setNearValue(0.05f);

   // Inits Particle Engine
   // Sets the update step
   SPK::System::setClampStep(true,0.1f);         // clamp the step to 100 ms
   SPK::System::useAdaptiveStep(0.001f,0.01f);      // use an adaptive step from 1ms to 10ms (1000fps to 100fps)
   
   irr::scene::CSPKParticleSystemNode* system = new irr::scene::CSPKParticleSystemNode(smgr->getRootSceneNode(),smgr);
   system->drop(); // We let the scene manager take care of the system life time

   {
   SPK::Ref<SPK::IRR::IRRQuadRenderer> quadRenderer = SPK::IRR::IRRQuadRenderer::create(device);
   quadRenderer->setBlendMode(SPK::BLEND_MODE_ADD);
   quadRenderer->enableRenderingOption(SPK::RENDERING_OPTION_DEPTH_WRITE,false);
   quadRenderer->setTexture(driver->getTexture("res\\flare.bmp"));
   quadRenderer->setTexturingMode(SPK::TEXTURE_MODE_2D);

   SPK::Ref<SPK::StraightEmitter> emitter = SPK::StraightEmitter::create(SPK::Vector3D(1,0,1),SPK::Point::create());
   emitter->initObject();
   emitter->setForce(0.4f,0.6f);
   emitter->setFlow(200);

   SPK::Ref<SPK::ColorGraphInterpolator> graphInterpolator = SPK::ColorGraphInterpolator::create();
   graphInterpolator->addEntry(0.0f,0xFF000088);
   graphInterpolator->addEntry(0.5f,0x00FF0088);
   graphInterpolator->addEntry(1.0f,0x0000FF88);

   SPK::Ref<SPK::Group> group = system->createSPKGroup(400);
   group->setRadius(0.15f);
   group->setLifeTime(1.0f,2.0f);
   group->setColorInterpolator(graphInterpolator);
   group->setParamInterpolator(SPK::PARAM_SCALE,SPK::FloatRandomInterpolator::create(0.8f,1.2f,0.0f,0.0f));
   group->setParamInterpolator(SPK::PARAM_ANGLE,SPK::FloatRandomInitializer::create(0.0f,2 * 3.14159f));
   group->addEmitter(emitter);
   group->addModifier(SPK::Gravity::create(SPK::Vector3D(0.0f,-0.5f,0.0f)));
   group->addModifier(SPK::Friction::create(0.2f));
   group->setRenderer(quadRenderer);

   SPK::Ref<SinController> scontroller1 = new SinController();
   SPK::Ref<SinController> scontroller2 = new SinController(0.5);
   SPK::Ref<VectorMultiplexer> vmcontroller = new VectorMultiplexer();
   scontroller1->initObject();
   scontroller2->initObject();
   vmcontroller->initObject();
   scontroller1->connect("value",vmcontroller,"x");
   scontroller2->connect("value",vmcontroller,"z");
   vmcontroller->connect("value",emitter,"direction");
   system->addController(scontroller1);
   system->addController(scontroller2);
   system->addController(vmcontroller);


   int startX = 80, startY = 80;
   float lineLength = 40.0f;

   while(device->run())
   {
      driver->beginScene(true, true, irr::video::SColor(0,0,0,0));

      // Renders scene
      smgr->drawAll();

      irr::core::stringw infos; infos+="FPS: "; infos+=driver->getFPS(); infos+=" - Nb Particles: "; infos+=system->getNbParticles();
        guienv->getBuiltInFont()->draw(infos.c_str(),irr::core::rect<irr::s32>(0,0,170,20),irr::video::SColor(255,255,255,255));

      irr::video::SMaterial mat;
      mat.Lighting = false;
      driver->setTransform(irr::video::ETS_WORLD,irr::core::matrix4());
      driver->setMaterial(mat);
      driver->draw2DLine(irr::core::vector2di(startX,startY),irr::core::vector2di((int)(startX + lineLength * dirX),(int)(startY + lineLength * dirZ)));

      driver->endScene();
   }

   SPK_DUMP_MEMORY
   }
   device->drop();
   SPK_DUMP_MEMORY

   return 0;
}

_________________
Back to top Go down
View user profile
Juff
Developer


Messages : 539
Date d'inscription : 2009-07-14
Age : 34

PostSubject: Re: version 2 sujet à questions en vrac XD   Mon Feb 20, 2012 7:03 pm

Salut, ca m'a l'air pas mal tout çà. J'ai pas le temps de me pencher dessus en profondeur tout de suite alors fait ton truc, commite le dans une branche à part, et je regarderai tout çà dès que je peux.
Back to top Go down
View user profile http://spark.developpez.com
Darktib
Committer


Messages : 389
Date d'inscription : 2009-07-20
Localisation : A coté de Paris

PostSubject: Re: version 2 sujet à questions en vrac XD   Tue Feb 21, 2012 2:06 pm

OK, ça avance tranquillement, d'ailleurs en passant j'ai corrigé un certain nombre de bugs:
- l'erreur de nom pour la fonction 'pack_texture...' appelée par IRRRenderer (cette fonction a changée de nom dans les dernières SVN d'Irrlicht)
- une invertion de l'ordre des paramètres de constructeurs entre le header et le fichier source pour CSPKIrrSystem (bool initialized, bool worldTransform)
- quelques autre bugs mineurs dont je ne me souviens plus Wink

Quand j'aurai assez avancé, je commiterais dans une branche séparée. D'ici là, je vais continuer à poster l'avancement ici.

_________________
Back to top Go down
View user profile
Darktib
Committer


Messages : 389
Date d'inscription : 2009-07-20
Localisation : A coté de Paris

PostSubject: Re: version 2 sujet à questions en vrac XD   Tue Mar 13, 2012 6:39 am

Petite question: considère-t-on la répartition des attributs comme définitive ou pas (peut-elle être encore un peu modifiée) ?

En gros, certains attributs n'ont pas vraiment de setter associé (par exemple, il n'existe pas de setRadiuses(float,float) pour Group. D'ailleurs, une telle méthode ne serait pas claire du tout). Du coup, au lieu d'avoir un attribut "radius" de type FLOAT_PAIR, on aurait plutôt 2 attributs, le premier "graphical radius", le deuxième "physical radius", tous deux de type FLOAT.
Ainsi, je pourrais préciser les attributs sans ajouter de méthode obscure pour l'utilisateur.

L'autre chose, c'est qu'en regardant juste les attributs présents, on peut se faire une idée de comment la classe fonctionne. Et c'est facilité par le fait qu'en général les déclarations d'attribut se situent en haut des déclarations de classe. D'où l’intérêt d'avoir des attributs "explicites".

En contrepartie, les fichiers sauvegardés avec SPARK 2 jusqu'à maintenant ne pourront plus être directement lisibles (mais il est toujours possible de faire une conversion).

Question subsidiaire: dans quelle mesure l'API existante peut changer (pour l'instant il n'y a quasiment aucun changement à ce qui existe sur le dépôt) ?

_________________
Back to top Go down
View user profile
Darktib
Committer


Messages : 389
Date d'inscription : 2009-07-20
Localisation : A coté de Paris

PostSubject: Re: version 2 sujet à questions en vrac XD   Sat Mar 17, 2012 1:23 pm

Question très importante: il faudrait que tu répondes à la question ci-dessous le plus rapidement possible

J'ai regardé le code de sérialisation, et je le trouve assez compliqué: les Attributs ne stockent pas les valeurs, mais les écrivent en brut dans le descripteur... Je trouve pas ça très robuste.
Pourquoi ne pas plutôt templatiser la classe IO::Attribute par le type de l'attribut et stocker la valeur dans l'attribut ? Avec le code des contrôleurs j'ai été amené a définir des "template typedef" (ie, structures template ne contenant que des typedefs) qui permettent de passer d'un type SPARK (défini par la valeur d'une énumération) à un type en C++ et vice-versa (genre SPK::SPK_TYPE_INT32 <-> int). Donc, pas d'overhead.
Le code serait beaucoup plus lisible et plus robuste.
Si c'est pour les performances que les attributs stockent pour l'instant les valeurs en brut, j'ajouterais que les sérialisations/désérialisation sont peu fréquentes pour l'ordinateur, donc pas besoin d'hyper-optimiser cette partie...

La question est donc: puis-je changer le code de la sérialisation de la manière exprimée ci-dessus ? (réponse par défaut: oui...)

_________________
Back to top Go down
View user profile
Juff
Developer


Messages : 539
Date d'inscription : 2009-07-14
Age : 34

PostSubject: Re: version 2 sujet à questions en vrac XD   Mon Mar 19, 2012 11:49 am

Salut, je ne pense pas qu'un détail d'implémentation (au final c'est ce que la facon de stocker les valeurs d'attibuts est) puisse changer la robustesse du code.
Enfin pourquoi c'est comme çà, comme tu l'as dit c'est pour une question d'optimisation afin de limiter les allocations mémoires et aussi parcequ'au début je voulais me servir de ses données contigues pour la serialisation binaire. Au final comme l'endianess n'était pas garantie, j'ai utilisé un autre buffer pour la sérialisation binaire du coup cette manière de stocker les data devient un détail d'implémentation qui peut être changé.

Maintenant j'ai fait comme çà parceque je ne voulais justement pas d'allocation statique dans l'attribut, l'attribut a été designé pour être a la base juste un proxy pour le descripteur qui sert à getter et/ou a setter une valeur. Les descripteurs ont vocations a la base à être beaucoup plus flexibles que juste pour être utilisé pour la serialisation/deserialisation complète des objets de spark.

Ils peuvent être utilisés pour décrire les champs d'un objet par exemple (donc sans notion de valeurs dans les attributs), pour de la sérialisation désérialisation partielle... Si on prend le cas d'un editeur simple par exemple, on peut facilement se faire un petit MVC à l'aide des descripteurs très rapide à coder sans aucune wrapper ou description supplémentaire nécessaire. A la base je pensais même faire le système de controlleurs en passant directement par les descripteurs et les import/export. Enfin bref, en gros le design c'etait un attribut est un proxy vers une valeur et rien de plus.

Stocker les valeurs directement dans les attributs va pas forcément simplifier des masses l'implémentation d'après moi : Déjà tu aura une hierachie avec un attribut abstrait et un attribut template ensuite il y a aura pas mal de spécialisation explicite en fonction des types.

Mais si tu veux changer le système vas y, tu es plus impliqué que moi dans spark en ce moment alors je te laisse faire ton truc. Je ferais une review de ton code dans ta branche avant de merger avec le branche principale quand tu auras été au bout de ton idée et on discutera des choix. Tant que l'interface reste simple (pas de cast dans tous les sens...), le code flexible et pas trop lent, moi ca me va.
Back to top Go down
View user profile http://spark.developpez.com
Darktib
Committer


Messages : 389
Date d'inscription : 2009-07-20
Localisation : A coté de Paris

PostSubject: Re: version 2 sujet à questions en vrac XD   Mon Mar 19, 2012 3:07 pm

D'accord, si c'est un détail de l'implémentation je change ça.

Pour ce qui est des cast, en faisant les contrôleurs j'ai pour but que le code de l'utilisateur final change le moins possible. Il se trouve que pour l'instant, cette règle marche pas trop mal Wink

Sinon, je n'ai pas du tout utilisé les descripteurs pour le système de contrôleurs, je les voyais plutôt comme un méthode pour la sérialisation. Enfin, tu verras tout ça sur la branche que je committerais dans pas trop longtemps j'espère...

_________________
Back to top Go down
View user profile
Sponsored content




PostSubject: Re: version 2 sujet à questions en vrac XD   Today at 3:43 am

Back to top Go down
 
version 2 sujet à questions en vrac XD
View previous topic View next topic Back to top 
Page 5 of 5Go to page : Previous  1, 2, 3, 4, 5
 Similar topics
-
» Answer these questions with song titles
» EEG Questions
» Few questions about switching to Selenium
» 40 questions everyone is afraid to ask themselves
» Selenium Interview Questions

Permissions in this forum:You cannot reply to topics in this forum
 :: Forum Francais :: Evolution (fr)-
Jump to: