aboutsummaryrefslogblamecommitdiffstats
path: root/src/lib/evas/canvas/evas_canvas3d_light.c
blob: 3149e83dc04fdfc3335ecf507fdf49340f12a705 (plain) (tree)
1
2
3
4
5
6
7
8
9


                                
                                          
 



                                                                             
                                                       
                                                                                                 


                    
                  
                                                                                                                                                                            
 

                                                                  

 
                  
                                                                                                                      
 

 

    
                                                                                  

                 
                                                                      
                         
      
                                                
 
                              





                                                 
                                                              
 
                                                                         


    
                                                                                  

                 
                                                                      
                         




                                  
                                                            

                  
                                           
       
                                                                           

 
 

                                
 


                                    
                               

 
                  
                                                                                  
 
                                                   
                                                                       










                                                     

              

 
                  
                                                                                 
 

                            
                                        
 
                 



                                                   
                                                                       





                                           
                                            

 

                  
                                                                                                  

                                      
      
                                      
                                                                        


      
                       
                                                                                       
 
                          

 
                  
                                                                                                                           
 



                     
 
                                                                             

 
                  
                                                                                                                                                 
 



                             

 
                  
                                                                                                                           
 



                     
 
                                                                             

 
                  
                                                                                                                                                 
 



                             

 
                  
                                                                                                                            
 



                      
 
                                                                              

 
                  
                                                                                                                                                  
 



                              

 
                  
                                                                                                 
 
                           
                                                                              

 
                       
                                                                                         
 
                       

 
                  
                                                                                             
 

                                                    
                                                                                 

 
                       
                                                                                       
 
                          

 
                  
                                                                                                                                      
 


                              
                                                                                 

 
                  
                                                                                                                                                           
 


                                              

 
                  
                                                                                                    
 
                                        
      
                                        
                                                                                      


      
                       
                                                                                              
 
                                 
 
 
                  
                                                                                 

                                                                 
                                                   
                                                                                


                  
                                                                     
                                                                      

                                                           
                                                              


                  
                                                                                      









                                                                                 
                                                                                


                  
                                                                                  




                                                                                 
                                                                                


                  
                                                                                



                                                                        
                                                                                  
                                                                                


 
                                          
#include "evas_common_private.h"
#include "evas_private.h"

#define MY_CLASS EVAS_CANVAS3D_LIGHT_CLASS

static Eina_Bool
_light_node_change_notify(const Eina_Hash *hash EINA_UNUSED, const void *key,
                        void *data EINA_UNUSED, void *fdata)
{
   Evas_Canvas3D_Node *n = *(Evas_Canvas3D_Node **)key;
   evas_canvas3d_object_change(n, EVAS_CANVAS3D_STATE_NODE_LIGHT, (Evas_Canvas3D_Object *)fdata);
   return EINA_TRUE;
}

EOLIAN static void
_evas_canvas3d_light_evas_canvas3d_object_change_notify(Eo *obj, Evas_Canvas3D_Light_Data *pd, Evas_Canvas3D_State state EINA_UNUSED, Evas_Canvas3D_Object *ref EINA_UNUSED)
{
   if (pd->nodes)
     eina_hash_foreach(pd->nodes, _light_node_change_notify, obj);
}

EOLIAN static void
_evas_canvas3d_light_evas_canvas3d_object_update_notify(Eo *obj EINA_UNUSED, Evas_Canvas3D_Light_Data *pd EINA_UNUSED)
{

}

void
evas_canvas3d_light_node_add(Evas_Canvas3D_Light *light, Evas_Canvas3D_Node *node)
{
   int count = 0;
   Evas_Canvas3D_Light_Data *pd = efl_data_scope_get(light, MY_CLASS);
   if (pd->nodes == NULL)
     {
        pd->nodes = eina_hash_pointer_new(NULL);

        if (pd->nodes == NULL)
          {
             ERR("Failed to create hash table.");
             return;
          }
     }
   else
     count = (int)(uintptr_t)eina_hash_find(pd->nodes, &node);

   eina_hash_set(pd->nodes, &node, (const void *)(uintptr_t)(count + 1));
}

void
evas_canvas3d_light_node_del(Evas_Canvas3D_Light *light, Evas_Canvas3D_Node *node)
{
   int count = 0;
   Evas_Canvas3D_Light_Data *pd = efl_data_scope_get(light, MY_CLASS);
   if (pd->nodes == NULL)
     {
        ERR("No node to delete.");
        return;
     }

   count = (int)(uintptr_t)eina_hash_find(pd->nodes, &node);

   if (count == 1)
     eina_hash_del(pd->nodes, &node, NULL);
   else
     eina_hash_set(pd->nodes, &node, (const void *)(uintptr_t)(count - 1));
}


EAPI Evas_Canvas3D_Light *
evas_canvas3d_light_add(Evas *e)
{
   MAGIC_CHECK(e, Evas, MAGIC_EVAS);
   return NULL;
   MAGIC_CHECK_END();
   return efl_add(MY_CLASS, e);
}

EOLIAN static Eo *
_evas_canvas3d_light_efl_object_constructor(Eo *obj, Evas_Canvas3D_Light_Data *pd)
{
   obj = efl_constructor(efl_super(obj, MY_CLASS));
   evas_canvas3d_object_type_set(obj, EVAS_CANVAS3D_OBJECT_TYPE_LIGHT);
   evas_color_set(&pd->ambient, 0.0, 0.0, 0.0, 1.0);
   evas_color_set(&pd->diffuse, 1.0, 1.0, 1.0, 1.0);
   evas_color_set(&pd->specular, 1.0, 1.0, 1.0, 1.0);

   pd->spot_exp = 0.0;
   pd->spot_cutoff = 180.0;
   pd->spot_cutoff_cos = -1.0;

   pd->atten_const = 1.0;
   pd->atten_linear = 0.0;
   pd->atten_quad = 0.0;

   return obj;
}

EOLIAN static void
_evas_canvas3d_light_efl_object_destructor(Eo *obj, Evas_Canvas3D_Light_Data *pd)
{
   Eina_Iterator *it = NULL;
   void *data = NULL;
   Evas_Canvas3D_Node_Data *node = NULL;

   if (pd->nodes)
     {
        it = eina_hash_iterator_key_new(pd->nodes);
        while (eina_iterator_next(it, &data))
          {
             node = efl_data_scope_get(data, EVAS_CANVAS3D_NODE_CLASS);
             node->data.light.light = NULL;
          }

        eina_hash_free(pd->nodes);
     }

   efl_destructor(efl_super(obj, MY_CLASS));
}


EOLIAN static void
_evas_canvas3d_light_directional_set(Eo *obj, Evas_Canvas3D_Light_Data *pd, Eina_Bool directional)
{
   if (pd->directional != directional)
     {
        pd->directional = directional;
        evas_canvas3d_object_change(obj, EVAS_CANVAS3D_STATE_ANY, NULL);
     }
}

EOLIAN static Eina_Bool
_evas_canvas3d_light_directional_get(Eo *obj EINA_UNUSED, Evas_Canvas3D_Light_Data *pd)
{
   return pd->directional;
}

EOLIAN static void
_evas_canvas3d_light_ambient_set(Eo *obj, Evas_Canvas3D_Light_Data *pd, Evas_Real r, Evas_Real g, Evas_Real b, Evas_Real a)
{
   pd->ambient.r = r;
   pd->ambient.g = g;
   pd->ambient.b = b;
   pd->ambient.a = a;

   evas_canvas3d_object_change(obj, EVAS_CANVAS3D_STATE_LIGHT_AMBIENT, NULL);
}

EOLIAN static void
_evas_canvas3d_light_ambient_get(const Eo *obj EINA_UNUSED, Evas_Canvas3D_Light_Data *pd, Evas_Real *r, Evas_Real *g, Evas_Real *b, Evas_Real *a)
{
   if (r) *r = pd->ambient.r;
   if (g) *g = pd->ambient.g;
   if (b) *b = pd->ambient.b;
   if (a) *a = pd->ambient.a;
}

EOLIAN static void
_evas_canvas3d_light_diffuse_set(Eo *obj, Evas_Canvas3D_Light_Data *pd, Evas_Real r, Evas_Real g, Evas_Real b, Evas_Real a)
{
   pd->diffuse.r = r;
   pd->diffuse.g = g;
   pd->diffuse.b = b;
   pd->diffuse.a = a;

   evas_canvas3d_object_change(obj, EVAS_CANVAS3D_STATE_LIGHT_DIFFUSE, NULL);
}

EOLIAN static void
_evas_canvas3d_light_diffuse_get(const Eo *obj EINA_UNUSED, Evas_Canvas3D_Light_Data *pd, Evas_Real *r, Evas_Real *g, Evas_Real *b, Evas_Real *a)
{
   if (r) *r = pd->diffuse.r;
   if (g) *g = pd->diffuse.g;
   if (b) *b = pd->diffuse.b;
   if (a) *a = pd->diffuse.a;
}

EOLIAN static void
_evas_canvas3d_light_specular_set(Eo *obj, Evas_Canvas3D_Light_Data *pd, Evas_Real r, Evas_Real g, Evas_Real b, Evas_Real a)
{
   pd->specular.r = r;
   pd->specular.g = g;
   pd->specular.b = b;
   pd->specular.a = a;

   evas_canvas3d_object_change(obj, EVAS_CANVAS3D_STATE_LIGHT_SPECULAR, NULL);
}

EOLIAN static void
_evas_canvas3d_light_specular_get(const Eo *obj EINA_UNUSED, Evas_Canvas3D_Light_Data *pd, Evas_Real *r, Evas_Real *g, Evas_Real *b, Evas_Real *a)
{
   if (r) *r = pd->specular.r;
   if (g) *g = pd->specular.g;
   if (b) *b = pd->specular.b;
   if (a) *a = pd->specular.a;
}

EOLIAN static void
_evas_canvas3d_light_spot_exponent_set(Eo *obj, Evas_Canvas3D_Light_Data *pd, Evas_Real exponent)
{
   pd->spot_exp = exponent;
   evas_canvas3d_object_change(obj, EVAS_CANVAS3D_STATE_LIGHT_SPOT_EXP, NULL);
}

EOLIAN static Evas_Real
_evas_canvas3d_light_spot_exponent_get(Eo *obj EINA_UNUSED, Evas_Canvas3D_Light_Data *pd)
{
   return pd->spot_exp;
}

EOLIAN static void
_evas_canvas3d_light_spot_cutoff_set(Eo *obj, Evas_Canvas3D_Light_Data *pd, Evas_Real cutoff)
{
   pd->spot_cutoff = cutoff;
   pd->spot_cutoff_cos = cos(cutoff * M_PI / 180.0);
   evas_canvas3d_object_change(obj, EVAS_CANVAS3D_STATE_LIGHT_SPOT_CUTOFF, NULL);
}

EOLIAN static Evas_Real
_evas_canvas3d_light_spot_cutoff_get(Eo *obj EINA_UNUSED, Evas_Canvas3D_Light_Data *pd)
{
   return pd->spot_cutoff;
}

EOLIAN static void
_evas_canvas3d_light_attenuation_set(Eo *obj, Evas_Canvas3D_Light_Data *pd, Evas_Real constant, Evas_Real linear, Evas_Real quadratic)
{
   pd->atten_const = constant;
   pd->atten_linear = linear;
   pd->atten_quad = quadratic;
   evas_canvas3d_object_change(obj, EVAS_CANVAS3D_STATE_LIGHT_ATTENUATION, NULL);
}

EOLIAN static void
_evas_canvas3d_light_attenuation_get(const Eo *obj EINA_UNUSED, Evas_Canvas3D_Light_Data *pd, Evas_Real *constant, Evas_Real *linear, Evas_Real *quadratic)
{
   if (constant) *constant = pd->atten_const;
   if (linear) *linear = pd->atten_linear;
   if (quadratic) *quadratic = pd->atten_quad;
}

EOLIAN static void
_evas_canvas3d_light_attenuation_enable_set(Eo *obj, Evas_Canvas3D_Light_Data *pd, Eina_Bool enable)
{
   if (pd->enable_attenuation != enable)
     {
        pd->enable_attenuation = enable;
        evas_canvas3d_object_change(obj, EVAS_CANVAS3D_STATE_LIGHT_ATTENUATION, NULL);
     }
}

EOLIAN static Eina_Bool
_evas_canvas3d_light_attenuation_enable_get(Eo *obj EINA_UNUSED, Evas_Canvas3D_Light_Data *pd)
{
   return pd->enable_attenuation;
}

EOLIAN static void
_evas_canvas3d_light_projection_matrix_set(Eo *obj, Evas_Canvas3D_Light_Data *pd,
                                         const Evas_Real *matrix)
{
   eina_matrix4_array_set(&pd->projection, matrix);
   evas_canvas3d_object_change(obj, EVAS_CANVAS3D_STATE_LIGHT_PROJECTION, NULL);
}

EOLIAN static void
_evas_canvas3d_light_projection_matrix_get(const Eo *obj EINA_UNUSED,
                                         Evas_Canvas3D_Light_Data *pd,
                                         Evas_Real *matrix)
{
   memcpy(matrix, &pd->projection.xx, sizeof(Evas_Real) * 16);
}

EOLIAN static void
_evas_canvas3d_light_projection_perspective_set(Eo *obj, Evas_Canvas3D_Light_Data *pd,
                                              Evas_Real fovy, Evas_Real aspect,
                                              Evas_Real dnear, Evas_Real dfar)
{
   Evas_Real   xmax;
   Evas_Real   ymax;

   ymax = dnear * (Evas_Real)tan((double)fovy * M_PI / 360.0);
   xmax = ymax * aspect;

   evas_mat4_frustum_set(&pd->projection, -xmax, xmax, -ymax, ymax, dnear, dfar);
   evas_canvas3d_object_change(obj, EVAS_CANVAS3D_STATE_LIGHT_PROJECTION, NULL);
}

EOLIAN static void
_evas_canvas3d_light_projection_frustum_set(Eo *obj, Evas_Canvas3D_Light_Data *pd,
                                          Evas_Real left, Evas_Real right,
                                          Evas_Real bottom, Evas_Real top,
                                          Evas_Real dnear, Evas_Real dfar)
{
   evas_mat4_frustum_set(&pd->projection, left, right, bottom, top, dnear, dfar);
   evas_canvas3d_object_change(obj, EVAS_CANVAS3D_STATE_LIGHT_PROJECTION, NULL);
}

EOLIAN static void
_evas_canvas3d_light_projection_ortho_set(Eo *obj, Evas_Canvas3D_Light_Data *pd,
                                        Evas_Real left, Evas_Real right,
                                        Evas_Real bottom, Evas_Real top,
                                        Evas_Real dnear, Evas_Real dfar)
{
   eina_matrix4_ortho_set(&pd->projection, left, right, bottom, top, dnear, dfar);
   evas_canvas3d_object_change(obj, EVAS_CANVAS3D_STATE_LIGHT_PROJECTION, NULL);
}


#include "canvas/evas_canvas3d_light.eo.c"