view Renderer/Engine/task/CreatePolygonFromSceneGraph.cc @ 2041:363b7c401c79 draft

Make Rendefing Engine
author Shin,ichi Uehara
date Mon, 23 Mar 2015 17:47:12 +0900
parents 8587ee89ef79
children
line wrap: on
line source

/**
 * SceneGraphを読み込んでpolygonの座標に変換行列を掛けて
 * 実座標のpolygonを生成する。
 *
 * SceneGraph が増えてくると動かなくなるかもしれない。
 * 一応 mainMem とかで動くようになるとは思うけど。
 * だめだったら、そこら辺が怪しいと思うべき
 */

#include "CreatePolygonFromSceneGraph.h"
#include "polygon_pack.h"
#include "texture.h"
#include "matrix_calc.h"
#include "Func.h"

#define  STATUS_NUM 3

SchedDefineTask1(CreatePolygonFromSceneGraph,createPolygon);

/**
 *  ベクトルに行列を乗算する
 * @param[out] v vector (float[4])
 * @param[in] m matrix (float[16])
 */
/*
static void
ApplyMatrix(float *v, float *m)
{
    float t[4];

    t[0] = v[0];
    t[1] = v[1];
    t[2] = v[2];
    t[3] = v[3];

    for (int i = 0; i < 4; i++) {
	v[i] = t[0]*m[i] + t[1]*m[i+4] + t[2]*m[i+8] + t[3]*m[i+12];
    }
}
*/


static int
compare_value(float *val, int num) {

    float max = 0;
    float min = 0;
    max = val[0];
    min = val[0];

    for (int i = 1; i < num; i++) {
        if (max < val[i]) {
            max = val[i];
        } else if (min > val[i]) {
            min = val[i];
        }
    }

    return (max - min);
}

/**
 * 輝度の計算
 * @param[in] vertexs polygon vertex position
 * @param[in] normal normal vector
 * @param[in] light light object position
 * @return diffuse
 */

// test
static float
lighting(const float *vertex, const float *normal, const float *light) {
    
    float light_vector[4];
    float normal_vector[4];

    light_vector[0] = vertex[0] - light[0];
    light_vector[1] = vertex[1] - light[1];
    light_vector[2] = vertex[2] - light[2];
    light_vector[3] = 0;

    normal_vector[0] = normal[0];
    normal_vector[1] = normal[1];
    normal_vector[2] = normal[2];
    normal_vector[3] = 0;

    normalize(light_vector, light_vector);
    normalize(normal_vector, normal_vector);

    float diffuse = innerProduct(light_vector, normal_vector);

    if ( diffuse < 0 ) {
        diffuse = 0;
    }

    return diffuse;
}


static int 
createPolygon(SchedTask *smanager, void *rbuf, void *wbuf)
{

    float xyz1[4], xyz2[4], xyz3[4];
    float normal1[4],normal2[4],normal3[4];

    //pp, matrix, を受け取る
    PolygonPackPtr in_pp      = (PolygonPackPtr)smanager->get_input(rbuf, 0);
    // w = world, v = view, p = perspective
    float *wvp_matrix         = (float*)smanager->get_input(rbuf, 1);
    float *m_screen           = (float*)smanager->get_input(rbuf, 2);

    float normal_matrix[16]; 
  
    for (int i = 0; i<16; i++) normal_matrix[i] = wvp_matrix[i];
    normal_matrix[4*0+3] = normal_matrix[4*1+3] = normal_matrix[4*2+3] = 0;
    normal_matrix[4*3] = normal_matrix[4*3+1] = normal_matrix[4*3+2] = 0;
    normal_matrix[4*3+3] = 1;

    float matrix[16]; // wvps matrix
    matrix4x4(matrix, wvp_matrix, m_screen);

    texture_list *tritexinfo  = (texture_list*)smanager->get_input(rbuf, 3);
    
    PolygonPackPtr next = (PolygonPackPtr)smanager->get_param(0);

    PolygonPackPtr out_pp = (PolygonPackPtr)smanager->get_output(wbuf, 0);
    out_pp->info.size = in_pp->info.size;
    out_pp->next = next;

    if (in_pp->info.size == 0) {
      printf("in_pp->info.size = 0\n");
    }

    float *light_xyz = (float*)smanager->global_get(LightData);
    int *light_switch = (int*)smanager->global_get(LightSwitch);
    int light_num = 4;
    // test

    for (int i = 0; i < in_pp->info.size; i++) {

      float diffuse1 = 0;
      float diffuse2 = 0;
      float diffuse3 = 0;

      TrianglePack tri = in_pp->tri[i];
      
      xyz1[0] = tri.ver1.x;
      xyz1[1] = tri.ver1.y;
      xyz1[2] = tri.ver1.z * -1.0f;
      xyz1[3] = 1.0f;
      
      xyz2[0] = tri.ver2.x;
      xyz2[1] = tri.ver2.y;
      xyz2[2] = tri.ver2.z * -1.0f;
      xyz2[3] = 1.0f;
      
      xyz3[0] = tri.ver3.x;
      xyz3[1] = tri.ver3.y;
      xyz3[2] = tri.ver3.z * -1.0f;
      xyz3[3] = 1.0f;

      normal1[0] = tri.normal1.x;
      normal1[1] = tri.normal1.y;
      normal1[2] = tri.normal1.z * -1.0f;
      //normal1[3] = 1.0f;
      normal1[3] = 0.0f;
      
      normal2[0] = tri.normal2.x;
      normal2[1] = tri.normal2.y;
      normal2[2] = tri.normal2.z * -1.0f;
      //normal2[3] = 1.0f;
      normal2[3] = 0.0f;
      
      normal3[0] = tri.normal3.x;
      normal3[1] = tri.normal3.y;
      normal3[2] = tri.normal3.z * -1.0f;
      //normal3[3] = 1.0f;
      normal3[3] = 0.0f;

      // matrix = ビュー座標変換行列*射影変換行列
      ApplyMatrix(xyz1, matrix);
      ApplyMatrix(xyz2, matrix);
      ApplyMatrix(xyz3, matrix);

      ApplyMatrix(normal1, normal_matrix);
      ApplyMatrix(normal2, normal_matrix);
      ApplyMatrix(normal3, normal_matrix);

      // test

      for (int j = 0; j < light_num; j++) {
          // 光源のスイッチが入ってたら 
      	if (light_switch[j] == 1) {
              // 複数の光源の計算, 全部足し合わせてみる.. 
              // rdb値は255を超えた値は、255にされるからここではいくら足してもいい
              diffuse1 += lighting(xyz1, normal1, &light_xyz[j*4]);
              diffuse2 += lighting(xyz2, normal2, &light_xyz[j*4]);
              diffuse3 += lighting(xyz3, normal3, &light_xyz[j*4]);
	      }
      }


      // このif文は、視錐台カリングに変えられる. 違うやり方があるはず
      if (xyz1[2] > 100 && xyz2[2] > 100 && xyz3[2] > 100) {

          /*
           * 同次座標で除算、同次クリップ空間に変換する
           *
           */

          xyz1[0] /= xyz1[3];
          xyz1[1] /= xyz1[3];
          xyz1[2] /= xyz1[3];

          xyz2[0] /= xyz2[3];
          xyz2[1] /= xyz2[3];
          xyz2[2] /= xyz2[3];

          xyz3[0] /= xyz3[3];
          xyz3[1] /= xyz3[3];
          xyz3[2] /= xyz3[3];


      } else {

          // ここは0じゃなくて、ppに登録しなければいい。pp->info.size をデクリメントすればいいはず
          xyz1[0] = 0; 
          xyz1[1] = 0;
          xyz1[2] = 0;
          
          xyz2[0] = 0;
          xyz2[1] = 0; 
          xyz2[2] = 0;
          
          xyz3[0] = 0; 
          xyz3[1] = 0;
          xyz3[2] = 0;
          
      }

   
      TrianglePackPtr triangle = &out_pp->tri[i];

      triangle->ver1.x = xyz1[0];
      triangle->ver1.y = xyz1[1];
      triangle->ver1.z = xyz1[2];
      triangle->ver1.tex_x = tri.ver1.tex_x;
      triangle->ver1.tex_y = tri.ver1.tex_y;
      // test
      triangle->ver1.diffuse = diffuse1;

      triangle->ver2.x = xyz2[0];
      triangle->ver2.y = xyz2[1];
      triangle->ver2.z = xyz2[2];
      triangle->ver2.tex_x = tri.ver2.tex_x;
      triangle->ver2.tex_y = tri.ver2.tex_y;
      // test
      triangle->ver2.diffuse = diffuse2;      
      
      triangle->ver3.x = xyz3[0];
      triangle->ver3.y = xyz3[1];
      triangle->ver3.z = xyz3[2];
      triangle->ver3.tex_x = tri.ver3.tex_x;
      triangle->ver3.tex_y = tri.ver3.tex_y;
      // test
      triangle->ver3.diffuse = diffuse3;      

      triangle->normal1.x = normal1[0];
      triangle->normal1.y = normal1[1];
      triangle->normal1.z = normal1[2];
      
      triangle->normal2.x = normal2[0];
      triangle->normal2.y = normal2[1];
      triangle->normal2.z = normal2[2];
      
      triangle->normal3.x = normal3[0];
      triangle->normal3.y = normal3[1];
      triangle->normal3.z = normal3[2];
      
      triangle->tex_info.addr   = tritexinfo->pixels;
      triangle->tex_info.width  = tritexinfo->t_w;
      triangle->tex_info.height = tritexinfo->t_h;
      triangle->tex_info.scale_max = tritexinfo->scale_max;

      //spanの数を先に計算しておくと、CreateSpanの時に静的にoutputが割り振れる(Taskの内の dma load がなくせるよ)
      //polygonの高さが、spanの数と一緒になるはず。

      float y[STATUS_NUM] = { xyz1[1], xyz2[1], xyz3[1] };
      int span_num = 0;
      span_num = compare_value(y, STATUS_NUM);
      out_pp->info.span_num += span_num;

    }

    return 0;
}