Example #1
0
void eigenvectors_in_order_3x3s(
    //in, the matrix
    float m11,
    float m21, float m22,
    float m31, float m32, float m33,

    //out, the eigenvectors (must be float[3])
    float *er, float *es, float *et,
    //out, the eigenvalues corresponding to r, s, t (must be float[3])
    float *el )
{
    eigenvectors_3x3s( m11, m21, m22, m31, m32, m33, er, es, et, el );

    if( el[0] < el[1] )
    {
        swapf( el[0], el[1] );
        swap3fv( er, es );
    }

    if( el[0] < el[2] )
    {
        swapf( el[0], el[2] );
        swap3fv( er, et );
    }

    if( el[1] < el[2] )
    {
        swapf( el[1], el[2] );
        swap3fv( es, et );
    }
}
Example #2
0
void matrix_transpose(float *mat, int n)
{
	int i, j;

	for (i = 0; i < n; i++)
		for (j = i + 1; j < n; j++)
			swapf(&mat[i * n + j], &mat[j * n + i]);

}
Example #3
0
File: nbt.c Project: Youx/kouzan
int nbt_write_float(nbt_file *nbt, float *val)
{
    float temp = *val;

    if (get_endianness() == L_ENDIAN)
        temp = swapf(temp);

    return gzwrite(nbt->fp, &temp, sizeof(float));
}
Example #4
0
File: nbt.c Project: Youx/kouzan
int nbt_read_float(nbt_file *nbt, float **out)
{
    float t;

    gzread(nbt->fp, &t, sizeof(t));
    if (get_endianness() == L_ENDIAN)
        t = swapf(t);

    *out = malloc(sizeof(float));
    memcpy(*out, &t, sizeof(float));

    return 0;
}
void test_swapf_should_swap_0x12_into_0x21_save_in_wreg_access_bank_should_pass(){
	int error;	
	
	Instruction inst = { .mnemonic = SWAPF, .name = "swapf" };
	Bytecode code = {.instruction = &inst, .operand1 = 0x12, .operand2 = W, .operand3 = ACCESS, .absoluteAddress = 0};

	FSR[0x12] = 0x12;
	
	swapf(&code);
	TEST_ASSERT_EQUAL_HEX8(0x21, FSR[WREG]);
}

void test_swapf_should_swap_0x12_into_0x21_save_in_file_reg_acess_bank_should_pass(){
	int error;
	Instruction inst = { .mnemonic = SWAPF, .name = "swapf" };
	Bytecode code = {.instruction = &inst, .operand1 = 0x12, .operand2 = 1, .operand3 = ACCESS, .absoluteAddress = 0};
	
	FSR[0x12] = 0x12;	 
	
	swapf(&code);
	TEST_ASSERT_EQUAL_HEX8(0x21, FSR[0x12]);
}

void test_swapf_should_swap_0x13_into_0x21_save_in_file_reg_acess_bank_should_pass(){
	int error;
	Instruction inst = { .mnemonic = SWAPF, .name = "swapf" };
	Bytecode code = {.instruction = &inst, .operand1 = 0xff0, .operand2 = 1, .operand3 = ACCESS, .absoluteAddress = 0};
	
	FSR[0xff0] = 0x13;
		
	swapf(&code);
	TEST_ASSERT_EQUAL_HEX8(0x31, FSR[0xff0]);
}

void test_swapf_should_swap_0x12_into_0x21_default_operand2_operand3_should_pass(){
	int error;
	Instruction inst = { .mnemonic = SWAPF, .name = "swapf" };
	Bytecode code = {.instruction = &inst, .operand1 = 0x12, .operand2 = -1, .operand3 = -1, .absoluteAddress = 0};
	
	FSR[0x12] = 0x12;
	
	swapf(&code);
	TEST_ASSERT_EQUAL_HEX8(0x21, FSR[0x12]);
}

void test_swapf_should_swap_0x12_into_0x21_default_operand3_file_reg_should_pass(){
	int error;
	Instruction inst = { .mnemonic = SWAPF, .name = "swapf" };
	Bytecode code = {.instruction = &inst, .operand1 = 0x12, .operand2 = F, .operand3 = -1, .absoluteAddress = 0};
	
	FSR[0x12] = 0x12;
	
	swapf(&code);
	TEST_ASSERT_EQUAL_HEX8(0x21, FSR[0x12]);
}

void test_swapf_should_swap_0x12_into_0x21_default_operand2_acess_bank_should_pass(){
	int error;
	Instruction inst = { .mnemonic = SWAPF, .name = "swapf" };
	Bytecode code = {.instruction = &inst, .operand1 = 0x90, .operand2 = ACCESS, .operand3 = -1, .absoluteAddress = 0};
	
	FSR[0x90] = 0x12;
	
	swapf(&code);
	TEST_ASSERT_EQUAL_HEX8(0x21, FSR[0xf90]);
}

void test_swapf_should_swap_0x51_into_0x15_default_operand2_acess_bank_should_pass(){
	int error;
	Instruction inst = { .mnemonic = SWAPF, .name = "swapf" };
	Bytecode code = {.instruction = &inst, .operand1 = 0xff3, .operand2 = ACCESS, .operand3 = -1, .absoluteAddress = 0};
	
	FSR[0xff3] = 0x51;
	
	swapf(&code);
	TEST_ASSERT_EQUAL_HEX8(0x15, FSR[0xff3]);
}

void test_swapf_should_swap_0x01_into_0x10_save_in_wreg_with_bsr_5_should_pass(){
	
	int error;
	Instruction inst = { .mnemonic = SWAPF, .name = "swapf" };
	Bytecode code = {.instruction = &inst, .operand1 = 0x12, .operand2 = 0, .operand3 = BANKED, .absoluteAddress = 0};
	
	FSR[BSR] = 0x5;
	FSR[code.operand1+(FSR[BSR]<<8)] = 0x01;
	
	swapf(&code);
	TEST_ASSERT_EQUAL_HEX8(0x10, FSR[WREG]);
}

void test_swapf_should_swap_0x11_into_0x11_save_in_wreg_with_bsr_5_should_pass(){
	
	int error;
	Instruction inst = { .mnemonic = SWAPF, .name = "swapf" };
	Bytecode code = {.instruction = &inst, .operand1 = 0xfa3, .operand2 = 0, .operand3 = BANKED, .absoluteAddress = 0};
	
	FSR[BSR] = 0x5;
	FSR[0xfa3] = 0x11;

	swapf(&code);
	TEST_ASSERT_EQUAL_HEX8(0x11, FSR[WREG]);
}

void test_swapf_should_swap_0x01_into_0x10_save_in_file_reg_with_bsr_5_should_pass(){
	
	int error;
	Instruction inst = { .mnemonic = SWAPF, .name = "swapf" };
	Bytecode code = {.instruction = &inst, .operand1 = 0x12, .operand2 = F, .operand3 = BANKED, .absoluteAddress = 0};
	
	FSR[BSR] = 0x5;
	FSR[0x512] = 0x01;
	
	swapf(&code);
	TEST_ASSERT_EQUAL_HEX8(0x10, FSR[0x512]);
}

void test_swapf_should_swap_0x04_into_0x40_save_in_file_reg_with_bsr_5_should_pass(){
	
	int error;
	Instruction inst = { .mnemonic = SWAPF, .name = "swapf" };
	Bytecode code = {.instruction = &inst, .operand1 = 0xfa1, .operand2 = F, .operand3 = BANKED, .absoluteAddress = 0};
	
	FSR[BSR] = 0x5;
	FSR[0xfa1] = 0x04;
	
	swapf(&code);
	TEST_ASSERT_EQUAL_HEX8(0x40, FSR[0x5a1]);	
}

void test_swapf_should_swap_0x01_into_0x10_default_operand2_with_bsr_5_should_pass(){
	
	int error;
	Instruction inst = { .mnemonic = SWAPF, .name = "swapf" };
	Bytecode code = {.instruction = &inst, .operand1 = 0x12, .operand2 = F, .operand3 = BANKED, .absoluteAddress = 0};
	
	FSR[BSR] = 0x5;
	FSR[0x512] = 0x01;
	
	swapf(&code);
	TEST_ASSERT_EQUAL_HEX8(0x10, FSR[0x512]);
}

void test_swapf_should_swap_0x01_into_0x10_save_in_file_reg_with_bsr_15_should_throw_exception(){
	
	int error;
	Instruction inst = { .mnemonic = SWAPF, .name = "swapf" };
	Bytecode code = {.instruction = &inst, .operand1 = 0x12, .operand2 = F, .operand3 = BANKED};
	
	FSR[BSR] = 0x15;
	FSR[code.operand1+(FSR[BSR]<<8)] = 0x01;
	
	Try{
		swapf(&code);
	}Catch(error){
		TEST_ASSERT_EQUAL(1, ERR_INVALID_OPERAND);
	}
}

void test_swapf_should_swap_0x01_into_0x10_invalid_operand1_should_throw_exception(){
	
	int error;
	Instruction inst = { .mnemonic = SWAPF, .name = "swapf" };
	Bytecode code = {.instruction = &inst, .operand1 = -1, .operand2 = 2, .operand3 = BANKED};
	
	FSR[BSR] = 0x15;
	FSR[code.operand1+(FSR[BSR]<<8)] = 0x01;

	Try{
		swapf(&code);
	}Catch(error){
		TEST_ASSERT_EQUAL(1, ERR_INVALID_OPERAND);
	}
}

void test_swapf_should_swap_0x01_into_0x10_invalid_operand2_should_throw_exception(){
	
	int error;
	Instruction inst = { .mnemonic = SWAPF, .name = "swapf" };
	Bytecode code = {.instruction = &inst, .operand1 = 0x12, .operand2 = 2, .operand3 = BANKED};
	
	FSR[BSR] = 0x15;
	FSR[code.operand1+(FSR[BSR]<<8)] = 0x01;
	
	Try{
		swapf(&code);
	}Catch(error){
		TEST_ASSERT_EQUAL(1, ERR_INVALID_OPERAND);
	}
}

void test_swapf_should_swap_0x01_into_0x10_invalid_operand3_should_throw_exception(){
	
	int error;
	Instruction inst = { .mnemonic = SWAPF, .name = "swapf" };
	Bytecode code = {.instruction = &inst, .operand1 = 0x12, .operand2 = F, .operand3 = 2};
	
	FSR[BSR] = 0x15;
	FSR[code.operand1+(FSR[BSR]<<8)] = 0x01;
	
	Try{
		swapf(&code);
	}Catch(error){
		TEST_ASSERT_EQUAL(1, ERR_INVALID_OPERAND);
	}
}

void test_swapf_should_swap_0x01_into_0x10_default_operand2_invalid_operand3_should_throw_exception(){
	
	int error;
	Instruction inst = { .mnemonic = SWAPF, .name = "swapf" };
	Bytecode code = {.instruction = &inst, .operand1 = 0x12, .operand2 = ACCESS, .operand3 = 2};
	
	FSR[BSR] = 0x15;
	FSR[code.operand1+(FSR[BSR]<<8)] = 0x01;
	
	Try{
		swapf(&code);
	}Catch(error){
		TEST_ASSERT_EQUAL(1, ERR_INVALID_OPERAND);
	}
}

void test_swapf_should_swap_0x01_into_0x10_default_operand3_invalid_operand2_should_throw_exception(){
	
	int error;
	Instruction inst = { .mnemonic = SWAPF, .name = "swapf" };
	Bytecode code = {.instruction = &inst, .operand1 = 0x12, .operand2 = 4, .operand3 = -1};
	
	FSR[BSR] = 0x15;
	FSR[code.operand1+(FSR[BSR]<<8)] = 0x01;
	
	Try{
		swapf(&code);
	}Catch(error){
		TEST_ASSERT_EQUAL(1, ERR_INVALID_OPERAND);
	}
}

void test_swapf_should_swap_0x12_into_0x21_should_change_operand1_0xa1_into_0xfa1_save_in_wreg_access_bank_should_pass(){
	
	int error;	
	Instruction inst = { .mnemonic = SWAPF, .name = "swapf" };
	Bytecode code = {.instruction = &inst, .operand1 = 0xa1, .operand2 = W, .operand3 = ACCESS, .absoluteAddress = 0};
	
	FSR[0xa1] = 0x12;
	
	swapf(&code);
	TEST_ASSERT_EQUAL_HEX8(0x21, FSR[WREG]);
}

void test_swapf_should_swap_0x12_into_0x21_should_change_operand1_0xa2_into_0xfa2_save_in_wreg_access_bank_should_pass(){
	int error;
	Instruction inst = { .mnemonic = SWAPF, .name = "swapf" };
	Bytecode code = {.instruction = &inst, .operand1 = 0xa2, .operand2 = ACCESS, .operand3 = -1, .absoluteAddress = 0};
	
	FSR[0xa2] = 0x12;
	
	swapf(&code);
	TEST_ASSERT_EQUAL_HEX8(0x21, FSR[0xfa2]);
}
Example #6
0
static void swap3fv( float *v0, float *v1 )
{
    swapf( v0[0], v1[0] );
    swapf( v0[1], v1[1] );
    swapf( v0[2], v1[2] );
}
Example #7
0
void DrawLineAA(PixBufT *canvas, float x0, float y0, float x1, float y1) {
  bool steep = fabsf(y1 - y0) > fabsf(x1 - x0);
  float dx, dy;
  float gradient, intery;
  float xend, yend, xgap, yend_i, yend_f;
  int xpxl1, ypxl1, xpxl2, ypxl2, x;
 
  if (steep) {
    swapf(x0, y0);
    swapf(x1, y1);
  }

  if (x0 > x1) {
    swapf(x0, x1);
    swapf(y0, y1);
  }
 
  dx = x1 - x0;
  dy = y1 - y0;
  gradient = dy / dx;

  if (dx == 0.0f)
    return;

  /* Handle first endpoint. */
  xend = truncf(x0 + 0.5f);
  yend = y0 + gradient * (xend - x0);
  xgap = 1.0f - modff(x0 + 0.5f, NULL);
  xgap *= 128.0f;

  /* This will be used in the main loop. */
  yend_f = modff(yend, &yend_i);
  xpxl1 = (int)xend;
  ypxl1 = (int)truncf(yend);

  /* Draw first endpoint. */
  if (steep) {
    AddPixel(canvas, ypxl1, xpxl1, (1.0f - yend_f) * xgap);
    AddPixel(canvas, ypxl1 + 1, xpxl1, yend_f * xgap);
  } else {
    AddPixel(canvas, xpxl1, ypxl1, (1.0f - yend_f) * xgap);
    AddPixel(canvas, xpxl1, ypxl1 + 1, yend_f * xgap);
  }

  /* First y-intersection for the main loop. */
  intery = yend + gradient;

  /* Handle second endpoint. */
  xend = truncf(x1 + 0.5f);
  yend = y1 + gradient * (xend - x1);
  xgap = modff(x1 + 0.5f, NULL);
  xgap *= 128.0f;

  /* This will be used in the main loop. */
  yend_f = modff(yend, &yend_i);
  xpxl2 = (int)xend;
  ypxl2 = (int)yend_i;

  if (steep) {
    /* Draw second endpoint. */
    AddPixel(canvas, ypxl2, xpxl2, (1.0f - yend_f) * xgap);
    AddPixel(canvas, ypxl2 + 1, xpxl2, yend_f * xgap);

    /* Inner part of line. */
    for (x = xpxl1 + 1; x < xpxl2; x++, intery += gradient) {
      float i, f;
      f = modff(intery, &i) * 128.0f;
      AddPixel(canvas, i, x, 128.0f - f);
      AddPixel(canvas, i + 1, x, f);
    }
  } else {
    /* Draw second endpoint. */
    AddPixel(canvas, xpxl2, ypxl2, (1.0f - yend_f) * xgap);
    AddPixel(canvas, xpxl2, ypxl2 + 1, yend_f * xgap);

    /* Inner part of line. */
    for (x = xpxl1 + 1; x < xpxl2; x++, intery += gradient) {
      float i, f;
      f = modff(intery, &i) * 128.0f;
      AddPixel(canvas, x, i, 128.0f - f);
      AddPixel(canvas, x, i + 1, f);
    }
  }
}
Example #8
0
void Prop2D::render(Camera *cam, DrawBatchList *bl ) {
    if( debug_id ) {
        assertmsg(deck || grid_used_num > 0 || children_num > 0 || prim_drawer , "no deck/grid/prim_drawer is set. deck:%p grid:%d child:%d prim:%p", deck, grid_used_num, children_num, prim_drawer );
    }
    
	float camx=0.0f;
	float camy=0.0f;
	if(cam){
		camx = cam->loc.x;
		camy = cam->loc.y;
	}

	if( children_num > 0 && render_children_first ){
		for(int i=0;i<children_num;i++){
			Prop2D *p = (Prop2D*) children[i];
            if( p->visible ) {
                if( !p->parent_group ) {
                    p->parent_group = parent_group;
                }
                p->render( cam, bl );
            }
		}
	}

	if( grid_used_num > 0 ){
		glEnable(GL_TEXTURE_2D);
		glColor4f(color.r,color.g,color.b,color.a);        
		for(int i=0;i<grid_used_num;i++){
			Grid *grid = grids[i];
			if(!grid)break;
			if(!grid->visible)continue;
            if(!grid->index_table)continue;

			Deck *draw_deck = deck;
			if( grid->deck ) draw_deck = grid->deck;
			if( grid->fragment_shader ){
#if !(TARGET_IPHONE_SIMULATOR ||TARGET_OS_IPHONE || defined(__linux__) )
				glUseProgram(grid->fragment_shader->program );
#endif                
				grid->fragment_shader->updateUniforms();
			}

            if(!grid->mesh) {
                //                print("new grid mesh! wh:%d,%d", grid->width, grid->height );
                grid->mesh = new Mesh();
                VertexFormat *vf = DrawBatch::getVertexFormat( VFTYPE_COORD_COLOR_UV );
                IndexBuffer *ib = new IndexBuffer();
                VertexBuffer *vb = new VertexBuffer();
                vb->setFormat(vf);
                /*
                  3+--+--+--+--+
                   |  |  |  |  |
                  2+--+--+--+--+
                   |  |  |  |  |
                  1+--+--+--+--+
                   |  |  |  |  |
                  0+--+--+--+--+
                   0  1  2  3  4
                 */
                int quad_num = grid->width * grid->height;
                int triangle_num = quad_num * 2;
                int vert_num = quad_num * 4; // Can't share vertices because each vert has different UVs 
                vb->reserve( vert_num);
                ib->reserve( triangle_num*3 );
                grid->mesh->setVertexBuffer(vb);
                grid->mesh->setIndexBuffer(ib);
                grid->mesh->setPrimType( GL_TRIANGLES );

                grid->uv_changed = true;
                grid->color_changed = true;
            }

            if( grid->uv_changed || grid->color_changed ) {
                if(grid->debug) {
                    print("debug:%d Grid changed: uv:%d col:%d", grid->debug, grid->uv_changed, grid->color_changed );
                }
                grid->uv_changed = false;
                grid->color_changed = false;
                
                VertexBuffer *vb = grid->mesh->vb;
                IndexBuffer *ib = grid->mesh->ib;
                vb->unbless();
                ib->unbless();

                int quad_cnt=0;
                for(int y=0;y<grid->height;y++) {
                    for(int x=0;x<grid->width;x++) {
                        int ind = x+y*grid->width;
                        if(grid->debug) {
                            if(grid->texofs_table) {
                                prt("%.2f,%.2f ", grid->texofs_table[ind].x, grid->texofs_table[ind].y );
                            } else if( grid->index_table ) {
                                prt("%3d ", grid->index_table[ind] );
                            }
                        }
                        if( grid->index_table[ind] == Grid::GRID_NOT_USED ) continue;
                        
                        
                        Vec2 left_bottom, right_top;
                        float u0,v0,u1,v1;
                        draw_deck->getUVFromIndex( grid->index_table[ind], &u0,&v0,&u1,&v1,0,0,grid->uv_margin);
                        if(grid->texofs_table) {
                            float u_per_cell = draw_deck->getUperCell();
                            float v_per_cell = draw_deck->getVperCell();
                            u0 += grid->texofs_table[ind].x * u_per_cell;
                            v0 += grid->texofs_table[ind].y * v_per_cell;
                            u1 += grid->texofs_table[ind].x * u_per_cell;
                            v1 += grid->texofs_table[ind].y * v_per_cell;
                        }

                        //
                        // Q (u0,v0) - R (u1,v0)      top-bottom upside down.
                        //      |           |
                        //      |           |                        
                        // P (u0,v1) - S (u1,v1)
                        //
                        if(grid->xflip_table && grid->xflip_table[ind]) {
                            swapf( &u0, &u1 );
                        }
                        if(grid->yflip_table && grid->yflip_table[ind]) {
                            swapf( &v0, &v1 );
                        }
                        Vec2 uv_p(u0,v1), uv_q(u0,v0), uv_r(u1,v0), uv_s(u1,v1);

                        
                        // left bottom
                        const float d = 1;
                        int vi = quad_cnt * 4;
                        vb->setCoord(vi,Vec3(d*x-enfat_epsilon,d*y-enfat_epsilon,0));
                        if(grid->rot_table && grid->rot_table[ind]) vb->setUV(vi,uv_s); else vb->setUV(vi,uv_p);
                        if(grid->color_table) vb->setColor(vi, grid->color_table[ind]); else vb->setColor(vi, Color(1,1,1,1));
                        // right bottom
                        vb->setCoord(vi+1,Vec3(d*(x+1)+enfat_epsilon,d*y-enfat_epsilon,0));
                        if(grid->rot_table && grid->rot_table[ind]) vb->setUV(vi+1,uv_r); else vb->setUV(vi+1,uv_s);                        
                        if(grid->color_table) vb->setColor(vi+1,grid->color_table[ind]); else vb->setColor(vi+1, Color(1,1,1,1));
                        // left top
                        vb->setCoord(vi+2,Vec3(d*x-enfat_epsilon,d*(y+1)+enfat_epsilon,0));
                        if(grid->rot_table && grid->rot_table[ind]) vb->setUV(vi+2,uv_p); else vb->setUV(vi+2,uv_q);
                        if(grid->color_table) vb->setColor(vi+2,grid->color_table[ind]); else vb->setColor(vi+2, Color(1,1,1,1));
                        // right top
                        vb->setCoord(vi+3,Vec3(d*(x+1)+enfat_epsilon,d*(y+1)+enfat_epsilon,0));
                        if(grid->rot_table && grid->rot_table[ind]) vb->setUV(vi+3,uv_q); else vb->setUV(vi+3,uv_r);
                        if(grid->color_table) vb->setColor(vi+3,grid->color_table[ind]); else vb->setColor(vi+3, Color(1,1,1,1));

                        // TODO: no need to update index every time it changes.
                       
                        int indi = quad_cnt * 6; // 2 triangles = 6 verts per quad
                        ib->setIndex(indi++, quad_cnt*4+0 );
                        ib->setIndex(indi++, quad_cnt*4+2 );
                        ib->setIndex(indi++, quad_cnt*4+1 );
                        ib->setIndex(indi++, quad_cnt*4+1 );
                        ib->setIndex(indi++, quad_cnt*4+2 );
                        ib->setIndex(indi++, quad_cnt*4+3 );

                        quad_cnt++; // next quad!
                    }
                    if(grid->debug) print("");
                }
                ib->setRenderLen(quad_cnt*6);
            } 

            
            // draw
            if(!draw_deck) {
                print("no tex? (grid)");
                continue;
            }
            if( grid->mesh == NULL || grid->mesh->hasIndexesToRender() == false ) {
                continue;
            }
            FragmentShader *fs = fragment_shader;
            if( grid->fragment_shader ) fs = grid->fragment_shader;
            //            print("appendMesh, tex:%d vn:%d rn:%d", draw_deck->tex->tex, grid->mesh->vb->array_len, grid->mesh->ib->render_len );
            Vec2 finloc(loc.x+grid->rel_loc.x, loc.y+grid->rel_loc.y);
            Vec2 finscl(scl.x*grid->rel_scl.x, scl.y*grid->rel_scl.y);
            if(!fs)fs=default_fs;
            bl->appendMesh( getViewport(), fs, getBlendType(), draw_deck->tex->tex, finloc - Vec2(camx,camy), finscl, rot, grid->mesh, copy_mesh_at_draw );
		}
	}

	if(deck && index >= 0 ){
        float u0,v0,u1,v1;
        deck->getUVFromIndex( index, &u0,&v0,&u1,&v1,0,0,uv_margin);
        if(xflip) {
            swapf(&u0,&u1);
        }
        if(yflip) {
            swapf(&v0,&v1);
        }
        // Q (u0,v0) - R (u1,v0)      top-bottom upside down.
        //      |           |
        //      |           |                        
        // P (u0,v1) - S (u1,v1)
        Vec2 uv_p(u0,v1), uv_q(u0,v0), uv_r(u1,v0), uv_s(u1,v1);
        if(uvrot) {
            Vec2 tmp = uv_p;
            uv_p = uv_s;
            uv_s = uv_r;
            uv_r = uv_q;
            uv_q = tmp;
        }
        if(!fragment_shader)fragment_shader=default_fs;
        bl->appendSprite1( getViewport(),
                           fragment_shader,
                           getBlendType(),
                           deck->tex->tex,
                           color,
                           loc - Vec2(camx,camy) + draw_offset,
                           scl,
                           rot,
                           uv_p,
                           uv_q,
                           uv_r,
                           uv_s
                           );
	}

	if( children_num > 0 && (render_children_first == false) ){
		for(int i=0;i<children_num;i++){
			Prop2D *p = (Prop2D*) children[i];
			if(p->visible) {
                if( !p->parent_group ) {
                    p->parent_group = parent_group;
                }
                p->render( cam, bl );
            }
		}
	}

	// primitives should go over image sprites
	if( prim_drawer ){
		prim_drawer->drawAll( bl, getViewport(), loc - Vec2(camx,camy),scl,rot);
	}
}