void CL_Sprite_Impl::draw_calcs_step1( const CL_Surface_DrawParams2 ¶ms2, CL_Surface_TargetDrawParams1 &t_params1) { // Find size of surface: float size_width = (float) params2.srcWidth; float size_height = (float) params2.srcHeight; // Calculate translation hotspot CL_Pointf translation_hotspot = calc_hotspot( params2.translate_origin, (float) params2.translate_x, (float) params2.translate_y, size_width, size_height); // Calculate rotation hotspot: t_params1.rotation_hotspot = calc_hotspot( params2.rotate_origin, (float) params2.rotate_x, (float) params2.rotate_y, size_width, size_height); if (!params2.sub_pixel_accuracy) { // Avoid linear smoothing: translation_hotspot.x = float(int(translation_hotspot.x)); translation_hotspot.y = float(int(translation_hotspot.y)); t_params1.rotation_hotspot.x = float(int(t_params1.rotation_hotspot.x)); t_params1.rotation_hotspot.y = float(int(t_params1.rotation_hotspot.y)); } // Find top left point of destination rectangle and map rotation hotspot to screen coordinates: if (params2.scale_x == 1.0 && params2.scale_y == 1.0) { t_params1.destWidth = (float)params2.srcWidth; t_params1.destHeight = (float)params2.srcHeight; t_params1.pixDestX = params2.destX-translation_hotspot.x; t_params1.pixDestY = params2.destY-translation_hotspot.y; t_params1.rotation_hotspot.x += float(t_params1.pixDestX); t_params1.rotation_hotspot.y += float(t_params1.pixDestY); } else { t_params1.destWidth = params2.srcWidth * params2.scale_x; t_params1.destHeight = params2.srcHeight * params2.scale_y; t_params1.pixDestX = params2.destX-translation_hotspot.x * params2.scale_x; t_params1.pixDestY = params2.destY-translation_hotspot.y * params2.scale_y; t_params1.rotation_hotspot.x = float(t_params1.pixDestX + t_params1.rotation_hotspot.x * params2.scale_x); t_params1.rotation_hotspot.y = float(t_params1.pixDestY + t_params1.rotation_hotspot.y * params2.scale_y); } }
void Sprite_Impl::draw(Canvas &canvas, const Rect &p_src, const Pointf &p_dest, const Pointf &p_scale) { SpriteFrame &frame = frames[current_frame]; // Find size of surface: float src_width = (float) p_src.get_width(); float src_height = (float) p_src.get_height(); // Calculate translation hotspot Pointf target_translation_hotspot = calc_hotspot( translation_origin, (float) (translation_hotspot.x + frame.offset.x), (float) (translation_hotspot.y + frame.offset.y), src_width, src_height); // Calculate rotation hotspot: Pointf target_rotation_hotspot = calc_hotspot( rotation_origin, (float) (rotation_hotspot.x + frame.offset.x), (float) (rotation_hotspot.y + frame.offset.y), src_width, src_height); // Find top left point of destination rectangle and map rotation hotspot to screen coordinates: float destWidth = src_width * p_scale.x; float destHeight = src_height * p_scale.y; float pixDestX = p_dest.x -target_translation_hotspot.x * p_scale.x; float pixDestY = p_dest.y -target_translation_hotspot.y * p_scale.y; target_rotation_hotspot.x = float(pixDestX + target_rotation_hotspot.x * p_scale.x); target_rotation_hotspot.y = float(pixDestY + target_rotation_hotspot.y * p_scale.y); // Calculate unit vectors for rotated surface: // (cached for speed reasons) static float vect_rotate_x[2] = { 1.0f, 0.0f }; static float vect_rotate_y[2] = { 0.0f, 1.0f }; static Angle last_angle(0, angle_radians); Angle target_rotate_angle = angle - base_angle; if (last_angle != target_rotate_angle) { float angle_degrees = target_rotate_angle.to_degrees(); if (angle_degrees == 0.0f) { vect_rotate_x[0] = 1.0; vect_rotate_x[1] = 0.0; vect_rotate_y[0] = 0.0; vect_rotate_y[1] = 1.0; } else if (angle_degrees == 90.0f) { vect_rotate_x[0] = 0.0; vect_rotate_x[1] = 1.0; vect_rotate_y[0] = -1.0; vect_rotate_y[1] = 0.0; } else if (angle_degrees == 180.0f) { vect_rotate_x[0] = -1.0; vect_rotate_x[1] = 0.0; vect_rotate_y[0] = 0.0; vect_rotate_y[1] = -1.0; } else if (angle_degrees == 270.0f) { vect_rotate_x[0] = 0.0; vect_rotate_x[1] = -1.0; vect_rotate_y[0] = 1.0; vect_rotate_y[1] = 0.0; } else { float angle_rad = target_rotate_angle.to_radians(); vect_rotate_x[0] = cos(angle_rad); vect_rotate_x[1] = sin(angle_rad); vect_rotate_y[0] = cos(PI/2+angle_rad); vect_rotate_y[1] = sin(PI/2+angle_rad); } } // Calculate final source rectangle points for render: const Texture2D &texture = frames[current_frame].texture; float texture_width = texture.get_width(); float texture_height = texture.get_height(); Pointf texture_position[4]; // Scaled to the range of 0.0f to 1.0f Pointf dest_position[4]; texture_position[0].x = (((float) p_src.left) ) / texture_width; texture_position[1].x = (((float) p_src.left+src_width) ) / texture_width; texture_position[2].x = (((float) p_src.left) ) / texture_width; texture_position[3].x = (((float) p_src.left+src_width) ) / texture_width; texture_position[0].y = (((float) p_src.top) ) / texture_height; texture_position[1].y = (((float) p_src.top) ) / texture_height; texture_position[2].y = (((float) p_src.top+src_height) ) / texture_height; texture_position[3].y = (((float) p_src.top+src_height) ) / texture_height; // Calculate final destination rectangle points for surface rectangle: if (target_rotate_angle.to_radians() == 0.0f) { dest_position[0].x = pixDestX; dest_position[1].x = pixDestX+destWidth; dest_position[2].x = pixDestX; dest_position[3].x = pixDestX+destWidth; dest_position[0].y = pixDestY; dest_position[1].y = pixDestY; dest_position[2].y = pixDestY+destHeight; dest_position[3].y = pixDestY+destHeight; } else { // Roll dest_position[0].x = calc_rotate_x(pixDestX, pixDestY, target_rotation_hotspot.x, target_rotation_hotspot.y, vect_rotate_x[0], vect_rotate_y[0]); dest_position[1].x = calc_rotate_x(pixDestX+destWidth, pixDestY, target_rotation_hotspot.x, target_rotation_hotspot.y, vect_rotate_x[0], vect_rotate_y[0]); dest_position[2].x = calc_rotate_x(pixDestX, pixDestY+destHeight, target_rotation_hotspot.x, target_rotation_hotspot.y, vect_rotate_x[0], vect_rotate_y[0]); dest_position[3].x = calc_rotate_x(pixDestX+destWidth, pixDestY+destHeight, target_rotation_hotspot.x, target_rotation_hotspot.y, vect_rotate_x[0], vect_rotate_y[0]); dest_position[0].y = calc_rotate_y(pixDestX, pixDestY, target_rotation_hotspot.x, target_rotation_hotspot.y, vect_rotate_x[1], vect_rotate_y[1]); dest_position[1].y = calc_rotate_y(pixDestX+destWidth, pixDestY, target_rotation_hotspot.x, target_rotation_hotspot.y, vect_rotate_x[1], vect_rotate_y[1]); dest_position[2].y = calc_rotate_y(pixDestX, pixDestY+destHeight, target_rotation_hotspot.x, target_rotation_hotspot.y, vect_rotate_x[1], vect_rotate_y[1]); dest_position[3].y = calc_rotate_y(pixDestX+destWidth, pixDestY+destHeight, target_rotation_hotspot.x, target_rotation_hotspot.y, vect_rotate_x[1], vect_rotate_y[1]); } RenderBatchTriangle *batcher = canvas.impl->batcher.get_triangle_batcher(); batcher->draw_sprite(canvas, texture_position, dest_position, frames[current_frame].texture, color); }