Exemplo n.º 1
0
static GLboolean r300RunRender(GLcontext * ctx,
			       struct tnl_pipeline_stage *stage)
{
	r300ContextPtr rmesa = R300_CONTEXT(ctx);
	struct radeon_vertex_buffer *VB = &rmesa->state.VB;
	int i;
	int cmd_reserved = 0;
	int cmd_written = 0;
	drm_radeon_cmd_header_t *cmd = NULL;

	if (RADEON_DEBUG & DEBUG_PRIMS)
		fprintf(stderr, "%s\n", __FUNCTION__);

	if (stage) {
		TNLcontext *tnl = TNL_CONTEXT(ctx);
		radeon_vb_to_rvb(rmesa, VB, &tnl->vb);
	}

	r300UpdateShaders(rmesa);
	if (r300EmitArrays(ctx))
		return GL_TRUE;

	r300UpdateShaderStates(rmesa);

	reg_start(R300_RB3D_DSTCACHE_CTLSTAT, 0);
	e32(R300_RB3D_DSTCACHE_UNKNOWN_0A);

	reg_start(R300_RB3D_ZCACHE_CTLSTAT, 0);
	e32(R300_RB3D_ZCACHE_UNKNOWN_03);

	r300EmitState(rmesa);

	for (i = 0; i < VB->PrimitiveCount; i++) {
		GLuint prim = _tnl_translate_prim(&VB->Primitive[i]);
		GLuint start = VB->Primitive[i].start;
		GLuint end = VB->Primitive[i].start + VB->Primitive[i].count;
		r300RunRenderPrimitive(rmesa, ctx, start, end, prim);
	}

	reg_start(R300_RB3D_DSTCACHE_CTLSTAT, 0);
	e32(R300_RB3D_DSTCACHE_UNKNOWN_0A);

	reg_start(R300_RB3D_ZCACHE_CTLSTAT, 0);
	e32(R300_RB3D_ZCACHE_UNKNOWN_03);

#ifdef USER_BUFFERS
	r300UseArrays(ctx);
#endif

	r300ReleaseArrays(ctx);

	return GL_FALSE;
}
static void r300FireEB(r300ContextPtr rmesa, unsigned long addr,
		       int vertex_count, int type)
{
	int cmd_reserved = 0;
	int cmd_written = 0;
	drm_radeon_cmd_header_t *cmd = NULL;

	start_packet3(CP_PACKET3(R300_PACKET3_3D_DRAW_INDX_2, 0), 0);
	e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (vertex_count << 16) | type | R300_VAP_VF_CNTL__INDEX_SIZE_32bit);

	start_packet3(CP_PACKET3(R300_PACKET3_INDX_BUFFER, 2), 2);
	e32(R300_EB_UNK1 | (0 << 16) | R300_EB_UNK2);
	e32(addr);
	e32(vertex_count);
}
static void r300FireAOS(r300ContextPtr rmesa, int vertex_count, int type)
{
	int cmd_reserved = 0;
	int cmd_written = 0;
	drm_radeon_cmd_header_t *cmd = NULL;

	start_packet3(CP_PACKET3(R300_PACKET3_3D_DRAW_VBUF_2, 0), 0);
	e32(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (vertex_count << 16) | type);
}
static void r300EmitAOS(r300ContextPtr rmesa, GLuint nr, GLuint offset)
{
	int sz = 1 + (nr >> 1) * 3 + (nr & 1) * 2;
	int i;
	int cmd_reserved = 0;
	int cmd_written = 0;
	drm_radeon_cmd_header_t *cmd = NULL;

	if (RADEON_DEBUG & DEBUG_VERTS)
		fprintf(stderr, "%s: nr=%d, ofs=0x%08x\n", __FUNCTION__, nr,
			offset);

	start_packet3(CP_PACKET3(R300_PACKET3_3D_LOAD_VBPNTR, sz - 1), sz - 1);
	e32(nr);

	for (i = 0; i + 1 < nr; i += 2) {
		e32((rmesa->state.aos[i].aos_size << 0) |
		    (rmesa->state.aos[i].aos_stride << 8) |
		    (rmesa->state.aos[i + 1].aos_size << 16) |
		    (rmesa->state.aos[i + 1].aos_stride << 24));

		e32(rmesa->state.aos[i].aos_offset + offset * 4 * rmesa->state.aos[i].aos_stride);
		e32(rmesa->state.aos[i + 1].aos_offset + offset * 4 * rmesa->state.aos[i + 1].aos_stride);
	}

	if (nr & 1) {
		e32((rmesa->state.aos[nr - 1].aos_size << 0) |
		    (rmesa->state.aos[nr - 1].aos_stride << 8));
		e32(rmesa->state.aos[nr - 1].aos_offset + offset * 4 * rmesa->state.aos[nr - 1].aos_stride);
	}
}
Exemplo n.º 5
0
static void r300_render_vb_primitive(r300ContextPtr rmesa,
	GLcontext *ctx,
	int start,
	int end,
	int prim)
{
   int type, num_verts;

   type=r300_get_primitive_type(rmesa, ctx, prim);
   num_verts=r300_get_num_verts(rmesa, ctx, end-start, prim);

   if(type<0 || num_verts <= 0)return;

   if(rmesa->state.VB.Elts){
	r300EmitAOS(rmesa, rmesa->state.aos_count, /*0*/start);
#if 0
	LOCAL_VARS
	int i;
	start_index32_packet(num_verts, type);
	for(i=0; i < num_verts; i++)
		e32(((unsigned long *)rmesa->state.VB.Elts)[i]/*rmesa->state.Elts[start+i]*/); /* start ? */
#else
	if(num_verts == 1){
		//start_index32_packet(num_verts, type);
		//e32(rmesa->state.Elts[start]);
		return;
	}
	
	if(num_verts > 65535){ /* not implemented yet */
		WARN_ONCE("Too many elts\n");
		return;
	}
	
	r300EmitElts(ctx, rmesa->state.VB.Elts, num_verts, rmesa->state.VB.elt_size);
	fire_EB(PASS_PREFIX rmesa->state.elt_dma.aos_offset, num_verts, type, rmesa->state.VB.elt_size);
#endif
   }else{
	   r300EmitAOS(rmesa, rmesa->state.aos_count, start);
	   fire_AOS(PASS_PREFIX num_verts, type);
   }
}
Exemplo n.º 6
0
GLboolean r300_run_vb_render(GLcontext *ctx,
				 struct tnl_pipeline_stage *stage)
{
	r300ContextPtr rmesa = R300_CONTEXT(ctx);
	struct radeon_vertex_buffer *VB = &rmesa->state.VB;
	int i;
	LOCAL_VARS
   
	if (RADEON_DEBUG & DEBUG_PRIMS)
		fprintf(stderr, "%s\n", __FUNCTION__);

	if (stage) {
 		TNLcontext *tnl = TNL_CONTEXT(ctx);
		radeon_vb_to_rvb(rmesa, VB, &tnl->vb);
	}
	
	r300UpdateShaders(rmesa);
	if (rmesa->state.VB.LockCount == 0 || 1) {
 	  	r300ReleaseArrays(ctx);
		r300EmitArrays(ctx, GL_FALSE);

		r300UpdateShaderStates(rmesa);
	} else {
		/* TODO: Figure out why do we need these. */
		R300_STATECHANGE(rmesa, vir[0]);
		R300_STATECHANGE(rmesa, vir[1]);
		R300_STATECHANGE(rmesa, vic);
		R300_STATECHANGE(rmesa, vof);
		
#if 0		
		fprintf(stderr, "dt:\n");
		for(i=0; i < VERT_ATTRIB_MAX; i++){
			fprintf(stderr, "dt %d:", i);
			dump_dt(&rmesa->state.VB.AttribPtr[i], VB->Count);
		}
		
		fprintf(stderr, "before:\n");
		for(i=0; i < rmesa->state.aos_count; i++){
			fprintf(stderr, "aos %d:", i);
			dump_array(&rmesa->state.aos[i], VB->Count);
		}
#endif
#if 0
 	  	r300ReleaseArrays(ctx);
		r300EmitArrays(ctx, GL_FALSE);
			
		fprintf(stderr, "after:\n");
		for(i=0; i < rmesa->state.aos_count; i++){
			fprintf(stderr, "aos %d:", i);
			dump_array(&rmesa->state.aos[i], VB->Count);
		}
#endif
	}
	
	reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
	e32(0x0000000a);

	reg_start(0x4f18,0);
	e32(0x00000003);
#if 0
	reg_start(R300_VAP_PVS_WAITIDLE,0);
		e32(0x00000000);
#endif
	r300EmitState(rmesa);
	
	for(i=0; i < VB->PrimitiveCount; i++){
		GLuint prim = VB->Primitive[i].mode;
		GLuint start = VB->Primitive[i].start;
		GLuint length = VB->Primitive[i].count;
		
		r300_render_vb_primitive(rmesa, ctx, start, start + length, prim);
	}

	reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
	e32(0x0000000a/*0x2*/);

	reg_start(0x4f18,0);
	e32(0x00000003/*0x1*/);

#ifdef USER_BUFFERS
	r300UseArrays(ctx);
#endif
	return GL_FALSE;
}
Exemplo n.º 7
0
static void inline fire_EB(PREFIX unsigned long addr, int vertex_count, int type, int elt_size)
{
	LOCAL_VARS
	unsigned long addr_a;
	unsigned long t_addr;
	unsigned long magic_1, magic_2;
	GLcontext *ctx;
	ctx = rmesa->radeon.glCtx; 
	
	assert(elt_size == 2 || elt_size == 4);
	
	if(addr & (elt_size-1)){
		WARN_ONCE("Badly aligned buffer\n");
		return ;
	}
#ifdef OPTIMIZE_ELTS
	addr_a = 0;
	
	magic_1 = (addr % 32) / 4;
	t_addr = addr & (~0x1d);
	magic_2 = (vertex_count + 1 + (t_addr & 0x2)) / 2 + magic_1;
	
	check_space(6);
	
	start_packet3(RADEON_CP_PACKET3_3D_DRAW_INDX_2, 0);
	if(elt_size == 4){
		e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (vertex_count<<16) | type | R300_VAP_VF_CNTL__INDEX_SIZE_32bit);
	} else {
		e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (vertex_count<<16) | type);
	}

	start_packet3(RADEON_CP_PACKET3_INDX_BUFFER, 2);
	if(elt_size == 4){
		e32(R300_EB_UNK1 | (0 << 16) | R300_EB_UNK2);
		e32(addr /*& 0xffffffe3*/);
	} else {
		e32(R300_EB_UNK1 | (magic_1 << 16) | R300_EB_UNK2);
		e32(t_addr);
	}
	
	if(elt_size == 4){
		e32(vertex_count /*+ addr_a/4*/); /* Total number of dwords needed? */
	} else {
		e32(magic_2); /* Total number of dwords needed? */
	}
	//cp_delay(PASS_PREFIX 1);
#if 0
	fprintf(stderr, "magic_1 %d\n", magic_1);
	fprintf(stderr, "t_addr %x\n", t_addr);
	fprintf(stderr, "magic_2 %d\n", magic_2);
	exit(1);
#endif
#else
	(void)magic_2, (void)magic_1, (void)t_addr;
	
	addr_a = 0;
	
	check_space(6);
	
	start_packet3(RADEON_CP_PACKET3_3D_DRAW_INDX_2, 0);
	if(elt_size == 4){
		e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (vertex_count<<16) | type | R300_VAP_VF_CNTL__INDEX_SIZE_32bit);
	} else {
		e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (vertex_count<<16) | type);
	}

	start_packet3(RADEON_CP_PACKET3_INDX_BUFFER, 2);
	e32(R300_EB_UNK1 | (0 << 16) | R300_EB_UNK2);
	e32(addr /*& 0xffffffe3*/);
	
	if(elt_size == 4){
		e32(vertex_count /*+ addr_a/4*/); /* Total number of dwords needed? */
	} else {
		e32((vertex_count+1)/2 /*+ addr_a/4*/); /* Total number of dwords needed? */
	}
	//cp_delay(PASS_PREFIX 1);
#endif	
}
Exemplo n.º 8
0
static void r300FireEB(r300ContextPtr rmesa, unsigned long addr,
		       int vertex_count, int type, int elt_size)
{
	int cmd_reserved = 0;
	int cmd_written = 0;
	drm_radeon_cmd_header_t *cmd = NULL;
	unsigned long t_addr;
	unsigned long magic_1, magic_2;

	assert(elt_size == 2 || elt_size == 4);

	if (addr & (elt_size - 1)) {
		WARN_ONCE("Badly aligned buffer\n");
		return;
	}

	magic_1 = (addr % 32) / 4;
	t_addr = addr & ~0x1d;
	magic_2 = (vertex_count + 1 + (t_addr & 0x2)) / 2 + magic_1;

	start_packet3(RADEON_CP_PACKET3_3D_DRAW_INDX_2, 0);
	if (elt_size == 4) {
		e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES |
		    (vertex_count << 16) | type |
		    R300_VAP_VF_CNTL__INDEX_SIZE_32bit);
	} else {
		e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES |
		    (vertex_count << 16) | type);
	}

	start_packet3(RADEON_CP_PACKET3_INDX_BUFFER, 2);
#ifdef OPTIMIZE_ELTS
	if (elt_size == 4) {
		e32(R300_EB_UNK1 | (0 << 16) | R300_EB_UNK2);
		e32(addr);
	} else {
		e32(R300_EB_UNK1 | (magic_1 << 16) | R300_EB_UNK2);
		e32(t_addr);
	}
#else
	e32(R300_EB_UNK1 | (0 << 16) | R300_EB_UNK2);
	e32(addr);
#endif

	if (elt_size == 4) {
		e32(vertex_count);
	} else {
#ifdef OPTIMIZE_ELTS
		e32(magic_2);
#else
		e32((vertex_count + 1) / 2);
#endif
	}
}
Exemplo n.º 9
0
/**
 * Get the Wilson's B-matrix
 */
void getBMatrix(Real** cartCoords, int numCartesians,
		bondCoord** bonds, int numBonds,
		angleCoord** angles, int numAngles,
		dihedralCoord** dihedrals, int numDihedrals,
		improperCoord** impropers, int numImpropers,
		Matrix& B) {
#ifdef DEBUG
  cout << "\n\ngetBMatrix - Constructing B Matrix\n";
#endif

  // Constructing B Matrix
  //   follows method in chapter 4 of Molecular Vibrations by Wilson, Decius, and Cross

#ifdef DEBUG  
  int numInternals = numBonds + numAngles + numDihedrals + numImpropers;
  cout << "numBonds: " << numBonds << "\n";
  cout << "numAngles: " << numAngles << "\n";
  cout << "numDihedrals: " << numDihedrals << "\n";
  cout << "numImpropers: " << numImpropers << "\n";
  cout << "numInternals: " << numInternals << "\n";
#endif

  // Load Data
  B = 0.0;
  int i = 0;
  int j = 0;
  int index1 = 0;
  int index2 = 0;
  RowVector tempCoord1(3);
  RowVector tempCoord2(3);
  Real norm = 0.0;
  
  // Bonds
  for (i=0; i<numBonds; i++) {
    index1 = bonds[i]->x1;
    index2 = bonds[i]->x2;
    //norm = bonds[i].val;   // Could calculate this, like below.
#ifdef DEBUG
    cout << "index1=" << index1 << "index2=" << index2 << "\n";
#endif
    for (j=0; j<3; j++) {
      tempCoord1(j+1) = cartCoords[index1][j];
      tempCoord2(j+1) = cartCoords[index2][j];
    }
    tempCoord1 << tempCoord1 - tempCoord2;
    norm = tempCoord1.NormFrobenius();   // XXX - don't delete
    if (norm > 0.0) {
      tempCoord1 << tempCoord1 / norm;
    }
    for (j=1; j<=3; j++) {
      B(i+1,((index1)*3)+j) =  tempCoord1(j);
      B(i+1,((index2)*3)+j) = -tempCoord1(j);
    }
  }
  
#ifdef DEBUG
  cout << "after bonds\n";
  cout << "B:\n";
  cout << setw(9) << setprecision(3) << (B);
  cout << "\n\n";
#endif

  // Angles
  int index3 = 0;
  RowVector tempCoord3(3);
  RowVector tempCoord4(3);
  RowVector tempCoord5(3);
  RowVector r21(3);   // Vector from 2nd to 1st point
  RowVector r23(3);   // Vector from 2nd to 3rd point
  RowVector e21(3);   // Unit vector from 2nd to 1st point
  RowVector e23(3);   // Unit vector from 2nd to 3rd point
  Real norm21;        // Norm of r21
  Real norm23;        // Norm of r23
  Real angle = 0.0;   // Angle in radians
  Real cosAngle123 = 0.0;
  Real sinAngle123 = 0.0;
  //Real pi = 3.14159265;
  Real scaleFactor = 0.529178;   // Scaling factor (0.529178)
  for (i=0; i<numAngles; i++) {
    index1 = angles[i]->x1;
    index2 = angles[i]->x2;
    index3 = angles[i]->x3;
    //angle = angles[i].val * (pi/180.0);   // Convert to radians.
    for (j=0; j<3; j++) {
      tempCoord1(j+1) = cartCoords[index1][j];
      tempCoord2(j+1) = cartCoords[index2][j];
      tempCoord3(j+1) = cartCoords[index3][j];
    }
    r21 << tempCoord1 - tempCoord2;
    r23 << tempCoord3 - tempCoord2;
    norm21 = r21.NormFrobenius();
    norm23 = r23.NormFrobenius();
    e21 << r21;
    if (norm21 > 0.0) {
      e21 << e21 / norm21;
    }
    e23 << r23;
    if (norm23 > 0.0) {
      e23 << e23 / norm23;
    }
    angle = acos(DotProduct(r21,r23) / (norm21 * norm23));
    cosAngle123 = DotProduct(r21,r23) / (norm21 * norm23);
    sinAngle123 = sqrt(1 - (cosAngle123 * cosAngle123));
    
#ifdef DEBUG
    cout << "r21: " << (r21) << "\n";
    cout << "r23: " << (r23) << "\n";
    cout << "norm21: " << norm21 << ", norm23: " << norm23 << "\n\n";
    cout << "e21: " << (e21) << "\n";
    cout << "e23: " << (e23) << "\n";
    cout << "cos(" << angle << "): " << cos(angle) << "\n";
    cout << "sin(" << angle << "): " << sin(angle) << "\n";
    cout << "angle: " << acos(DotProduct(r21,r23) / (norm21 * norm23)) << "\n";
    cout << "cosAngle123: " << cosAngle123 << "\n";
    cout << "sinAngle123: " << sinAngle123 << "\n";
#endif    

    // First elements of coordinate triples
    tempCoord4 << ((cosAngle123 * e21) - e23);
    tempCoord4 << (tempCoord4 * scaleFactor) / (norm21 * sinAngle123);
    for (j=1; j<=3; j++) {
      B(i+numBonds+1,((index1)*3)+j) = tempCoord4(j);
    }
    // Third elements of coordinate triples
    tempCoord5 << ((cosAngle123 * e23) - e21);
    tempCoord5 << (tempCoord5 * scaleFactor) / (norm23 * sinAngle123);
    for (j=1; j<=3; j++) {
      B(i+numBonds+1,((index3)*3)+j) = tempCoord5(j);
    }
    // Second (middle) elements of coordinate triples (depends on 1st and 3rd)
    tempCoord4 << -tempCoord4 - tempCoord5;
    for (j=1; j<=3; j++) {
      B(i+numBonds+1,((index2)*3)+j) = tempCoord4(j);
    }
  }
  
#ifdef DEBUG
  cout << "after angles\n";
  cout << "B:\n";
  cout << setw(9) << setprecision(3) << (B);
  cout << "\n\n";
#endif  

  // Dihedrals
  RowVector r12(3);   // Vector from 1st to 2nd point
  RowVector r32(3);   // Vector from 3rd to 2nd point
  RowVector r34(3);   // Vector from 3rd to 2nd point
  RowVector r43(3);   // Vector from 4th to 3rd point
  RowVector e12(3);   // Unit vector from 1st to 2nd point
  RowVector e32(3);   // Unit vector from 3rd to 2nd point
  RowVector e34(3);   // Unit vector from 3rd to 2nd point
  RowVector e43(3);   // Unit vector from 4th to 3rd point
  Real norm12;        // Norm of r12
  Real norm32;        // Norm of r32
  Real norm34;        // Norm of r34
  Real norm43;        // Norm of r43
  RowVector cross1223(3);   // Cross product of e12 and e23
  RowVector cross4332(3);   // Cross product of e43 and e32
  Real angle123 = 0.0;   // Angle in radians
  Real angle234 = 0.0;   // Angle in radians
  Real cosAngle234 = 0.0;
  Real sinAngle234 = 0.0;
  scaleFactor = 0.529178;   // Scaling factor (0.529178)
  int index4 = 0;
  RowVector tempCoord6(3);
  for (i=0; i<numDihedrals; i++) {
    index1 = dihedrals[i]->x1;
    index2 = dihedrals[i]->x2;
    index3 = dihedrals[i]->x3;
    index4 = dihedrals[i]->x4;
    for (j=0; j<3; j++) {
      tempCoord1(j+1) = cartCoords[index1][j];
      tempCoord2(j+1) = cartCoords[index2][j];
      tempCoord3(j+1) = cartCoords[index3][j];
      tempCoord4(j+1) = cartCoords[index4][j];
    }
    r12 << tempCoord2 - tempCoord1;
    r21 << tempCoord1 - tempCoord2;
    r23 << tempCoord3 - tempCoord2;
    r32 << tempCoord2 - tempCoord3;
    r34 << tempCoord4 - tempCoord3;
    r43 << tempCoord3 - tempCoord4;
    norm12 = r12.NormFrobenius();
    norm21 = r21.NormFrobenius();
    norm23 = r23.NormFrobenius();
    norm32 = r32.NormFrobenius();
    norm34 = r34.NormFrobenius();
    norm43 = r43.NormFrobenius();
#ifdef DEBUG
    cout << "norm12: " << norm12 << "\n";
    cout << "norm21: " << norm21 << "\n";
    cout << "norm23: " << norm23 << "\n";
    cout << "norm32: " << norm32 << "\n";
    cout << "norm34: " << norm34 << "\n";
    cout << "norm43: " << norm43 << "\n";
#endif
    e12 << r12 / norm12;
    e21 << r21 / norm21;
    e23 << r23 / norm23;
    e32 << r32 / norm32;
    e34 << r34 / norm34;
    e43 << r43 / norm43;
    angle123 = acos(DotProduct(r21,r23) / (norm21 * norm23));   // Wilson's angle 2
    angle234 = acos(DotProduct(r32,r34) / (norm32 * norm34));   // Wilson's angle 3
    cosAngle123 = DotProduct(r21,r23) / (norm21 * norm23);
    cosAngle234 = DotProduct(r32,r34) / (norm32 * norm34);
    sinAngle123 = sqrt(1 - (cosAngle123 * cosAngle123));
    sinAngle234 = sqrt(1 - (cosAngle234 * cosAngle234));
#ifdef DEBUG
    cout << "angle123: " << angle123 << ", cos(angle123): " << cos(angle123) << ", sin(angle123): " << sin(angle123) << "\n";
    cout << "angle234: " << angle234 << ", cos(angle234): " << cos(angle234) << ", sin(angle234): " << sin(angle234) << "\n";
    cout << "cosAngle123: " << cosAngle123 << ", sinAngle123: " << sinAngle123 << "\n";
    cout << "cosAngle234: " << cosAngle234 << ", sinAngle234: " << sinAngle234 << "\n";
#endif
    cross1223(1) = (e12(2)*e23(3)) - (e12(3)*e23(2));
    cross1223(2) = (e12(3)*e23(1)) - (e12(1)*e23(3));
    cross1223(3) = (e12(1)*e23(2)) - (e12(2)*e23(1));
    cross4332(1) = (e43(2)*e32(3)) - (e43(3)*e32(2));
    cross4332(2) = (e43(3)*e32(1)) - (e43(1)*e32(3));
    cross4332(3) = (e43(1)*e32(2)) - (e43(2)*e32(1));
#ifdef DEBUG
    cout << "cross1223 (norm " << cross1223.NormFrobenius() << "):\n";
    cout << setw(9) << setprecision(6) << (cross1223);
    cout << "\n\n";
    cout << "cross4332 (norm " << cross4332.NormFrobenius() << "):\n";
    cout << setw(9) << setprecision(6) << (cross4332);
    cout << "\n\n";
#endif
    // First elements of coordinate triples
    tempCoord5 << -((cross1223 * scaleFactor) / (norm12 * sinAngle123 * sinAngle123));
    for (j=1; j<=3; j++) {
      B(i+numBonds+numAngles+1,((index1)*3)+j) = tempCoord5(j);
    }
    // Second elements of coordinate triples
    tempCoord5 << ((norm23 - (norm12 * cosAngle123)) / (norm23 * norm12 * sinAngle123 * sinAngle123)) * (cross1223);
    tempCoord6 << (cosAngle234 / (norm23 * sinAngle234 * sinAngle234)) * (cross4332);
#ifdef DEBUG
    cout << "tempCoord5:\n";
    cout << setw(9) << setprecision(6) << (tempCoord5);
    cout << "tempCoord6:\n";
    cout << setw(9) << setprecision(6) << (tempCoord6);
#endif
    tempCoord5 << (tempCoord5 + tempCoord6) * scaleFactor;
#ifdef DEBUG
    cout << "tempCoord5:\n";
    cout << setw(9) << setprecision(6) << (tempCoord5);
#endif
    for (j=1; j<=3; j++) {
      B(i+numBonds+numAngles+1,((index2)*3)+j) = tempCoord5(j);
    }
    // Third elements of coordinate triples
    tempCoord5 << ((norm32 - (norm43 * cosAngle234)) / (norm32 * norm43 * sinAngle234 * sinAngle234)) * (cross4332);
    tempCoord6 << (cosAngle123 / (norm32 * sinAngle123 * sinAngle123)) * (cross1223);
    tempCoord5 << (tempCoord5 + tempCoord6) * scaleFactor;
    for (j=1; j<=3; j++) {
      B(i+numBonds+numAngles+1,((index3)*3)+j) = tempCoord5(j);
    }
    // Fourth elements of coordinate triples
    tempCoord5 << -((cross4332 * scaleFactor) / (norm43 * sinAngle234 * sinAngle234));
    for (j=1; j<=3; j++) {
      B(i+numBonds+numAngles+1,((index4)*3)+j) = tempCoord5(j);
    }
  }
  
#ifdef DEBUG
  cout << "B:\n";
  cout << setw(9) << setprecision(3) << (B);
  cout << "\n\n";
#endif

  // Impropers
  RowVector r41(3);   // Vector from 4th to 1st point
  RowVector r42(3);   // Vector from 4th to 2nd point
  RowVector e41(3);   // Unit vector from 4th to 1st point
  RowVector e42(3);   // Unit vector from 4th to 2nd point
  RowVector normVector(3);   // Normal to the plane
  Real norm41;        // Norm of r41
  Real norm42;        // Norm of r42
  Real angle142 = 0.0;   // Angle in radians
  Real angle143 = 0.0;   // Angle in radians
  Real angle243 = 0.0;   // Angle in radians
  Real cosAngle142 = 0.0;
  Real cosAngle143 = 0.0;
  Real cosAngle243 = 0.0;
  Real sinAngle142 = 0.0;
  Real sinAngle143 = 0.0;
  Real sinAngle243 = 0.0;
  Real apexCoeff = 0.0;   // Magnitude of central atom displacement
  scaleFactor = -0.352313;   // Scale factor (-0.352313)
  for (i=0; i<numImpropers; i++) {
    index1 = impropers[i]->x1;
    index2 = impropers[i]->x2;
    index3 = impropers[i]->x3;
    index4 = impropers[i]->x4;
    for (j=0; j<3; j++) {
      tempCoord1(j+1) = cartCoords[index1][j];
      tempCoord2(j+1) = cartCoords[index2][j];
      tempCoord3(j+1) = cartCoords[index3][j];
      tempCoord4(j+1) = cartCoords[index4][j];
    }
    r41 << tempCoord1 - tempCoord4;
    r42 << tempCoord2 - tempCoord4;
    r43 << tempCoord3 - tempCoord4;
    norm41 = r41.NormFrobenius();
    norm42 = r42.NormFrobenius();
    norm43 = r43.NormFrobenius();
    e41 << r41 / norm41;
    e42 << r42 / norm42;
    e43 << r43 / norm43;
    angle142 = acos(DotProduct(r41,r42) / (norm41 * norm42));
    angle143 = acos(DotProduct(r41,r43) / (norm41 * norm43));
    angle243 = acos(DotProduct(r42,r43) / (norm42 * norm43));
    cosAngle142 = DotProduct(r41,r42) / (norm41 * norm42);
    cosAngle143 = DotProduct(r41,r43) / (norm41 * norm43);
    cosAngle243 = DotProduct(r42,r43) / (norm42 * norm43);
    sinAngle142 = sqrt(1 - (cosAngle142 * cosAngle142));
    sinAngle143 = sqrt(1 - (cosAngle143 * cosAngle143));
    sinAngle243 = sqrt(1 - (cosAngle243 * cosAngle243));
    normVector(1) = (r41(2)*r42(3)) - (r41(3)*r42(2));
    normVector(2) = (r41(3)*r42(1)) - (r41(1)*r42(3));
    normVector(3) = (r41(1)*r42(2)) - (r41(2)*r42(1));
    normVector << normVector / normVector.NormFrobenius();
    // First elements of coordinate triples
    tempCoord5 << normVector * (scaleFactor / norm41);
    for (j=1; j<=3; j++) {
      B(i+numBonds+numAngles+numDihedrals+1,((index1)*3)+j) = tempCoord5(j);
    }
    // Second elements of coordinate triples
    tempCoord5 << normVector * sinAngle143 * scaleFactor;
    tempCoord5 << tempCoord5 / (norm42 * sinAngle243);
    for (j=1; j<=3; j++) {
      B(i+numBonds+numAngles+numDihedrals+1,((index2)*3)+j) = tempCoord5(j);
    }
    // Third elements of coordinate triples
    tempCoord5 << normVector * sinAngle142 * scaleFactor;
    tempCoord5 << tempCoord5 / (norm43 * sinAngle243);
    for (j=1; j<=3; j++) {
      B(i+numBonds+numAngles+numDihedrals+1,((index3)*3)+j) = tempCoord5(j);
    }
    // Fourth elements of coordinate triples
    apexCoeff = -1.0 / norm42;
    apexCoeff -= sinAngle143 / (norm42 * sinAngle243);
    apexCoeff -= sinAngle142 / (norm43 * sinAngle243);
    tempCoord5 << normVector * apexCoeff * scaleFactor;
    for (j=1; j<=3; j++) {
      B(i+numBonds+numAngles+numDihedrals+1,((index4)*3)+j) = tempCoord5(j);
    }
  }
  
  return;
}