This is MolShape.m in view mode; [Download] [Up]
/* MolShape.m - Copyright 1993 Steve Ludtke */
/* This object does the actual molecule rendering (except for quick mode) */
/* ball and stick mode is still quite primitive */
/* I should probably change the flags from numbers to #defined strings ... */
#import "Mtypes.h"
#import "MolShape.h"
#import <ri/ri.h>
#import <math.h>
#define SC .05
#define SCP1 SC/1.732
#define SCP2 SC/.866
#define SCP3 SC/2.45
#define SCP4 SC/1.633-SCP3
@implementation MolShape:N3DShape
- renderSelf:(RtToken)context
{
int i,j,n,ln;
float x,y,z,r,d,lx,ly,lz;
/* a big square for a white background */
static RtPoint bsquare[4]= {{-200.0,-200.0,-40.0},{200.0,-200.0,-40.0},{200.0,200.0,-40.0},{-200.0,200.0,-40.0}};
static RtPoint square[4]= {{0.0,0.0,0.0},{1.0,0.0,0.0},{1.0,1.0,0.0},{0.0,1.0,0.0}};
static RtColor bgCol = {1.0,1.0,1.0};
static RtColor stCol = {.4,.4,.4};
static RtColor bCol = { 0,0,0 };
static RtColor dCol = { .95,.95,.95 };
static RtColor cCol;
static RtColor selCol = { 0.0,0.0,0.0 };
char *tmap = "/users/steve/grid.tex";
if (mode==4) return self; /* quick mode, do nothing */
if (mode==12) mode=11; /* quick mode, but we want to print, so render */
/* RiMakeTexture("/users/steve/grid.tiff","/users/steve/grid.tex", RI_PERIODIC,RI_PERIODIC,RiGaussianFilter,1,1,RI_NULL); */
RiDeclare("texname","uniform string");
RiColor(dCol);
/*
if (nmol!=0 && mol[0].numaa>2) {
RiTransformBegin();
RiTranslate(10.2,4.3,0.0);
RiScale(10.0,10.0,1.0);
RiSurface("texmap",(RtToken)"texname",(RtPointer)&tmap,RI_NULL);
RiPolygon(4,RI_P,(RtPointer)square,RI_NULL);
RiSurface("constant",RI_NULL);
RiColor(bCol);
RiTranslate(mol[0].am[1].phi/(2.0*M_PI)+.5,
mol[0].am[1].psi/(2.0*M_PI)+.5,0.0);
RiSphere(.05,-.05,.05,360.0,RI_NULL);
RiTransformEnd();
}*/
RiSurface("constant",RI_NULL);
if (mode>=8) {
RiColor(bgCol);
RiPolygon(4,RI_P,(RtPointer)bsquare,RI_NULL);
}
RiRotate(chi,0,1.0,0);
RiRotate(theta,1.0,0,0.0);
RiRotate(phi,0,1.0,0);
/* metal is ok too ... */
RiSurface("plastic",RI_NULL);
RiColor(dCol);
/* stick mode */
if ((flags&3)==0) {
RiColor(stCol);
for (i=0; i<nmol; i++) {
if (mol[i].numlb==0) continue;
/* RiPointsLines(mol[i].numlb,mol[i].nverts,mol[i].verts
,RI_P,mol[i].coord,RI_NULL); */
for (j=0; j<mol[i].numlb; j++) {
if (j%20==0) {
RiSynchronize( RI_FLUSH );
RiSynchronize( RI_WAIT );
}
n=mol[i].lb[j].n1;
ln=mol[i].lb[j].n2;
x=mol[i].coord[n][0];
y=mol[i].coord[n][1];
z=mol[i].coord[n][2];
lx=mol[i].coord[ln][0]-x;
ly=mol[i].coord[ln][1]-y;
lz=mol[i].coord[ln][2]-z;
r=sqrt(SQR(lx)+SQR(ly)+SQR(lz));
d=acos(sqrt(SQR(lx)+SQR(ly))/r);
if (lz<0.0) d*=-1.0;
d=90.0-d/DRC;
RiTransformBegin();
RiTranslate(x,y,z);
RiRotate(-d,ly,-lx,0.0);
/* cylinder 1 */
if (mol[i].atom[n].sel) RiColor(selCol); /* selected black */
else if (flags&4) {
d=mol[i].atom[n].charge;
if (d<0.0) { cCol[2]=1.0; cCol[0]=cCol[1]=1.0+d; }
if (d>=0.0) { cCol[0]=1.0; cCol[1]=cCol[2]=1.0-d; }
RiColor(cCol);
}
else RiColor(elinfo[mol[i].atom[n].anum].color);
RiCylinder(BSR,0.0,r/2.0,360.0,RI_NULL);
/* cylinder 2 */
if (mol[i].atom[ln].sel) RiColor(selCol); /* selected black */
else if (flags&4) {
d=mol[i].atom[ln].charge;
if (d<0.0) { cCol[2]=1.0; cCol[0]=cCol[1]=1.0+d; }
if (d>=0.0) { cCol[0]=1.0; cCol[1]=cCol[2]=1.0-d; }
RiColor(cCol);
}
else RiColor(elinfo[mol[i].atom[ln].anum].color);
RiCylinder(BSR,r/2.0,r,360.0,RI_NULL);
RiTransformEnd();
}
}
}
/* ball and stick mode */
else if ((flags&3)==1) {
for (i=0; i<nmol; i++) {
if ((mode&3)>=2) RiColor(dCol);
else RiColor(dCol);
ln=-1;
/* no ellipticity info. Just spheres are faster */
if (mol[i].ell==NULL) {
for (j=0; j<mol[i].numa; j++) {
if (j%20==0) {
RiSynchronize( RI_FLUSH );
RiSynchronize( RI_WAIT );
}
x=mol[i].coord[j][0];
y=mol[i].coord[j][1];
z=mol[i].coord[j][2];
n=mol[i].atom[j].anum;
r=elinfo[n].rad/BSS;
if (flags&4) {
d=mol[i].atom[j].charge;
if (d<0.0) { cCol[2]=1.0; cCol[0]=cCol[1]=1.0+d; }
if (d>=0.0) { cCol[0]=1.0; cCol[1]=cCol[2]=1.0-d; }
RiColor(cCol);
}
else if (n!=ln) RiColor(elinfo[n].color);
ln=n;
if (mol[i].atom[j].sel) { RiColor(selCol); ln=-1; }
RiTransformBegin();
RiTranslate(x,y,z);
RiSphere(r,-r,r,360.0,RI_NULL);
RiTransformEnd();
}
RiColor(stCol);
for (j=0; j<mol[i].numlb; j++) {
if (j%20==0) {
RiSynchronize( RI_FLUSH );
RiSynchronize( RI_WAIT );
}
n=mol[i].lb[j].n1;
ln=mol[i].lb[j].n2;
x=mol[i].coord[n][0];
y=mol[i].coord[n][1];
z=mol[i].coord[n][2];
lx=mol[i].coord[ln][0]-x;
ly=mol[i].coord[ln][1]-y;
lz=mol[i].coord[ln][2]-z;
r=sqrt(SQR(lx)+SQR(ly)+SQR(lz));
d=acos(sqrt(SQR(lx)+SQR(ly))/r);
if (lz<0.0) d*=-1.0;
d=90.0-d/DRC;
RiTransformBegin();
RiTranslate(x,y,z);
RiRotate(-d,ly,-lx,0.0);
RiCylinder(BSR,0.0,r,360.0,RI_NULL);
RiTransformEnd();
}
}
/* Draw ellipsoids instead of spheres (otherwise identical) */
else {
for (j=0; j<mol[i].numa; j++) {
if (j%20==0) {
RiSynchronize( RI_FLUSH );
RiSynchronize( RI_WAIT );
}
x=mol[i].coord[j][0];
y=mol[i].coord[j][1];
z=mol[i].coord[j][2];
n=mol[i].atom[j].anum;
if (flags&4) {
d=mol[i].atom[j].charge;
if (d<0.0) { cCol[2]=1.0; cCol[0]=cCol[1]=1.0+d; }
if (d>=0.0) { cCol[0]=1.0; cCol[1]=cCol[2]=1.0-d; }
RiColor(cCol);
}
else if (n!=ln) RiColor(elinfo[n].color);
ln=n;
if (mol[i].atom[j].sel) { RiColor(selCol); ln=-1; }
RiTransformBegin();
RiTranslate(x,y,z);
RiRotate(mol[i].ell[j].dz,0.0,0.0,1.0);
RiRotate(mol[i].ell[j].dx,1.0,0.0,0.0);
RiRotate(mol[i].ell[j].dz2,0.0,0.0,1.0);
RiScale(mol[i].ell[j].x/BSS,mol[i].ell[j].y/BSS,
mol[i].ell[j].z/BSS);
RiSphere(1.0,-1.0,1.0,360.0,RI_NULL);
RiTransformEnd();
}
RiColor(stCol);
for (j=0; j<mol[i].numlb; j++) {
if (j%20==0) {
RiSynchronize( RI_FLUSH );
RiSynchronize( RI_WAIT );
}
n=mol[i].lb[j].n1;
ln=mol[i].lb[j].n2;
x=mol[i].coord[n][0];
y=mol[i].coord[n][1];
z=mol[i].coord[n][2];
lx=mol[i].coord[ln][0]-x;
ly=mol[i].coord[ln][1]-y;
lz=mol[i].coord[ln][2]-z;
r=sqrt(SQR(lx)+SQR(ly)+SQR(lz));
d=acos(sqrt(SQR(lx)+SQR(ly))/r);
if (lz<0.0) d*=-1.0;
d=90.0-d/DRC;
RiTransformBegin();
RiTranslate(x,y,z);
RiRotate(-d,ly,-lx,0.0);
RiCylinder(BSR,0.0,r,360.0,RI_NULL);
RiTransformEnd();
}
}
}
}
/* space filling mode */
else if ((flags&3)==2) {
lx=ly=lz=0;
for (i=0; i<nmol; i++) {
if ((mode&3)>=2) RiColor(dCol);
else RiColor(dCol);
ln=-1;
/* no ellipsoids */
if (mol[i].ell==NULL) {
for (j=0; j<mol[i].numa; j++) {
if (j%20==0) {
RiSynchronize( RI_FLUSH );
RiSynchronize( RI_WAIT );
}
x=mol[i].coord[j][0];
y=mol[i].coord[j][1];
z=mol[i].coord[j][2];
n=mol[i].atom[j].anum;
r=elinfo[n].rad;
if (flags&4) {
d=mol[i].atom[j].charge;
if (d<0.0) { cCol[2]=1.0; cCol[0]=cCol[1]=1.0+d; }
if (d>=0.0) { cCol[0]=1.0; cCol[1]=cCol[2]=1.0-d; }
RiColor(cCol);
}
else if (n!=ln) RiColor(elinfo[n].color);
ln=n;
if (mol[i].atom[j].sel) { RiColor(selCol); ln=-1; }
RiTranslate(x-lx,y-ly,z-lz);
RiSphere(r,-r,r,360.0,RI_NULL);
if (r==0.0) printf("%d %d %f %f %f\n",j,n,x,y,z);
lx=x; ly=y; lz=z;
}
}
/* Ellipsoids */
else {
for (j=0; j<mol[i].numa; j++) {
if (j%20==0) {
RiSynchronize( RI_FLUSH );
RiSynchronize( RI_WAIT );
}
x=mol[i].coord[j][0];
y=mol[i].coord[j][1];
z=mol[i].coord[j][2];
n=mol[i].atom[j].anum;
r=elinfo[n].rad;
if (flags&4) {
d=mol[i].atom[j].charge;
if (d<0.0) { cCol[2]=1.0; cCol[0]=cCol[1]=1.0+d; }
if (d>=0.0) { cCol[0]=1.0; cCol[1]=cCol[2]=1.0-d; }
RiColor(cCol);
}
else if (n!=ln) RiColor(elinfo[n].color);
ln=n;
if (mol[i].atom[j].sel) { RiColor(selCol); ln=-1; }
RiTransformBegin();
RiTranslate(x,y,z);
RiRotate(mol[i].ell[j].dz,0.0,0.0,1.0);
RiRotate(mol[i].ell[j].dx,1.0,0.0,0.0);
RiRotate(mol[i].ell[j].dz2,0.0,0.0,1.0);
RiScale(mol[i].ell[j].x,mol[i].ell[j].y,mol[i].ell[j].z);
RiSphere(1.0,-1.0,1.0,360.0,RI_NULL);
lx=x; ly=y; lz=z;
RiTransformEnd();
}
}
}
}
return self;
}
-setData:(Molecule *)Mol :(int)Nmol :(struct ELINFO *)Elinfo :(int)Mode :(int)Flags
{
mol=Mol;
nmol=Nmol;
elinfo=Elinfo;
mode=Mode;
flags=Flags;
return self;
}
-setAng:(float)Theta :(float)Chi :(float)Phi
{
theta=Theta/DRC;
chi=Chi/DRC;
phi=Phi/DRC;
return self;
}
- setSurfaceType:(N3DSurfaceType)st andDescendants:(BOOL)flag
{
[super setSurfaceType:st andDescendants:flag];
return self;
}
-setBSSR:(float)bss :(float)bsr
{
BSS=bss;
BSR=bsr;
if (BSS<=0.0) BSS=1.0;
if (BSR<=0.0) BSR=0.1;
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.