view old/simple_render/task/create_span.cpp @ 1048:40cde8c1a6cd default tip

add ScaleXY (not for allExecute...)
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Wed, 08 Dec 2010 06:22:15 +0900
parents 735f76483bb2
children
line wrap: on
line source

#include <iostream>
#include "viewer.h"
#include "polygon_pack.h"
#include "SpuSpan.h"
using namespace std;

static float calc(float f1, float f2,int i, float base){
    float ans;
    ans = f1/f2*i + base;
    return ans;
}


static VertexPack*
vMid1(VertexPack *vMid1, VertexPack *vMin, VertexPack *vMid, VertexPack *vMax)
{
    int d, d1;

    // float2int のマクロとか書く?
#if 0
    d  = (int)vMax->y - (int)vMin->y;
    d1 = (int)vMid->y - (int)vMin->y;
#else
    d  = (int)(vMax->y - vMin->y);
    d1 = (int)(vMid->y - vMin->y);
#endif

    vMid1->tex_x  = calc(vMax->tex_x - vMin->tex_x, d, d1, vMin->tex_x);
    vMid1->tex_y  = calc(vMax->tex_y - vMin->tex_y, d, d1, vMin->tex_y);
    vMid1->x      = calc(vMax->x - vMin->x, d, d1, vMin->x);
    vMid1->y      = vMid->y;
    vMid1->z      = calc(vMax->z - vMin->z, d, d1, vMin->z);

    return vMid1;
}

void
half_triangle(SpuSpan *ssl,
	      long *tex_addr, long tex_width, long tex_height,
	      VertexPack *vMin, VertexPack *vMid, VertexPack *vMid1)
{
    float tmp_z,tmp_tex1, tmp_tex2 ,tmp_tey1,tmp_tey2;
    float tmp_xpos,tmp_end,tmp_zpos;
    int i;
    //int j;
    float div_y;
    float start_z,end_z;
    float start_tex_x,end_tex_x,start_tex_y,end_tex_y;
    int x,y,length;
    int k =0;
    int l = 1;
    int start_y = (int)vMid->y;
    int end_y   = (int)vMin->y; 
    int real_x, real_y;

    if (start_y<end_y) { 
	int i; i=end_y; end_y=start_y; start_y = i;
	k = 1;
	l = -1;
    }

    div_y = start_y - end_y;  // > 0

    for(i = k; i < div_y+1; i++) {
	tmp_xpos = calc(vMid1->x - vMin->x ,div_y, i, vMin->x);
	tmp_end =  calc(vMid->x  - vMin->x ,div_y, i, vMin->x); 
	tmp_z =    calc(vMid1->z - vMin->z ,div_y, i, vMin->z);
	tmp_zpos = calc(vMid->z  - vMin->z ,div_y, i, vMin->z);

	tmp_tex1 =((i/(div_y)) * vMid1->tex_x) +
	     ( ((div_y - i)/(div_y)) * vMin->tex_x); 
	tmp_tex2 =( (i/(div_y)) * vMid->tex_x) +	
	     ( ((div_y - i)/(div_y)) * vMin->tex_x); 
    
	tmp_tey1 =( (i/(div_y)) * vMid1->tex_y) +      
	     ( ((div_y - i)/(div_y)) * vMin->tex_y); 
	tmp_tey2 =( (i/(div_y)) * vMid->tex_y) +	
	     ( ((div_y - i)/(div_y)) * vMin->tex_y); 

	if (tmp_xpos > tmp_end) {
	    x = (int)tmp_end;
	    y = (int)vMin->y + i*l;
	    length = (int)(tmp_xpos)-(int)(tmp_end)+1;
	    start_z = tmp_zpos;
	    end_z = tmp_z;
	    start_tex_x = tmp_tex2;
	    end_tex_x = tmp_tex1;
	    start_tex_y = tmp_tey2;
	    end_tex_y = tmp_tey1;
	} else {
	    x = (int)tmp_xpos;
	    y = (int)vMin->y + i*l;
	    length = (int)(tmp_end)-(int)(tmp_xpos)+1;
	    start_z = tmp_z;
	    end_z = tmp_zpos;
	    start_tex_x = tmp_tex1;
	    end_tex_x = tmp_tex2;
	    start_tex_y = tmp_tey1;
	    end_tex_y = tmp_tey2;
	}

	// 画面外のものはここで
	// この判定で当たってるのかな?
#if 0
	real_x = x + Viewer::width/2;
	real_y = y + Viewer::height/2;

	if (real_x < 0 || real_x > Viewer::width ||
	    real_y < 0 || real_y > Viewer::height) {
	    continue;
	}

	int line_set = (y + (Viewer::height/2))/TEXTURE_SPLIT_PIXEL;
#else
	if (x < 0 || x > Viewer::width ||
	    y < 0 || y > Viewer::height) {
	    continue;
	}

	int line_set = y  / TEXTURE_SPLIT_PIXEL;
#endif
	
	int spu_no   = line_set % SPE_NUM_MAX;
	int spp_no   = line_set / SPE_NUM_MAX;

	SpanPack *spack = &ssl->list[spu_no].packs[spp_no];

	while (spack->next) spack = spack->next;

	if (spack->info.size >= MAX_SIZE_SPAN) {
	    SpanPack *pack_new = new SpanPack();
	    //SpanPack *pack_new;
	    //posix_memalign((void**)&pack_new, 16, sizeof(SpanPack));
	    pack_new->init();
	    spack->next = pack_new;
	    spack = pack_new;
	}

	int span_no = spack->info.size++;
	Span *span = &spack->span[span_no];

	span->tex_addr   = tex_addr;
	span->tex_width  = tex_width;
	span->tex_height = tex_height;
	span->x          = x;
	span->y          = y;
	span->length_x   = length;
	span->start_z    = start_z;
	span->end_z      = end_z;
	span->tex_x1     = start_tex_x;
	span->tex_x2     = end_tex_x;
	span->tex_y1     = start_tex_y;
	span->tex_y2     = end_tex_y;
    }
}

void
fill(SpuSpan *ssl)
{
    for (int y = 0; y < Viewer::height; y = y + TEXTURE_SPLIT_PIXEL) {
	int line_set = y / TEXTURE_SPLIT_PIXEL;
	int spu_no = line_set % SPE_NUM_MAX;
	int spp_no = line_set / SPE_NUM_MAX;

	SpanPack *spack = &ssl->list[spu_no].packs[spp_no];

	// 既に Span がある場合はスルー
	if (spack->info.size > 0) continue;

	// 塗りつぶし用 Span は info.size = -1
	//
	// ってことにしたけど、わかりづらいか・・・・
	spack->info.size = -1;
	Span *span = &spack->span[0];
	span->y = y;
    }
}

int create_span(void *rbuf,void *wbuf) {
    PolygonPack *polygon = (PolygonPack*)rbuf;
    SpuSpan *ssl = polygon->ssl;
    VertexPack *vMin, *vMid, *vMax, *vMid10;
    VertexPack ver;
    vMid10 = &ver;
    TrianglePack *triPack;

    ssl->init();

    for(int a = 0; a < polygon->info.size; a++) {
	triPack = &polygon->tri[a];
	
	if (triPack->ver1.y <= triPack->ver2.y) {
	    if (triPack->ver2.y <= triPack->ver3.y) {
		vMin = &triPack->ver1;
		vMid = &triPack->ver2;
		vMax = &triPack->ver3;
	    } else if (triPack->ver3.y <= triPack->ver1.y) {
		vMin = &triPack->ver3;
		vMid = &triPack->ver1;
		vMax = &triPack->ver2;
	    } else {
		vMin = &triPack->ver1;
		vMid = &triPack->ver3;
		vMax = &triPack->ver2;
	    }
	} else {
	    if (triPack->ver1.y <= triPack->ver3.y) {
		vMin = &triPack->ver2;
		vMid = &triPack->ver1;
		vMax = &triPack->ver3;
	    } else if (triPack->ver3.y <= triPack->ver2.y) {
		vMin = &triPack->ver3;
		vMid = &triPack->ver2;
		vMax = &triPack->ver1;
	    } else {
		vMin = &triPack->ver2;
		vMid = &triPack->ver3;
		vMax = &triPack->ver1;
	    }
	}

	vMid1(vMid10,vMin,vMid,vMax);
	
	half_triangle(ssl, triPack->tex_addr, triPack->tex_width,
		      triPack->tex_height, vMin, vMid, vMid10);

	half_triangle(ssl, polygon->tri[0].tex_addr, polygon->tri[0].tex_width,
		      polygon->tri[0].tex_height, vMax, vMid, vMid10);
    }

    fill(ssl);
    
    return 0;
}