示例#1
0
GPSFilter::GPSFilter(double noise){
  //KalmanFilter alloc_filter_velocity2d(double noise) {
  /* The state model has four dimensions:
     x, y, x', y'
     Each time step we can only observe position, not velocity, so the
     observation vector has only two dimensions.
  */
  f = alloc_filter(4, 2);

  /* Assuming the axes are rectilinear does not work well at the
     poles, but it has the bonus that we don't need to convert between
     lat/long and more rectangular coordinates. The slight inaccuracy
     of our physics model is not too important.
   */
  double v2p = 0.001;
  set_identity_matrix(f.state_transition);
  set_seconds_per_timestep(1.0);
	     
  /* We observe (x, y) in each time step */
  set_matrix(f.observation_model,
	     1.0, 0.0, 0.0, 0.0,
	     0.0, 1.0, 0.0, 0.0);

  /* Noise in the world. */
  double pos = 0.000001;
  set_matrix(f.process_noise_covariance,
	     pos, 0.0, 0.0, 0.0,
	     0.0, pos, 0.0, 0.0,
	     0.0, 0.0, 1.0, 0.0,
	     0.0, 0.0, 0.0, 1.0);

  /* Noise in our observation */
  set_matrix(f.observation_noise_covariance,
	     pos * noise, 0.0,
	     0.0, pos * noise);

  /* The start position is totally unknown, so give a high variance */
  set_matrix(f.state_estimate, 0.0, 0.0, 0.0, 0.0);
  set_identity_matrix(f.estimate_covariance);
  double trillion = 1000.0 * 1000.0 * 1000.0 * 1000.0;
  scale_matrix(f.estimate_covariance, trillion);

  //return f;
}
示例#2
0
文件: matrix.c 项目: xcw0579/mudOS
void f_scale (void)
{
    array_t *matrix;
    double x, y, z;
    Matrix current_matrix;
    Matrix scaling_matrix;
    Matrix final_matrix;
    int i;

    if ((sp - 1)->type != T_REAL) {
        bad_arg(3, F_SCALE);
    }
    if (sp->type != T_REAL) {
        bad_arg(4, F_SCALE);
    }
    /*
     * get arguments from stack.
     */
    matrix = (sp - 3)->u.arr;
    x = (sp - 2)->u.real;
    y = (sp - 1)->u.real;
    z = sp->u.real;
    sp -= 3;
    /*
     * convert vec matrix to float matrix.
     */
    for (i = 0; i < 16; i++) {
        current_matrix[i] = matrix->item[i].u.real;
    }
    /*
     * create scaling matrix.
     */
    scale_matrix(x, y, z, scaling_matrix);
    /*
     * compute transformed matrix.
     */
    mult_matrix(current_matrix, scaling_matrix, final_matrix);
    /*
     * convert float matrix to vec matrix.
     */
    for (i = 0; i < 16; i++) {
        matrix->item[i].u.real = final_matrix[i];
    }
}
示例#3
0
//set view from x,y,z, viewer matrix, and zoom.  Must call one of g3_set_view_*()
void g3_set_view_matrix(vector *view_pos,matrix *view_matrix,float zoom)
{
	Assert( G3_count == 1 );

	View_zoom = zoom;
	View_position = *view_pos;

	View_matrix = *view_matrix;

	Eye_matrix = View_matrix;
	Eye_position = *view_pos;

	scale_matrix();

	Light_matrix = vmd_identity_matrix;
	Light_base.xyz.x = 0.0f;
	Light_base.xyz.y = 0.0f;
	Light_base.xyz.z = 0.0f;

	vm_vec_zero(&Object_position);
	Object_matrix = vmd_identity_matrix;
}
示例#4
0
文件: pmrrr.c 项目: birm/Elemental
int pmrrr
(char *jobz, char *range, int *np, double  *D,
 double *E, double *vl, double *vu, int *il,
 int *iu, int *tryracp, MPI_Comm comm, int *nzp,
 int *offsetp, double *W, double *Z, int *ldz, int *Zsupp)
{
  /* Input parameter */
  int  n      = *np;
  bool onlyW = toupper(jobz[0]) == 'N';
  bool wantZ = toupper(jobz[0]) == 'V';
  bool cntval = toupper(jobz[0]) == 'C';
  bool alleig = toupper(range[0]) == 'A';
  bool valeig = toupper(range[0]) == 'V';
  bool indeig = toupper(range[0]) == 'I';

  /* Check input parameters */
  if(!(onlyW  || wantZ  || cntval)) return 1;
  if(!(alleig || valeig || indeig)) return 1;
  if(n <= 0) return 1;
  if (valeig) {
    if(*vu<=*vl) return 1;
  } else if (indeig) {
    if (*il<1 || *il>n || *iu<*il || *iu>n) return 1;
  }
  
  /* MPI & multithreading info */
  int is_init, is_final;
  MPI_Initialized(&is_init);
  MPI_Finalized(&is_final);
  if (is_init!=1 || is_final==1) {
    fprintf(stderr, "ERROR: MPI is not active! (init=%d, final=%d) \n", 
      is_init, is_final);
    return 1;
  }
  MPI_Comm comm_dup;
  MPI_Comm_dup(comm, &comm_dup);
  int nproc, pid, thread_support;
  MPI_Comm_size(comm_dup, &nproc);
  MPI_Comm_rank(comm_dup, &pid);
  MPI_Query_thread(&thread_support);

  int nthreads;
  if ( !(thread_support == MPI_THREAD_MULTIPLE ||
         thread_support == MPI_THREAD_FUNNELED) ) {
    /* Disable multithreading; note: to support multithreading with 
     * MPI_THREAD_SERIALIZED the code must be changed slightly; this 
     * is not supported at the moment */
    nthreads = 1;
  } else {
    char *ompvar = getenv("PMR_NUM_THREADS");
    if (ompvar == NULL) {
      nthreads = DEFAULT_NUM_THREADS;
    } else {
      nthreads = atoi(ompvar);
    }
  }

#if defined(MVAPICH2_VERSION)
  if (nthreads>1) {
    int mv2_affinity=1;
    char *mv2_string = getenv("MV2_ENABLE_AFFINITY");
    if (mv2_string != NULL) 
      mv2_affinity = atoi(mv2_string);
    if (mv2_affinity!=0) {
      nthreads = 1;
      if (pid==0) {
        fprintf(stderr, "WARNING: PMRRR incurs a significant performance penalty when multithreaded with MVAPICH2 with affinity enabled. The number of threads has been reduced to one; please rerun with MV2_ENABLE_AFFINITY=0 or PMR_NUM_THREADS=1 in the future.\n");
        fflush(stderr);
      }
    }
  }
#endif

  /* If only maximal number of local eigenvectors are queried
   * return if possible here */
  *nzp     = 0;
  *offsetp = 0;
  if (cntval) {
    if ( alleig || n < DSTEMR_IF_SMALLER ) {
      *nzp = iceil(n,nproc);
      MPI_Comm_free(&comm_dup);
      return 0;
    } else if (indeig) {
      *nzp = iceil(*iu-*il+1,nproc);
      MPI_Comm_free(&comm_dup);
      return 0;
    }
  }

  /* Check if computation should be done by multiple processes */
  int info;
  if (n < DSTEMR_IF_SMALLER) {
    info = handle_small_cases(jobz, range, np, D, E, vl, vu, il,
			      iu, tryracp, comm, nzp, offsetp, W,
			      Z, ldz, Zsupp);
    MPI_Comm_free(&comm_dup);
    return info;
  }

  /* Allocate memory */
  double *Werr = (double*)malloc(n*sizeof(double)); assert(Werr!=NULL);
  double *Wgap = (double*)malloc(n*sizeof(double)); assert(Wgap!=NULL);
  double *gersch = (double*)malloc(2*n*sizeof(double)); assert(gersch!=NULL);
  int *iblock = (int*)calloc(n,sizeof(int)); assert(iblock!=NULL);
  int *iproc  = (int*)malloc(n*sizeof(int)); assert(iproc!=NULL);
  int *Windex = (int*)malloc(n*sizeof(int)); assert(Windex!=NULL);
  int *isplit = (int*)malloc(n*sizeof(int)); assert(isplit!=NULL);
  int *Zindex = (int*)malloc(n*sizeof(int)); assert(Zindex!=NULL);
  proc_t *procinfo = (proc_t*)malloc(sizeof(proc_t)); assert(procinfo!=NULL);
  in_t *Dstruct = (in_t*)malloc(sizeof(in_t)); assert(Dstruct!=NULL);
  val_t *Wstruct = (val_t*)malloc(sizeof(val_t)); assert(Wstruct!=NULL);
  vec_t *Zstruct = (vec_t*)malloc(sizeof(vec_t)); assert(Zstruct!=NULL);
  tol_t *tolstruct = (tol_t*)malloc(sizeof(tol_t)); assert(tolstruct!=NULL);

  /* Bundle variables into a structures */
  procinfo->pid            = pid;
  procinfo->nproc          = nproc;
  procinfo->comm           = comm_dup;
  procinfo->nthreads       = nthreads;
  procinfo->thread_support = thread_support;

  Dstruct->n      = n;
  Dstruct->D      = D;
  Dstruct->E      = E;
  Dstruct->isplit = isplit;

  Wstruct->n      = n;
  Wstruct->vl     = vl;
  Wstruct->vu     = vu;
  Wstruct->il     = il;
  Wstruct->iu     = iu;
  Wstruct->W      = W;
  Wstruct->Werr   = Werr;
  Wstruct->Wgap   = Wgap;
  Wstruct->Windex = Windex;
  Wstruct->iblock = iblock;
  Wstruct->iproc  = iproc;
  Wstruct->gersch = gersch;

  Zstruct->ldz    = *ldz;
  Zstruct->nz     = 0;
  Zstruct->Z      = Z;
  Zstruct->Zsupp  = Zsupp;
  Zstruct->Zindex = Zindex;

  /* Scale matrix to allowable range, returns 1.0 if not scaled */
  double scale = scale_matrix(Dstruct, Wstruct, valeig);

  /*  Test if matrix warrants more expensive computations which
   *  guarantees high relative accuracy */
  if (*tryracp)
    odrrr(&n, D, E, &info); /* 0 - rel acc */
  else info = -1;

  int i;
  double *Dcopy, *E2copy;
  if (info == 0) {
    /* This case is extremely rare in practice */ 
    tolstruct->split = DBL_EPSILON;
    /* Copy original data needed for refinement later */
    Dcopy = (double*)malloc(n*sizeof(double)); assert(Dcopy!=NULL);
    memcpy(Dcopy, D, n*sizeof(double));  
    E2copy = (double*)malloc(n*sizeof(double)); assert(E2copy!=NULL);
    for (i=0; i<n-1; i++) 
      E2copy[i] = E[i]*E[i];
  } else {
    /* Neg. threshold forces old splitting criterion */
    tolstruct->split = -DBL_EPSILON; 
    *tryracp = 0;
  }

  if (!wantZ) {
    /* Compute eigenvalues to full precision */
    tolstruct->rtol1 = 4.0 * DBL_EPSILON;
    tolstruct->rtol2 = 4.0 * DBL_EPSILON;
  } else {
    /* Do not compute to full accuracy first, but refine later */
    tolstruct->rtol1 = sqrt(DBL_EPSILON);
    tolstruct->rtol1 = fmin(1e-2*MIN_RELGAP, tolstruct->rtol1);
    tolstruct->rtol2 = sqrt(DBL_EPSILON)*5.0E-3;
    tolstruct->rtol2 = fmin(5e-6*MIN_RELGAP, tolstruct->rtol2);
    tolstruct->rtol2 = fmax(4.0 * DBL_EPSILON, tolstruct->rtol2);
  }

  /*  Compute all eigenvalues: sorted by block */
  info = plarre(procinfo,jobz,range,Dstruct,Wstruct,tolstruct,nzp,offsetp);
  assert(info == 0);

  /* If just number of local eigenvectors are queried */
  if (cntval & valeig) {    
    clean_up(comm_dup, Werr, Wgap, gersch, iblock, iproc, Windex,
	     isplit, Zindex, procinfo, Dstruct, Wstruct, Zstruct,
	     tolstruct);
    return 0;
  }

  /* If only eigenvalues are to be computed */
  if (!wantZ) {

    /* Refine to high relative with respect to input T */
    if (*tryracp) {
      info = 
        refine_to_highrac
        (procinfo, jobz, Dcopy, E2copy, Dstruct, nzp, Wstruct, tolstruct);
      assert(info == 0);
    }

    /* Sort eigenvalues */
    qsort(W, n, sizeof(double), cmp);

    /* Only keep subset ifirst:ilast */
    int ifirst, ilast, isize;
    int iil = *il;
    int iiu = *iu;
    int ifirst_tmp=iil;
    for (i=0; i<nproc; i++) {
      int chunk  = (iiu-iil+1)/nproc + (i < (iiu-iil+1)%nproc);
      int ilast_tmp;
      if (i == nproc-1) {
	ilast_tmp = iiu;
      } else {
	ilast_tmp = ifirst_tmp + chunk - 1;
	ilast_tmp = imin(ilast_tmp, iiu);
      }
      if (i == pid) {
	ifirst    = ifirst_tmp;
	ilast     = ilast_tmp;
	isize     = ilast - ifirst + 1;
	*offsetp = ifirst - iil;
	*nzp      = isize;
      }
      ifirst_tmp = ilast_tmp + 1;
      ifirst_tmp = imin(ifirst_tmp, iiu + 1);
    }
    if (isize > 0) {
      memmove(W, &W[ifirst-1], *nzp * sizeof(double));
    }

    /* If matrix was scaled, rescale eigenvalues */
    invscale_eigenvalues(Wstruct, scale, *nzp);

    clean_up
    (comm_dup, Werr, Wgap, gersch, iblock, iproc, Windex,
     isplit, Zindex, procinfo, Dstruct, Wstruct, Zstruct, tolstruct);

    return 0;
  } /* end of only eigenvalues to compute */

  /* Compute eigenvectors */
  info = plarrv(procinfo, Dstruct, Wstruct, Zstruct, tolstruct, 
		nzp, offsetp);
  assert(info == 0);

  /* Refine to high relative with respect to input matrix */
  if (*tryracp) {
    info = refine_to_highrac(procinfo, jobz, Dcopy, E2copy, 
			     Dstruct, nzp, Wstruct, tolstruct);
    assert(info == 0);
  }

  /* If matrix was scaled, rescale eigenvalues */
  invscale_eigenvalues(Wstruct, scale, n);

  /* Make the first nz elements of W contains the eigenvalues
   * associated to the process */
  int j, im=0;
  for (j=0; j<n; j++) {
    if (iproc[j] == pid) {
      W[im]      = W[j];
      Windex[im] = Windex[j];
      Zindex[im] = Zindex[j];
      im++;
    }
  }

  clean_up(comm_dup, Werr, Wgap, gersch, iblock, iproc, Windex,
	   isplit, Zindex, procinfo, Dstruct, Wstruct, Zstruct,
	   tolstruct);
  if (*tryracp) {
    free(Dcopy);
    free(E2copy);
  }

  return 0;
} /* end pmrrr */
示例#5
0
int rank_double_tab(double** matrix_in, int x, int y)
{
	double **matrix;

	/*
		int n[2], rank;
	

	readmatrix(matrix, n);

	printf("\tThe matrix you have entered is shown below\n\n");
	printmatrix(matrix,n);

	rank =  rank_double_vec(matrix, n[0], n[1]);
	*/
		
    int n[2], i, retest=1, grp, p, r, j, rank;
	int* initzeros;

	matrix = get_double_tab(x,y);
	copy_double_tab(matrix_in, matrix,x, y);

	n[0] = x;
	n[1] = y;
	initzeros = get_int_vec(y);

	/*
	printf("\tThe matrix you have entered is shown below %d , %d\n\n", x, y);
	printmatrix(matrix,n);
	//*/

	update_initzeros(initzeros,matrix,n);
	arrange_matrix(matrix,n,initzeros);

	/*printf("\tThe matrix after arrange  %d , %d\n\n", x, y);
	printmatrix(matrix,n);
	
	

	if(matrix[0][0]==0)
	{
	printf("\n\tError: Invalid Marix \n\n");
	}

	*/

	update_initzeros(initzeros,matrix,n);
	scale_matrix(matrix,n,initzeros);

	while(retest==1)
	{
		grp=0;
		for(i=0;i<n[0];++i)
		{
			p=0;
			while(initzeros[i+p]==initzeros[i+p+1]&&(i+p+1)<n[0])
			{
				grp=grp+1;
				p=p+1;
			}

			if(grp!=0)
			{
				while(grp!=0)
				{
					for(j=0;j<n[1];++j)
					{
						matrix[i+grp][j]=matrix[i+grp][j]-matrix[i][j];
					}
					grp=grp-1;
				}
			break;
			}
		}	

		update_initzeros(initzeros,matrix,n);
		arrange_matrix(matrix,n,initzeros);
		update_initzeros(initzeros,matrix,n);
		scale_matrix(matrix,n,initzeros);

		retest=0;
		for(r=0;r<n[0];++r)
		{
			if(initzeros[r]==initzeros[r+1]&&r+1<n[0])
			{
				if(initzeros[r]!=n[1])
				retest=1;
			}
		}
	}

	//printf("\n\n\t Reduced matrix is as shown below\n\n");
	//printmatrix(matrix,n);

	rank =0;
	for (i=0;i<n[0];++i)
	{
		if (initzeros[i]!=n[1])
		{
			++rank;
		}
	}

	free_double_tab(matrix, n[0]);

	//printf("\n Rank Of The Matrix = %d\n\n", rank); 

	return rank;
}
示例#6
0
static int calccoef(struct Control_Points_3D *cp, double OR[], int ndims)
{
    double **src_mat = NULL;
    double **src_mat_T = NULL;
    double **dest_mat = NULL;
    double **dest_mat_T = NULL;
    double **src_dest_mat = NULL;
    double *S_vec = NULL;
    double **R_mat = NULL;
    double **R_mat_T = NULL;
    double **mat_mn1 = NULL;
    double **mat_mn2 = NULL;
    double **mat_nm1 = NULL;
    double **mat_nm2 = NULL;
    double **mat_nn1 = NULL;
    double **E_mat = NULL;
    double **P_mat = NULL;
    double **Q_mat = NULL;
    double *D_vec = NULL;
    double *one_vec = NULL;
    double trace1 = 0.0;
    double trace2 = 0.0;
    int numactive;		/* NUMBER OF ACTIVE CONTROL POINTS */
    int m, n, i, j;
    int status;

    /* CALCULATE THE NUMBER OF VALID CONTROL POINTS */

    for (i = numactive = 0; i < cp->count; i++) {
	if (cp->status[i] > 0)
	    numactive++;
    }
    m = numactive;
    n = ndims;

    src_mat = G_alloc_matrix(m, n);
    dest_mat = G_alloc_matrix(m, n);

    for (i = numactive = 0; i < cp->count; i++) {
	if (cp->status[i] > 0) {
	    src_mat[numactive][0] = cp->e1[i];
	    src_mat[numactive][1] = cp->n1[i];
	    src_mat[numactive][2] = cp->z1[i];

	    dest_mat[numactive][0] = cp->e2[i];
	    dest_mat[numactive][1] = cp->n2[i];
	    dest_mat[numactive][2] = cp->z2[i];

	    numactive++;
	}
    }

    D_vec = G_alloc_vector(ndims);

    src_mat_T = G_alloc_matrix(n, m);
    dest_mat_T = G_alloc_matrix(n, m);
    src_dest_mat = G_alloc_matrix(n, n);
    R_mat = G_alloc_matrix(n, n);
    R_mat_T = G_alloc_matrix(n, n);

    mat_mn1 = G_alloc_matrix(m, n);
    mat_mn2 = G_alloc_matrix(m, n);
    mat_nm1 = G_alloc_matrix(n, m);
    mat_nm2 = G_alloc_matrix(n, m);
    mat_nn1 = G_alloc_matrix(n, n);

    E_mat = G_alloc_matrix(m, m);
    P_mat = G_alloc_matrix(ndims, ndims);
    Q_mat = G_alloc_matrix(ndims, ndims);

    transpose_matrix(m, n, dest_mat, dest_mat_T);

    for (i = 0; i < m; i++) {
	for (j = 0; j < m; j++) {
	    if (i != j) {
		E_mat[i][j] = -1.0 / (double)m;
	    }
	    else{
		E_mat[i][j] = 1.0 - 1.0 / (double)m;
	    }
	}
    }

    matmult(n, m, m, dest_mat_T, E_mat, mat_nm1);
    matmult(n, m, n, mat_nm1, src_mat, src_dest_mat);
    copy_matrix(n, n, src_dest_mat, P_mat);
    copy_matrix(n, n, src_dest_mat, mat_nn1);

    status = G_math_svduv(D_vec, mat_nn1, P_mat, n, Q_mat, n);

    if (status == 0)
	status = MSUCCESS;

    transpose_matrix(n, n, P_mat, mat_nn1);

    /* rotation matrix */
    matmult(n, n, n, Q_mat, mat_nn1, R_mat_T);
    transpose_matrix(n, n, R_mat_T, R_mat);

    /* scale */
    matmult(n, n, n, src_dest_mat, R_mat_T, mat_nn1);
    trace1 = trace(n, n, mat_nn1);

    transpose_matrix(m, n, src_mat, src_mat_T);
    matmult(n, m, m, src_mat_T, E_mat, mat_nm1);
    matmult(n, m, n, mat_nm1, src_mat, mat_nn1);
    trace2 = trace(n, n, mat_nn1);

    OR[14] = trace1 / trace2;

    /* shifts */
    matmult(m, n, n, src_mat, R_mat_T, mat_mn1);
    scale_matrix(m, n, OR[14], mat_mn1, mat_mn2);
    subtract_matrix(m, n, dest_mat, mat_mn2, mat_mn1);
    scale_matrix(m, n, 1.0 / m, mat_mn1, mat_mn2);
    transpose_matrix(m, n, mat_mn2, mat_nm1);

    S_vec = G_alloc_vector(n);
    one_vec = G_alloc_vector(m);

    for (i = 0; i < m; i++){
	one_vec[i] = 1.0;
    }

    matrix_multiply(n, m, mat_nm1, one_vec, S_vec);

    /* matrix to vector */
    for (i = 0; i < ndims; i++) {
	for (j = 0; j < ndims; j++) {
	    OR[i * ndims + j] = R_mat[i][j];
	}
    }
    
    G_free_matrix(src_mat);
    G_free_matrix(src_mat_T);
    G_free_matrix(dest_mat);
    G_free_matrix(dest_mat_T);
    G_free_matrix(src_dest_mat);
    G_free_vector(D_vec);
    G_free_matrix(E_mat);
    G_free_matrix(P_mat);
    G_free_matrix(Q_mat);
    G_free_matrix(R_mat);
    G_free_matrix(R_mat_T);
    G_free_matrix(mat_mn1);
    G_free_matrix(mat_mn2);
    G_free_matrix(mat_nm1);
    G_free_matrix(mat_nm2);
    G_free_matrix(mat_nn1);
    G_free_vector(S_vec);
    G_free_vector(one_vec);

    return status;
}
示例#7
0
void convert_model_material(model_uniform_data* data_out,
							const model_material& material,
							const matrix4& model_transform,
							const vec3d& scale,
							size_t transform_buffer_offset) {
	auto shader_flags = material.get_shader_flags();

	Assertion(gr_model_matrix_stack.depth() == 1, "Uniform conversion does not respect previous transforms! "
		"Model matrix stack must be empty!");

	matrix4 scaled_matrix = model_transform;
	scale_matrix(scaled_matrix, scale);

	data_out->modelMatrix = scaled_matrix;
	data_out->viewMatrix = gr_view_matrix;
	vm_matrix4_x_matrix4(&data_out->modelViewMatrix, &data_out->viewMatrix, &data_out->modelMatrix);
	data_out->projMatrix = gr_projection_matrix;
	data_out->textureMatrix = gr_texture_matrix;

	data_out->color = material.get_color();

	if (shader_flags & SDR_FLAG_MODEL_ANIMATED) {
		data_out->anim_timer = material.get_animated_effect_time();
		data_out->effect_num = material.get_animated_effect();
		data_out->vpwidth = 1.0f / i2fl(gr_screen.max_w);
		data_out->vpheight = 1.0f / i2fl(gr_screen.max_h);
	}

	if (shader_flags & SDR_FLAG_MODEL_CLIP) {
		if (material.is_clipped()) {
			auto& clip_info = material.get_clip_plane();

			data_out->use_clip_plane = true;

			vec4 clip_equation;
			clip_equation.xyzw.x = clip_info.normal.xyz.x;
			clip_equation.xyzw.y = clip_info.normal.xyz.y;
			clip_equation.xyzw.z = clip_info.normal.xyz.z;
			clip_equation.xyzw.w = -vm_vec_dot(&clip_info.normal, &clip_info.position);
			data_out->clip_equation = clip_equation;
		} else {
			data_out->use_clip_plane = false;
		}
	}

	if (shader_flags & SDR_FLAG_MODEL_LIGHT) {
		int num_lights = MIN(Num_active_gr_lights, (int)graphics::MAX_UNIFORM_LIGHTS);
		data_out->n_lights = num_lights;

		std::copy(std::begin(gr_light_uniforms), std::end(gr_light_uniforms), std::begin(data_out->lights));

		float light_factor = material.get_light_factor();
		data_out->diffuseFactor.xyz.x = gr_light_color[0] * light_factor;
		data_out->diffuseFactor.xyz.y = gr_light_color[1] * light_factor;
		data_out->diffuseFactor.xyz.z = gr_light_color[2] * light_factor;
		data_out->ambientFactor.xyz.x = gr_light_ambient[0];
		data_out->ambientFactor.xyz.y = gr_light_ambient[1];
		data_out->ambientFactor.xyz.z = gr_light_ambient[2];

		if (material.get_light_factor() > 0.25f && !Cmdline_no_emissive) {
			data_out->emissionFactor.xyz.x = gr_light_emission[0];
			data_out->emissionFactor.xyz.y = gr_light_emission[1];
			data_out->emissionFactor.xyz.z = gr_light_emission[2];
		} else {
			data_out->emissionFactor.xyz.x = gr_light_zero[0];
			data_out->emissionFactor.xyz.y = gr_light_zero[1];
			data_out->emissionFactor.xyz.z = gr_light_zero[2];
		}

		if (Gloss_override_set) {
			data_out->defaultGloss = Gloss_override;
		} else {
			data_out->defaultGloss = 0.6f;
		}
	}

	if (shader_flags & SDR_FLAG_MODEL_DIFFUSE_MAP) {
		if (material.is_desaturated()) {
			data_out->desaturate = 1;
		} else {
			data_out->desaturate = 0;
		}

		if (Basemap_color_override_set) {
			data_out->overrideDiffuse = 1;
			data_out->diffuseClr.xyz.x = Basemap_color_override[0];
			data_out->diffuseClr.xyz.y = Basemap_color_override[1];
			data_out->diffuseClr.xyz.z = Basemap_color_override[2];
		} else {
			data_out->overrideDiffuse = 0;
		}

		switch (material.get_blend_mode()) {
		case ALPHA_BLEND_PREMULTIPLIED:
			data_out->blend_alpha = 1;
			break;
		case ALPHA_BLEND_ADDITIVE:
			data_out->blend_alpha = 2;
			break;
		default:
			data_out->blend_alpha = 0;
			break;
		}

		data_out->sBasemapIndex = bm_get_array_index(material.get_texture_map(TM_BASE_TYPE));
	}

	if (shader_flags & SDR_FLAG_MODEL_GLOW_MAP) {
		if (Glowmap_color_override_set) {
			data_out->overrideGlow = 1;
			data_out->glowClr.xyz.x = Glowmap_color_override[0];
			data_out->glowClr.xyz.y = Glowmap_color_override[1];
			data_out->glowClr.xyz.z = Glowmap_color_override[2];
		} else {
			data_out->overrideGlow = 0;
		}
		data_out->sGlowmapIndex = bm_get_array_index(material.get_texture_map(TM_GLOW_TYPE));
	}

	if (shader_flags & SDR_FLAG_MODEL_SPEC_MAP) {
		if (Specmap_color_override_set) {
			data_out->overrideSpec = 1;
			data_out->specClr.xyz.x = Specmap_color_override[0];
			data_out->specClr.xyz.y = Specmap_color_override[1];
			data_out->specClr.xyz.z = Specmap_color_override[2];
		} else {
			data_out->overrideSpec = 0;
		}

		if (material.get_texture_map(TM_SPEC_GLOSS_TYPE) > 0) {
			data_out->sSpecmapIndex = bm_get_array_index(material.get_texture_map(TM_SPEC_GLOSS_TYPE));

			data_out->gammaSpec = 1;

			if (Gloss_override_set) {
				data_out->alphaGloss = 0;
			} else {
				data_out->alphaGloss = 1;
			}
		} else {
			data_out->sSpecmapIndex = bm_get_array_index(material.get_texture_map(TM_SPECULAR_TYPE));

			data_out->gammaSpec = 0;
			data_out->alphaGloss = 0;
		}

		if (shader_flags & SDR_FLAG_MODEL_ENV_MAP) {
			if (material.get_texture_map(TM_SPEC_GLOSS_TYPE) > 0 || Gloss_override_set) {
				data_out->envGloss = 1;
			} else {
				data_out->envGloss = 0;
			}

			data_out->envMatrix = gr_env_texture_matrix;
		}
	}

	if ( shader_flags & SDR_FLAG_MODEL_NORMAL_MAP ) {
		data_out->sNormalmapIndex = bm_get_array_index(material.get_texture_map(TM_NORMAL_TYPE));
	}

	if ( shader_flags & SDR_FLAG_MODEL_AMBIENT_MAP ) {
		data_out->sAmbientmapIndex = bm_get_array_index(material.get_texture_map(TM_AMBIENT_TYPE));
	}

	if ( shader_flags & SDR_FLAG_MODEL_MISC_MAP ) {
		data_out->sMiscmapIndex = bm_get_array_index(material.get_texture_map(TM_MISC_TYPE));
	}

	if (shader_flags & SDR_FLAG_MODEL_SHADOWS) {
		data_out->shadow_mv_matrix = Shadow_view_matrix;

		for (size_t i = 0; i < MAX_SHADOW_CASCADES; ++i) {
			data_out->shadow_proj_matrix[i] = Shadow_proj_matrix[i];
		}

		data_out->veryneardist = Shadow_cascade_distances[0];
		data_out->neardist = Shadow_cascade_distances[1];
		data_out->middist = Shadow_cascade_distances[2];
		data_out->fardist = Shadow_cascade_distances[3];
	}

	if (shader_flags & SDR_FLAG_MODEL_SHADOW_MAP) {
		for (size_t i = 0; i < MAX_SHADOW_CASCADES; ++i) {
			data_out->shadow_proj_matrix[i] = Shadow_proj_matrix[i];
		}
	}

	if (shader_flags & SDR_FLAG_MODEL_TRANSFORM) {
		data_out->buffer_matrix_offset = (int) transform_buffer_offset;
	}

	// Team colors are passed to the shader here, but the shader needs to handle their application.
	// By default, this is handled through the r and g channels of the misc map, but this can be changed
	// in the shader; test versions of this used the normal map r and b channels
	if (shader_flags & SDR_FLAG_MODEL_TEAMCOLOR) {
		auto& tm_clr = material.get_team_color();
		vec3d stripe_color;
		vec3d base_color;

		stripe_color.xyz.x = tm_clr.stripe.r;
		stripe_color.xyz.y = tm_clr.stripe.g;
		stripe_color.xyz.z = tm_clr.stripe.b;

		base_color.xyz.x = tm_clr.base.r;
		base_color.xyz.y = tm_clr.base.g;
		base_color.xyz.z = tm_clr.base.b;

		data_out->stripe_color = stripe_color;
		data_out->base_color = base_color;
	}

	if (shader_flags & SDR_FLAG_MODEL_THRUSTER) {
		data_out->thruster_scale = material.get_thrust_scale();
	}


	if (shader_flags & SDR_FLAG_MODEL_FOG) {
		material::fog fog_params = material.get_fog();

		if (fog_params.enabled) {
			data_out->fogStart = fog_params.dist_near;
			data_out->fogScale = 1.0f / (fog_params.dist_far - fog_params.dist_near);
			data_out->fogColor.xyzw.x = i2fl(fog_params.r) / 255.0f;
			data_out->fogColor.xyzw.y = i2fl(fog_params.g) / 255.0f;
			data_out->fogColor.xyzw.z = i2fl(fog_params.b) / 255.0f;
			data_out->fogColor.xyzw.w = 1.0f;
		}
	}

	if (shader_flags & SDR_FLAG_MODEL_NORMAL_ALPHA) {
		data_out->normalAlphaMinMax.x = material.get_normal_alpha_min();
		data_out->normalAlphaMinMax.y = material.get_normal_alpha_max();
	}

	if (shader_flags & SDR_FLAG_MODEL_NORMAL_EXTRUDE) {
		data_out->extrudeWidth = material.get_normal_extrude_width();
	}
}
示例#8
0
文件: d2d1.c 项目: VOID001/wine-void
static void test_color_brush(void)
{
    D2D1_MATRIX_3X2_F matrix, tmp_matrix;
    D2D1_BRUSH_PROPERTIES brush_desc;
    D2D1_COLOR_F color, tmp_color;
    ID2D1SolidColorBrush *brush;
    IDXGISwapChain *swapchain;
    ID2D1RenderTarget *rt;
    ID3D10Device1 *device;
    IDXGISurface *surface;
    D2D1_RECT_F rect;
    float opacity;
    HWND window;
    HRESULT hr;

    if (!(device = create_device()))
    {
        skip("Failed to create device, skipping tests.\n");
        return;
    }
    window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
            0, 0, 640, 480, NULL, NULL, NULL, NULL);
    swapchain = create_swapchain(device, window, TRUE);
    hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
    ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
    rt = create_render_target(surface);
    ok(!!rt, "Failed to create render target.\n");

    ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
    ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);

    set_color(&color, 0.0f, 0.0f, 0.0f, 0.0f);
    hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
    ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
    opacity = ID2D1SolidColorBrush_GetOpacity(brush);
    ok(opacity == 1.0f, "Got unexpected opacity %.8e.\n", opacity);
    set_matrix_identity(&matrix);
    ID2D1SolidColorBrush_GetTransform(brush, &tmp_matrix);
    ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
            "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
            tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
            tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
    tmp_color = ID2D1SolidColorBrush_GetColor(brush);
    ok(!memcmp(&tmp_color, &color, sizeof(color)),
            "Got unexpected color {%.8e, %.8e, %.8e, %.8e}.\n",
            tmp_color.r, tmp_color.g, tmp_color.b, tmp_color.a);
    ID2D1SolidColorBrush_Release(brush);

    set_color(&color, 0.0f, 1.0f, 0.0f, 0.8f);
    brush_desc.opacity = 0.3f;
    set_matrix_identity(&matrix);
    scale_matrix(&matrix, 2.0f, 2.0f);
    brush_desc.transform = matrix;
    hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, &brush_desc, &brush);
    ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
    opacity = ID2D1SolidColorBrush_GetOpacity(brush);
    ok(opacity == 0.3f, "Got unexpected opacity %.8e.\n", opacity);
    ID2D1SolidColorBrush_GetTransform(brush, &tmp_matrix);
    ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
            "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
            tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
            tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
    tmp_color = ID2D1SolidColorBrush_GetColor(brush);
    ok(!memcmp(&tmp_color, &color, sizeof(color)),
            "Got unexpected color {%.8e, %.8e, %.8e, %.8e}.\n",
            tmp_color.r, tmp_color.g, tmp_color.b, tmp_color.a);

    ID2D1RenderTarget_BeginDraw(rt);

    set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
    ID2D1RenderTarget_Clear(rt, &color);

    ID2D1SolidColorBrush_SetOpacity(brush, 1.0f);
    set_rect(&rect, 40.0f, 120.0f, 120.0f, 360.0f);
    ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)brush);

    set_matrix_identity(&matrix);
    scale_matrix(&matrix, 0.5f, 2.0f);
    translate_matrix(&matrix, 320.0f, 240.0f);
    rotate_matrix(&matrix, M_PI / 4.0f);
    ID2D1RenderTarget_SetTransform(rt, &matrix);
    set_color(&color, 1.0f, 0.0f, 0.0f, 0.625f);
    ID2D1SolidColorBrush_SetColor(brush, &color);
    ID2D1SolidColorBrush_SetOpacity(brush, 0.75f);
    set_rect(&rect, -80.0f, -60.0f, 80.0f, 60.0f);
    ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)brush);

    hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
    ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
    ok(compare_surface(surface, "6d1218fca5e21fb7e287b3a439d60dbc251f5ceb"), "Surface does not match.\n");

    ID2D1SolidColorBrush_Release(brush);
    ID2D1RenderTarget_Release(rt);
    IDXGISurface_Release(surface);
    IDXGISwapChain_Release(swapchain);
    ID3D10Device1_Release(device);
    DestroyWindow(window);
}
示例#9
0
void scale(double sx, double sy, double sz, matrix m) {
	matrix temp = mat_mat_multiply(scale_matrix(sx, sy, sz), m);
	memcpy(m, temp, 16 * sizeof(double));
	free(temp);
}
示例#10
0
static void set_view_trans_mat(
/*****************************/
/* This function examines the values in view and fills in  the ViewTrans */
/* matrix. This will be either the Nper' or Npar matrix described in */
/* sections 6.5.1 and 6.5.2. The Nper' matrix include the perspective  */
/* transformation matrix. */
    pipe_view   *view
) {
    matrix4     *mat1,*mat2,*mat3;  /* temporary matricies */
    vector      dop;                /* direction of projection after */
                                    /* trans and rotation */
    float       vrpz1;              /* vprz' used only for perspective */

    /* allocate the temporary matricies */
    _new( mat1, 1 );
    _new( mat2, 1 );
    _new( mat3, 1 );

    /* these matrices are common to both types of projection */
    trans_matrix( mat1->m, -view->ViewRefPt.p[0], -view->ViewRefPt.p[1],
                 -view->ViewRefPt.p[2] );

    form_rotation_matrix( mat2->m, view->ViewPlNorm, view->VUp );
    matrix_mult( mat2->m, mat1->m, mat3->m );
    /* we can reuse mat2->m and mat1->m now */

    if (view->type == PROJ_PARALLEL) {
    /* form the Npar matrix */
        dop.v[0] = (view->umax + view->umin) / 2.0 - view->ProjRefPt.p[0];
        dop.v[1] = (view->vmax + view->vmin) / 2.0 - view->ProjRefPt.p[1];
        dop.v[2] = -view->ProjRefPt.p[2];
        dop.v[3] = 0;
        shear_xy_matrix( mat1->m, -dop.v[0]/dop.v[2], -dop.v[1]/dop.v[2] );
        matrix_mult( mat1->m, mat3->m, mat2->m );
        /* reuse 1 and 3 */

        trans_matrix( mat1->m, (-view->umax - view->umin) / 2.0,
                            (-view->vmax - view->vmin) / 2.0,
                            -view->FrontClip );
        matrix_mult( mat1->m, mat2->m, mat3->m );
        /* reuse 1 and 2 */

        scale_matrix( mat1->m, 2.0 / (view->umax - view->umin),
                            2.0 / (view->vmax - view->vmin),
                            1. / (view->FrontClip - view->BackClip) );
        matrix_mult( mat1->m, mat3->m, ViewTrans );
    } else {
    /* form the Nper' matrix including the perspective transformation */
        trans_matrix( mat1->m, -view->ProjRefPt.p[0],
                            -view->ProjRefPt.p[1], -view->ProjRefPt.p[2] );
        matrix_mult( mat1->m, mat3->m, mat2->m );
        /* reuse 1 and 3 */

        /* This is the same shear as for Npar. See p. 269 for why. */
        dop.v[0] = (view->umax + view->umin) / 2.0 - view->ProjRefPt.p[0];
        dop.v[1] = (view->vmax + view->vmin) / 2.0 - view->ProjRefPt.p[1];
        dop.v[2] = -view->ProjRefPt.p[2];
        dop.v[3] = 0;
        shear_xy_matrix( mat1->m, -dop.v[0]/dop.v[2], -dop.v[1]/dop.v[2] );
        matrix_mult( mat1->m, mat2->m, mat3->m );
        /* reuse 1 and 2 */

        vrpz1 = -view->ProjRefPt.p[2];
        scale_matrix( mat1->m,
            2.0*vrpz1 / ((view->umax - view->umin)*(vrpz1 + view->BackClip)),
            2.0*vrpz1 / ((view->vmax - view->vmin)*(vrpz1 + view->BackClip)),
            -1.0 / (vrpz1 + view->BackClip) );
        matrix_mult( mat1->m, mat3->m, mat2->m );
        /* reuse 1 and 3 */

        persp_trans_matrix( mat1->m,
             -(vrpz1 + view->FrontClip)/(vrpz1 + view->BackClip) );

        matrix_mult( mat1->m, mat2->m, ViewTrans );
    }

    /* free the temporary matrices */
    _free( mat1 );
    _free( mat2 );
    _free( mat3 );
}
示例#11
0
文件: d2d1.c 项目: noruya/wine
static void test_bitmap_brush(void)
{
    D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode;
    D2D1_MATRIX_3X2_F matrix, tmp_matrix;
    D2D1_BITMAP_PROPERTIES bitmap_desc;
    ID2D1Bitmap *bitmap, *tmp_bitmap;
    D2D1_RECT_F src_rect, dst_rect;
    D2D1_EXTEND_MODE extend_mode;
    IDXGISwapChain *swapchain;
    ID2D1BitmapBrush *brush;
    ID2D1RenderTarget *rt;
    ID3D10Device1 *device;
    IDXGISurface *surface;
    D2D1_COLOR_F color;
    D2D1_SIZE_U size;
    ULONG refcount;
    float opacity;
    HWND window;
    HRESULT hr;

    static const DWORD bitmap_data[] =
    {
        0xffff0000, 0xffffff00, 0xff00ff00, 0xff00ffff,
        0xff0000ff, 0xffff00ff, 0xff000000, 0xff7f7f7f,
        0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
        0xffffffff, 0xff000000, 0xff000000, 0xff000000,
    };

    if (!(device = create_device()))
    {
        skip("Failed to create device, skipping tests.\n");
        return;
    }
    window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
            0, 0, 640, 480, NULL, NULL, NULL, NULL);
    swapchain = create_swapchain(device, window, TRUE);
    hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
    ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
    rt = create_render_target(surface);
    ok(!!rt, "Failed to create render target.\n");

    ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
    ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);

    set_size_u(&size, 4, 4);
    bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
    bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
    bitmap_desc.dpiX = 96.0f;
    bitmap_desc.dpiY = 96.0f;
    hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
    ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);

    /* Creating a brush with a NULL bitmap crashes on Vista, but works fine on
     * Windows 7+. */
    hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &brush);
    ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
    ID2D1BitmapBrush_GetBitmap(brush, &tmp_bitmap);
    ok(tmp_bitmap == bitmap, "Got unexpected bitmap %p, expected %p.\n", tmp_bitmap, bitmap);
    ID2D1Bitmap_Release(tmp_bitmap);
    opacity = ID2D1BitmapBrush_GetOpacity(brush);
    ok(opacity == 1.0f, "Got unexpected opacity %.8e.\n", opacity);
    set_matrix_identity(&matrix);
    ID2D1BitmapBrush_GetTransform(brush, &tmp_matrix);
    ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
            "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
            tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
            tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
    extend_mode = ID2D1BitmapBrush_GetExtendModeX(brush);
    ok(extend_mode == D2D1_EXTEND_MODE_CLAMP, "Got unexpected extend mode %#x.\n", extend_mode);
    extend_mode = ID2D1BitmapBrush_GetExtendModeY(brush);
    ok(extend_mode == D2D1_EXTEND_MODE_CLAMP, "Got unexpected extend mode %#x.\n", extend_mode);
    interpolation_mode = ID2D1BitmapBrush_GetInterpolationMode(brush);
    ok(interpolation_mode == D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
            "Got unexpected interpolation mode %#x.\n", interpolation_mode);
    ID2D1BitmapBrush_Release(brush);

    hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &brush);
    ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
    set_matrix_identity(&matrix);
    translate_matrix(&matrix, 40.0f, 120.0f);
    scale_matrix(&matrix, 20.0f, 60.0f);
    ID2D1BitmapBrush_SetTransform(brush, &matrix);
    ID2D1BitmapBrush_SetInterpolationMode(brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);

    ID2D1RenderTarget_BeginDraw(rt);

    set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
    ID2D1RenderTarget_Clear(rt, &color);

    set_rect(&dst_rect, 40.0f, 120.0f, 120.0f, 360.0f);
    ID2D1RenderTarget_FillRectangle(rt, &dst_rect, (ID2D1Brush *)brush);

    set_matrix_identity(&matrix);
    scale_matrix(&matrix, 0.5f, 2.0f);
    translate_matrix(&matrix, 320.0f, 240.0f);
    rotate_matrix(&matrix, M_PI / 4.0f);
    ID2D1RenderTarget_SetTransform(rt, &matrix);
    set_matrix_identity(&matrix);
    translate_matrix(&matrix, -80.0f, -60.0f);
    scale_matrix(&matrix, 40.0f, 30.0f);
    ID2D1BitmapBrush_SetTransform(brush, &matrix);
    ID2D1BitmapBrush_SetOpacity(brush, 0.75f);
    set_rect(&dst_rect, -80.0f, -60.0f, 80.0f, 60.0f);
    ID2D1RenderTarget_FillRectangle(rt, &dst_rect, (ID2D1Brush *)brush);

    set_matrix_identity(&matrix);
    translate_matrix(&matrix, 200.0f, 120.0f);
    scale_matrix(&matrix, 20.0f, 60.0f);
    ID2D1RenderTarget_SetTransform(rt, &matrix);
    ID2D1RenderTarget_DrawBitmap(rt, bitmap, NULL, 0.25f,
            D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
    set_rect(&dst_rect, -4.0f, 12.0f, -8.0f, 8.0f);
    ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 0.75f,
            D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
    set_rect(&dst_rect, 0.0f, 8.0f, 4.0f, 12.0f);
    set_rect(&src_rect, 2.0f, 1.0f, 4.0f, 3.0f);
    ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 1.0f,
            D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, &src_rect);

    hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
    ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
    ok(compare_surface(surface, "393636185359a550d459e1e5f0e25411814f724c"), "Surface does not match.\n");

    ID2D1BitmapBrush_Release(brush);
    refcount = ID2D1Bitmap_Release(bitmap);
    ok(!refcount, "Bitmap has %u references left.\n", refcount);
    ID2D1RenderTarget_Release(rt);
    IDXGISurface_Release(surface);
    IDXGISwapChain_Release(swapchain);
    ID3D10Device1_Release(device);
    DestroyWindow(window);
}