void translate4d(double x, double y, double z, double b[4][4]) { int i; identity4(b); b[0][3] = x; b[1][3] = y; b[2][3] = z; }
void translate4(double a[3], double b[4][4]) { int i; identity4(b); for (i = 0; i < 3; ++i) b[i][3] = a[i]; }
void SetStandardHelix() { int numResidues = 9, type[9] = {8, 8, 8, 8, 8, 8, 8, 8, 8}; double phi[9], psi[9], head[3], tail[3], diff[3]; int i, j, k, l, m, n; double v0[4], v1[4], v2[4], v3[4], v4[4], pos[4]; double mainpos[4]={0.0,0.0,0.0,0.0}; double a[4][4], b[4][4], c[4][4], d[4][4], e[4][4], f[4][4], g[4][4]; double chainN[9][3]; double chainCA[9][3]; double chainC[9][3]; double center[9][3]; double axis[3], plane[3], dd, radius; #if WRITEHELIXFILE FILE *fp; const char outfile[34] = "StandardHelix.pdb"; #endif char chainId[2], pc; char elementName[2]; int residueIndex; char* atomNamePtr; for (i = 0; i < numResidues; ++i) { phi[i] = -60.*PI/180.; psi[i] = -45.*PI/180.; } #if WRITEHELIXFILE fp = fopen(outfile, "w"); if (fp == 0) { printf("unable to open file %s\n", outfile); } #endif n = 1; identity4(a); // Standard amino acids have CA at the origin and N at -residue_d2, // so translate to put N at the origin. Standard amino acids also // have C in the xy plane, but not necessarily carbonyl O. for (i = 0; i < numResidues; ++i) { j = type[i]; translate4d(residued2[j], 0., 0., b); matmult4(a, b, c); rotX4(PI-StandardPhi[j], b); // printf("StandardPhi[%d] = %f\n", j, StandardPhi[j]); matmult4(c, b, f); // f is for the amide H // First do NH l = 2; for (k = 0; k < l; ++k) { for (m = 0; m < 3; ++m) v0[m] = residueAtomPos[j][k][m]; v0[3] = 1.; if(k == 0) { matrix_vector4(c, v0, mainpos); for (m = 0; m < 3; ++m) chainN[i][m] = mainpos[m]; } else matrix_vector4(f, v0, mainpos); #if WRITEHELIXFILE fprintf(fp, "ATOM %6d %4s%4s %4d %8.3f%8.3f%8.3f%6.2f%6.2f\n", n, residueAtomName[j][k], Protein::Residue::abbreviatedNames[j], i+1, mainpos[0], mainpos[1], mainpos[2], 0., 0.); #endif ++n; } rotX4(phi[i], b); matmult4(c, b, a); // a continuing backbone rotZ4(StandardAlpha[j], b); matmult4(a, b, c); rotX4(psi[i], b); matmult4(c, b, d); // d is to help continue backbone rotX4(StandardPsi[j], b); // to bring O to plane of next N and CA matmult4(d, b, g); rotZ4(-StandardAlpha[j], b); matmult4(g, b, e); // e is for carbonyl oxygen // Now do rest of atoms for (k = l; k < numbAtoms[j]; ++k) { for (m = 0; m < 3; ++m) v0[m] = residueAtomPos[j][k][m]; v0[3] = 1.; if (k == l+3) matrix_vector4(e, v0, pos); else matrix_vector4(a, v0, pos); if(k == 2) for (m = 0; m < 3; ++m) chainCA[i][m] = pos[m]; if(k == 4) for (m = 0; m < 3; ++m) chainC[i][m] = pos[m]; #if WRITEHELIXFILE fprintf(fp, "ATOM %6d %4s%4s %4d %8.3f%8.3f%8.3f%6.2f%6.2f\n", n, residueAtomName[j][k], Protein::Residue::abbreviatedNames[j], i+1, pos[0], pos[1], pos[2], 0., 0.); #endif ++n; } // Now build up rest of main chain effect on matrix a translate4d(residued3[j], 0., 0., b); matmult4(d, b, c); rotZ4(StandardBeta[j], b); matmult4(c, b, d); translate4d(1.325, 0., 0., b); matmult4(d, b, c); rotX4(PI, b); matmult4(c, b, d); rotZ4(StandardGamma[j], b); matmult4(d, b, a); // printf("Alpha %f Beta %f Gamma %f\n", 180*StandardAlpha[j]/PI, // 180*StandardBeta[j]/PI, 180*StandardGamma[j]/PI); } for (i = 1; i < numResidues-1; ++i) { for(m = 0; m < 3; ++m) { v0[m] = chainN[i-1][m] - chainN[i][m]; v1[m] = chainN[i+1][m] - chainN[i][m]; } normalize(v0); normalize(v1); for(m = 0; m < 3; ++m) center[i][m] = v0[m] + v1[m]; normalize(center[i]); } cross(center[1], center[2], axis); normalize(axis); cross(axis, center[2], plane); dd = dot(plane, chainN[2]) - dot(plane, chainN[1]) ; radius = dd/dot(plane,center[1]); for(m = 0; m < 3; ++m) { tail[m] = chainN[1][m] + radius*center[1][m]; head[m] = chainN[7][m] + radius*center[7][m]; diff[m] = (head[m] - tail[m])/6.; tail[m] -= diff[m]; } for(m = 0; m < 3; ++m) { v0[m] = chainN[0][m] - chainCA[0][m]; v1[m] = chainC[0][m] - chainCA[0][m]; } normalize(v0); normalize(v1); dd = dot(v0, v1); for(m = 0; m < 3; ++m) v1[m] -= dd*v0[m]; normalize(v1); cross(v0, v1, v2); normalize(v2); saxis[0] = dot(v0, diff); saxis[1] = dot(v1, diff); saxis[2] = dot(v2, diff); stail[0] = dot(v0, tail); stail[1] = dot(v1, tail); stail[2] = dot(v2, tail); cross(saxis, stail, ptail); normalize(ptail); dtail= sqrt( stail[0]*stail[0] + stail[1]*stail[1] + stail[2]*stail[2] ); daxis= sqrt( saxis[0]*saxis[0] + saxis[1]*saxis[1] + saxis[2]*saxis[2] ); for(m = 0; m < 3; ++m) ptail[m] = dtail*ptail[m]; /* normalize(diff); fprintf(fp, "ATOM %6d %4s%4s %4d %8.3f%8.3f%8.3f%6.2f%6.2f\n", 61, " C", Protein::Residue::abbreviatedNames[j], 9, head[0], head[1], head[2], 0., 0.); fprintf(fp, "ATOM %6d %4s%4s %4d %8.3f%8.3f%8.3f%6.2f%6.2f\n", 62, " O", Protein::Residue::abbreviatedNames[j], 9, tail[0], tail[1], tail[2], 0., 0.); cout << "radius " << radius << " dd " << dd << " plane " << *plane << " center[0] " << *center[1] << " tail " << *tail << "\n"; fprintf(stderr, "axis %g %g %g\n", axis[0], axis[1], axis[2]); fprintf(stderr, "diff %g %g %g\n", diff[0], diff[1], diff[2]); fprintf(stderr, "head %g %g %g\n", head[0], head[1], head[2]); fprintf(stderr, "tail %g %g %g\n", tail[0], tail[1], tail[2]); fprintf(stderr, "chainN[7] %g %g %g\n", chainN[7][0], chainN[7][1], chainN[7][2]); fprintf(stderr, "chainN[1] %g %g %g\n", chainN[1][0], chainN[1][1], chainN[1][2]); */ #if WRITEHELIXFILE fclose(fp); #endif }
Protein* SetDihedrals (int numResidues, const int type[], const char pred[], const double phi[], const double psi[]) { int i, j, k, l, m, n; double v0[4], v1[4], v2[4], v3[4], v4[4], pos[4]; double mainpos[4]={0.0,0.0,0.0,0.0}; double a[4][4], b[4][4], c[4][4], d[4][4], e[4][4], f[4][4], g[4][4]; #if WRITEPDBFILE FILE *fp; const char outfile[14] = "StandardHelix.pdb"; #endif Protein* result=new Protein; int currentResidueIndex=-1; Protein::ResidueCreator proteinCreator(result); Protein::SecondaryStructure::StructureType currentStructureType=Protein::SecondaryStructure::NONE; char chainId[2], pc; char elementName[2]; int residueIndex; char* atomNamePtr; if(numResidues <= 0) return result; #if WRITEPDBFILE fp = fopen(outfile, "w"); if (fp == 0) { printf("unable to open file %s\n", outfile); assert (fp != 0); } #endif n = 1; identity4(a); // Standard amino acids have CA at the origin and N at -residue_d2, // so translate to put N at the origin. Standard amino acids also // have C in the xy plane, but not necessarily carbonyl O. for (i = -1; i < numResidues+1; ++i) { if(i==-1||i==numResidues) { const char* residuePdbName; if (i == -1) { j = 0; residuePdbName="ACE"; } else { j = 14; residuePdbName="NME"; } Protein::SecondaryStructure::StructureType newStructureType; newStructureType=Protein::SecondaryStructure::COIL; if(newStructureType!=currentStructureType) { proteinCreator.newSecondaryStructure(newStructureType); currentStructureType=newStructureType; } proteinCreator.newResidue(residuePdbName,i+1); for (k = 0; k < numbAtoms[j]; ++k) { for (m = 0; m < 3; ++m) pos[m] = residueAtomPos[j][k][m] + mainpos[m]; pos[1] += 1; pos[0] -= 0.8; #if WRITEPDBFILE fprintf(fp, "ATOM %6d %4s%4s %4d %8.3f%8.3f%8.3f%6.2f%6.2f\n", n, residueAtomName[j][k], residuePdbName, i+1, pos[0], pos[1], pos[2], 0., 0.); #endif ++n; atomNamePtr=residueAtomName[j][k]; while(isspace(*atomNamePtr)) ++atomNamePtr; elementName[0]=*atomNamePtr; ++atomNamePtr; elementName[1]='\0'; proteinCreator.addAtom(elementName, n-1 ,Position(pos), atomNamePtr); } } else { j = type[i]; pc = pred[i]; Protein::SecondaryStructure::StructureType newStructureType; if (pc == 'C') newStructureType=Protein::SecondaryStructure::COIL; else if (pc == 'H') newStructureType=Protein::SecondaryStructure::ALPHA_HELIX; else if (pc == 'E') newStructureType=Protein::SecondaryStructure::BETA_STRAND; else { printf("Unknown secondary structure type.\n"); exit(-1); } if(newStructureType!=currentStructureType) { proteinCreator.newSecondaryStructure(newStructureType); currentStructureType=newStructureType; } proteinCreator.newResidue(Protein::Residue::abbreviatedNames[j],i+1); translate4d(residued2[j], 0., 0., b); matmult4(a, b, c); rotX4(PI-StandardPhi[j], b); // printf("StandardPhi[%d] = %f\n", j, StandardPhi[j]); matmult4(c, b, f); // f is for the amide H // First do NH if(j == 16) l = 1; else l = 2; for (k = 0; k < l; ++k) { for (m = 0; m < 3; ++m) v0[m] = residueAtomPos[j][k][m]; v0[3] = 1.; if(k == 0) matrix_vector4(c, v0, mainpos); else matrix_vector4(f, v0, mainpos); #if WRITEPDBFILE fprintf(fp, "ATOM %6d %4s%4s %4d %8.3f%8.3f%8.3f%6.2f%6.2f\n", n, residueAtomName[j][k], Protein::Residue::abbreviatedNames[j], i+1, mainpos[0], mainpos[1], mainpos[2], 0., 0.); #endif ++n; atomNamePtr=residueAtomName[j][k]; while(isspace(*atomNamePtr)) ++atomNamePtr; elementName[0]=*atomNamePtr; ++atomNamePtr; elementName[1]='\0'; proteinCreator.addAtom(elementName, n-1 ,Position(mainpos), atomNamePtr); // printf("%d %4s %4s %4s\n", // n-1, elementName, atomNamePtr, residueAtomName[j][k]); } rotX4(phi[i], b); matmult4(c, b, a); // a continuing backbone rotZ4(StandardAlpha[j], b); matmult4(a, b, c); rotX4(psi[i], b); matmult4(c, b, d); // d is to help continue backbone rotX4(StandardPsi[j], b); // to bring O to plane of next N and CA matmult4(d, b, g); rotZ4(-StandardAlpha[j], b); matmult4(g, b, e); // e is for carbonyl oxygen // Now do rest of atoms for (k = l; k < numbAtoms[j]; ++k) { for (m = 0; m < 3; ++m) v0[m] = residueAtomPos[j][k][m]; v0[3] = 1.; if (k == l+3) matrix_vector4(e, v0, pos); else matrix_vector4(a, v0, pos); #if WRITEPDBFILE fprintf(fp, "ATOM %6d %4s%4s %4d %8.3f%8.3f%8.3f%6.2f%6.2f\n", n, residueAtomName[j][k], Protein::Residue::abbreviatedNames[j], i+1, pos[0], pos[1], pos[2], 0., 0.); #endif ++n; atomNamePtr=residueAtomName[j][k]; while(isspace(*atomNamePtr)) ++atomNamePtr; elementName[0]=*atomNamePtr; ++atomNamePtr; elementName[1]='\0'; proteinCreator.addAtom(elementName, n-1 ,Position(pos), atomNamePtr); } // Now build up rest of main chain effect on matrix a translate4d(residued3[j], 0., 0., b); matmult4(d, b, c); rotZ4(StandardBeta[j], b); matmult4(c, b, d); translate4d(1.325, 0., 0., b); matmult4(d, b, c); rotX4(PI, b); matmult4(c, b, d); rotZ4(StandardGamma[j], b); matmult4(d, b, a); // printf("Alpha %f Beta %f Gamma %f\n", 180*StandardAlpha[j]/PI, // 180*StandardBeta[j]/PI, 180*StandardGamma[j]/PI); } } #if WRITEPDBFILE fclose(fp); #endif proteinCreator.finishProtein(); SetStandardHelix(); return result; }
//------------------------------------------------------------- // writes Wavefront OBJ into stream //------------------------------------------------------------- void WriteMODELToObjStream( IVirtualStream* pStream, MODEL* model, int model_index, bool debugInfo = true, const Matrix4x4& translation = identity4(), int* first_v = NULL, int* first_t = NULL, RegionModels_t* regModels = NULL) { if(!model) { MsgError("no model %d!!!\n", model_index); return; } // export OBJ with points if(debugInfo) pStream->Print("#vert count %d\r\n", model->num_vertices); pStream->Print("g lev_model_%d\r\n", model_index); pStream->Print("o lev_model_%d\r\n", model_index); MODEL* vertex_ref = model; if(model->instance_number > 0) // car models have vertex_ref=0 { pStream->Print("#vertex data ref model: %d (count = %d)\r\n", model->instance_number, model->num_vertices); vertex_ref = FindModelByIndex(model->instance_number, regModels); if(!vertex_ref) { Msg("vertex ref not found %d\n", model->instance_number); return; } } for(int j = 0; j < vertex_ref->num_vertices; j++) { Vector3D vertexTransformed = Vector3D(vertex_ref->pVertex(j)->x*-0.00015f, vertex_ref->pVertex(j)->y*-0.00015f, vertex_ref->pVertex(j)->z*0.00015f); vertexTransformed = (translation * Vector4D(vertexTransformed, 1.0f)).xyz(); pStream->Print("v %g %g %g\r\n", vertexTransformed.x, vertexTransformed.y, vertexTransformed.z); } int face_ofs = 0; if(debugInfo) { pStream->Print("#poly ofs %d\r\n", model->poly_block); pStream->Print("#poly count %d\r\n", model->num_polys); } pStream->Print("usemtl none\r\n", model->num_vertices); int numVertCoords = 0; int numVerts = 0; if(first_t) numVertCoords = *first_t; if(first_v) numVerts = *first_v; bool bSmooth = false; for(int j = 0; j < model->num_polys; j++) { char* facedata = model->pPolyAt(face_ofs); dface_t dec_face; int face_size = decode_poly(facedata, &dec_face); //if((dec_face.flags & FACE_SMOOTH) > 0 != bSmooth) //{ // bSmooth = (dec_face.flags & FACE_SMOOTH) > 0; // pStream->Print("s %s\r\n", bSmooth ? "1" : "off"); //} if((dec_face.flags & FACE_TEXTURED) || (dec_face.flags & FACE_TEXTURED2)) { pStream->Print("usemtl page_%d\r\n", dec_face.page); } if(debugInfo) pStream->Print("#ft=%d ofs=%d size=%d\r\n", dec_face.flags, model->poly_block+face_ofs, face_size); if(dec_face.flags & FACE_IS_QUAD) { // flip int vertex_index[4] = { dec_face.vindex[3], dec_face.vindex[2], dec_face.vindex[1], dec_face.vindex[0] }; if( dec_face.vindex[0] < 0 || dec_face.vindex[0] > vertex_ref->num_vertices || dec_face.vindex[1] < 0 || dec_face.vindex[1] > vertex_ref->num_vertices || dec_face.vindex[2] < 0 || dec_face.vindex[2] > vertex_ref->num_vertices || dec_face.vindex[3] < 0 || dec_face.vindex[3] > vertex_ref->num_vertices) { MsgError("quad %d (type=%d ofs=%d) has invalid indices (or format is unknown)\n", j, dec_face.flags, model->poly_block+face_ofs); face_ofs += face_size; continue; } if((dec_face.flags & FACE_TEXTURED) || (dec_face.flags & FACE_TEXTURED2)) { pStream->Print("vt %g %g\r\n", float(dec_face.texcoord[0][0]) / 256.0f+halfTexelSize, (255.0f-float(dec_face.texcoord[0][1])) / 256.0f+halfTexelSize); pStream->Print("vt %g %g\r\n", float(dec_face.texcoord[1][0]) / 256.0f+halfTexelSize, (255.0f-float(dec_face.texcoord[1][1])) / 256.0f+halfTexelSize); pStream->Print("vt %g %g\r\n", float(dec_face.texcoord[2][0]) / 256.0f+halfTexelSize, (255.0f-float(dec_face.texcoord[2][1])) / 256.0f+halfTexelSize); pStream->Print("vt %g %g\r\n", float(dec_face.texcoord[3][0]) / 256.0f+halfTexelSize, (255.0f-float(dec_face.texcoord[3][1])) / 256.0f+halfTexelSize); pStream->Print("f %d/%d %d/%d %d/%d %d/%d\r\n", vertex_index[0]+1+numVerts, numVertCoords+4, vertex_index[1]+1+numVerts, numVertCoords+3, vertex_index[2]+1+numVerts, numVertCoords+2, vertex_index[3]+1+numVerts, numVertCoords+1); numVertCoords += 4; } else { pStream->Print("f %d %d %d %d\r\n", vertex_index[0]+1+numVerts, vertex_index[1]+1+numVerts, vertex_index[2]+1+numVerts, vertex_index[3]+1+numVerts); } } else { // flip int vertex_index[3] = { dec_face.vindex[2], dec_face.vindex[1], dec_face.vindex[0] }; if( dec_face.vindex[0] < 0 || dec_face.vindex[0] > vertex_ref->num_vertices || dec_face.vindex[1] < 0 || dec_face.vindex[1] > vertex_ref->num_vertices || dec_face.vindex[2] < 0 || dec_face.vindex[2] > vertex_ref->num_vertices) { MsgError("triangle %d (type=%d ofs=%d) has invalid indices (or format is unknown)\n", j, dec_face.flags, model->poly_block+face_ofs); face_ofs += face_size; continue; } if((dec_face.flags & FACE_TEXTURED) || (dec_face.flags & FACE_TEXTURED2)) { pStream->Print("vt %g %g\r\n", float(dec_face.texcoord[0][0]) / 256.0f+halfTexelSize, (255.0f-float(dec_face.texcoord[0][1])) / 256.0f+halfTexelSize); pStream->Print("vt %g %g\r\n", float(dec_face.texcoord[1][0]) / 256.0f+halfTexelSize, (255.0f-float(dec_face.texcoord[1][1])) / 256.0f+halfTexelSize); pStream->Print("vt %g %g\r\n", float(dec_face.texcoord[2][0]) / 256.0f+halfTexelSize, (255.0f-float(dec_face.texcoord[2][1])) / 256.0f+halfTexelSize); pStream->Print("f %d/%d %d/%d %d/%d\r\n", vertex_index[0]+1+numVerts, numVertCoords+3, vertex_index[1]+1+numVerts, numVertCoords+2, vertex_index[2]+1+numVerts, numVertCoords+1); numVertCoords += 3; } else { pStream->Print("f %d %d %d\r\n", vertex_index[0]+1+numVerts, vertex_index[1]+1+numVerts, vertex_index[2]+1+numVerts); } } face_ofs += face_size; } if(first_t) *first_t = numVertCoords; if(first_v) *first_v = numVerts+vertex_ref->num_vertices; }