1
2
3 /*
4 A* -------------------------------------------------------------------
5 B* This file contains source code for the PyMOL computer program
6 C* Copyright (c) Schrodinger, LLC.
7 D* -------------------------------------------------------------------
8 E* It is unlawful to modify or remove this copyright notice.
9 F* -------------------------------------------------------------------
10 G* Please see the accompanying LICENSE file for further information.
11 H* -------------------------------------------------------------------
12 I* Additional authors of this source file include:
13 -*
14 -*
15 -*
16 Z* -------------------------------------------------------------------
17 */
18
19 #include"os_predef.h"
20 #include"os_std.h"
21 #include"os_gl.h"
22
23 #include"Base.h"
24 #include"Sphere.h"
25 #include"Vector.h"
26 #include"Err.h"
27
28 #include"MemoryDebug.h"
29
30 #define FAST_SPHERE_INIT
31
32 #ifndef FAST_SPHERE_INIT
33 /* Twelve vertices of icosahedron on unit sphere */
34 #define tau 0.8506508084F /* t=(1+sqrt(5))/2, tau=t/sqrt(1+t^2) */
35 #define one 0.5257311121F /* one=1/sqrt(1+t^2) , unit sphere */
36
37 static const float start_points[13][3] = {
38 {tau, one, 0},
39 {-tau, one, 0},
40 {-tau, -one, 0},
41 {tau, -one, 0},
42 {one, 0, tau},
43 {one, 0, -tau},
44 {-one, 0, -tau},
45 {-one, 0, tau},
46 {0, tau, one},
47 {0, -tau, one},
48 {0, -tau, -one},
49 {0, tau, -one}
50 };
51
52 static const int icosahedron[21][3] = {
53 {4, 8, 7},
54 {4, 7, 9},
55 {5, 6, 11},
56 {5, 10, 6},
57 {0, 4, 3},
58 {0, 3, 5},
59 {2, 7, 1},
60 {2, 1, 6},
61 {8, 0, 11},
62 {8, 11, 1},
63 {9, 10, 3},
64 {9, 2, 10},
65 {8, 4, 0},
66 {11, 0, 5},
67 {4, 9, 3},
68 {5, 3, 10},
69 {7, 8, 1},
70 {6, 1, 11},
71 {7, 2, 9},
72 {6, 10, 2}
73 };
74 #endif
75
76 static const int mesh[30][2] = {
77 {0, 3},
78 {0, 4},
79 {0, 5},
80 {0, 8},
81 {0, 11},
82 {1, 2},
83 {1, 6},
84 {1, 7},
85 {1, 8},
86 {1, 11},
87 {2, 6},
88 {2, 7},
89 {2, 9},
90 {2, 10},
91 {3, 4},
92 {3, 5},
93 {3, 9},
94 {3, 10},
95 {4, 7},
96 {4, 8},
97 {4, 9},
98 {5, 6},
99 {5, 10},
100 {5, 11},
101 {6, 10},
102 {6, 11},
103 {7, 8},
104 {7, 9},
105 {8, 11},
106 {9, 10}
107 };
108
109 #ifdef FAST_SPHERE_INIT
110 #include"SphereData.h"
111
112 #else
113
114 static SphereRec *MakeDotSphere(PyMOLGlobals * G, int level);
115
116 #endif
117
118 #ifndef FAST_SPHERE_INIT
SphereDumpAll(CSphere * I)119 static void SphereDumpAll(CSphere *I)
120 {
121 FILE *f;
122 int i, dot_total, a, c, strip_total, seq_total, tri_total;
123 SphereRec *sp;
124 f = fopen("SphereData.h", "w");
125
126 fprintf(f, "static int Sphere_NSpheres = %d;\n", NUMBER_OF_SPHERE_LEVELS);
127
128 fprintf(f, "static int Sphere_NTri[%d] = {\n", NUMBER_OF_SPHERE_LEVELS);
129 for (i=0; i < NUMBER_OF_SPHERE_LEVELS; i++){
130 fprintf(f, " %d, ", I->Sphere[i]->NTri);
131 }
132 fprintf(f, "\n};\n");
133
134 fprintf(f, "static int Sphere_NStrip[%d] = {\n", NUMBER_OF_SPHERE_LEVELS);
135 for (i=0; i < NUMBER_OF_SPHERE_LEVELS; i++){
136 fprintf(f, " %d, ", I->Sphere[i]->NStrip);
137 }
138 fprintf(f, "\n};\n");
139
140 fprintf(f, "static int Sphere_NVertTot[%d] = {\n", NUMBER_OF_SPHERE_LEVELS);
141 for (i=0; i < NUMBER_OF_SPHERE_LEVELS; i++){
142 fprintf(f, " %d, ", I->Sphere[i]->NVertTot);
143 }
144 fprintf(f, "\n};\n");
145
146 fprintf(f, "static int Sphere_nDot[%d] = {\n", NUMBER_OF_SPHERE_LEVELS);
147 for (i=0; i < NUMBER_OF_SPHERE_LEVELS; i++){
148 fprintf(f, " %d, ", I->Sphere[i]->nDot);
149 }
150 fprintf(f, "\n};\n");
151
152 fprintf(f, "static int Sphere_dot_start[%d] = {\n", NUMBER_OF_SPHERE_LEVELS);
153 dot_total = 0;
154 for (i=0; i < NUMBER_OF_SPHERE_LEVELS; i++){
155 fprintf(f, " %d, ", dot_total);
156 dot_total += I->Sphere[i]->nDot;
157 }
158 fprintf(f, "\n};\n");
159
160 fprintf(f, "static float Sphere_dot[][3] = {\n");
161 for (i=0; i < NUMBER_OF_SPHERE_LEVELS; i++){
162 sp = I->Sphere[i];
163 fprintf(f, "/* dots for Sphere #%d */\n", i);
164 for(a = 0; a < sp->nDot; a++) {
165 fprintf(f, "{ %15.12fF, %15.12fF, %15.12fF },\n",
166 sp->dot[a][0], sp->dot[a][1], sp->dot[a][2]);
167 }
168 }
169 fprintf(f, "};\n");
170
171 fprintf(f, "static float Sphere_area[] = {\n");
172 for (i=0; i < NUMBER_OF_SPHERE_LEVELS; i++){
173 sp = I->Sphere[i];
174 fprintf(f, "/* areas for Sphere #%d */\n", i);
175 c = 0;
176 for(a = 0; a < sp->nDot; a++) {
177 fprintf(f, "%15.12fF,", sp->area[a]);
178 c = (c + 1) % 4;
179 if (!c)
180 fprintf(f, "\n");
181 }
182 if (c)
183 fprintf(f, "\n");
184 }
185 fprintf(f, "};\n");
186
187
188 fprintf(f, "static int Sphere_StripLen_start[%d] = {\n", NUMBER_OF_SPHERE_LEVELS);
189 strip_total = 0;
190 for (i=0; i < NUMBER_OF_SPHERE_LEVELS; i++){
191 fprintf(f, " %d, ", strip_total);
192 strip_total += I->Sphere[i]->NStrip;
193 }
194 fprintf(f, "\n};\n");
195
196 fprintf(f, "static int Sphere_StripLen[] = {\n");
197 for (i=0; i < NUMBER_OF_SPHERE_LEVELS; i++){
198 sp = I->Sphere[i];
199 fprintf(f, "/* StripLen for Sphere #%d */\n", i);
200 c = 0;
201 for(a = 0; a < sp->NStrip; a++) {
202 fprintf(f, "%6d,", sp->StripLen[a]);
203 c = (c + 1) % 10;
204 if(!c)
205 fprintf(f, "\n");
206 }
207 if (c)
208 fprintf(f, "\n");
209 }
210 fprintf(f, "};\n");
211
212 fprintf(f, "static int Sphere_Sequence_start[%d] = {\n", NUMBER_OF_SPHERE_LEVELS);
213 seq_total = 0;
214 for (i=0; i < NUMBER_OF_SPHERE_LEVELS; i++){
215 fprintf(f, " %d, ", seq_total);
216 seq_total += I->Sphere[i]->NVertTot;
217 }
218 fprintf(f, "\n};\n");
219
220 fprintf(f, "static int Sphere_Sequence[] = {\n");
221 for (i=0; i < NUMBER_OF_SPHERE_LEVELS; i++){
222 sp = I->Sphere[i];
223 fprintf(f, "/* Sequence for Sphere #%d */\n", i);
224 c = 0;
225 for(a = 0; a < sp->NVertTot; a++) {
226 fprintf(f, "%6d,", sp->Sequence[a]);
227 c = (c + 1) % 10;
228 if(!c)
229 fprintf(f, "\n");
230 }
231 if (c)
232 fprintf(f, "\n");
233 }
234 fprintf(f, "};\n");
235
236 fprintf(f, "static int Sphere_Tri_start[%d] = {\n", NUMBER_OF_SPHERE_LEVELS);
237 tri_total = 0;
238 for (i=0; i < NUMBER_OF_SPHERE_LEVELS; i++){
239 fprintf(f, " %d, ", tri_total);
240 tri_total += 3 * I->Sphere[i]->NTri;
241 }
242 fprintf(f, "\n};\n");
243
244 fprintf(f, "static int Sphere_Tri[] = {\n");
245 for (i=0; i < NUMBER_OF_SPHERE_LEVELS; i++){
246 sp = I->Sphere[i];
247 fprintf(f, "/* Tri for Sphere #%d */\n", i);
248 c = 0;
249 for(a = 0; a < 3* sp->NTri; a++) {
250 fprintf(f, "%6d,", sp->Tri[a]);
251 c = (c + 1) % 10;
252 if(!c)
253 fprintf(f, "\n");
254 }
255 if (c)
256 fprintf(f, "\n");
257 }
258 fprintf(f, "};\n");
259
260 fclose(f);
261 }
262 #endif
263
SphereInit(PyMOLGlobals * G)264 void SphereInit(PyMOLGlobals * G)
265 {
266 CSphere *I = (G->Sphere = pymol::calloc<CSphere>(1));
267
268 #ifdef FAST_SPHERE_INIT
269 I->Array = pymol::malloc<SphereRec>(Sphere_NSpheres);
270
271 {
272 int i;
273 for (i=0; i<Sphere_NSpheres; i++){
274 I->Array[i].area = &Sphere_area[Sphere_dot_start[i]];
275 I->Array[i].dot = &Sphere_dot[Sphere_dot_start[i]];
276 I->Array[i].StripLen = &Sphere_StripLen[Sphere_StripLen_start[i]];
277 I->Array[i].Sequence = &Sphere_Sequence[Sphere_Sequence_start[i]];
278 I->Array[i].NStrip = Sphere_NStrip[i];
279 I->Array[i].NVertTot = Sphere_NVertTot[i];
280 I->Array[i].nDot = Sphere_nDot[i];
281 I->Array[i].Tri = &Sphere_Tri[Sphere_Tri_start[i]];
282 I->Array[i].NTri = Sphere_NTri[i];
283
284 if (i){
285 I->Array[i].Mesh = NULL;
286 I->Array[i].NMesh = 0;
287 } else {
288 I->Array[i].Mesh = (int *) (void *) mesh;
289 I->Array[i].NMesh = 30;
290 }
291 I->Sphere[i] = &I->Array[i];
292 }
293 }
294 #else
295 {
296 int i;
297 for (i=0; i<NUMBER_OF_SPHERE_LEVELS; i++){
298 I->Sphere[i] = MakeDotSphere(G, i);
299 }
300 SphereDumpAll(I);
301 }
302 #endif
303
304 }
305
306 #ifndef FAST_SPHERE_INIT
SpherePurge(SphereRec * I)307 static void SpherePurge(SphereRec * I)
308 {
309 /* NOTE: S->Mesh is not currently a pointer */
310 mfree(I->dot);
311 mfree(I->area);
312 mfree(I->StripLen);
313 mfree(I->Sequence);
314 mfree(I->Tri);
315 FreeP(I);
316 }
317 #endif
318
SphereFree(PyMOLGlobals * G)319 void SphereFree(PyMOLGlobals * G)
320 {
321 CSphere *I = G->Sphere;
322
323 #ifndef FAST_SPHERE_INIT
324 SpherePurge(I->Sphere[0]);
325 SpherePurge(I->Sphere[1]);
326 SpherePurge(I->Sphere[2]);
327 SpherePurge(I->Sphere[3]);
328 SpherePurge(I->Sphere[4]);
329 #else
330 FreeP(I->Array);
331 #endif
332 FreeP(I);
333 }
334
335
336 /* private stuff */
337
338 #ifndef FAST_SPHERE_INIT
339
340 // MAXDOT : 12, 42, 162, 642, 2562 ... :: 12 + (30 + 120 + 480 + 1920 + ... ) :: 12 + ( 30 + (30*4) + (30*4*4) + (30*4*4*4) + ... )
341 // MAXTRI : 80, 320, 1280, 5120, ... :: 20*1 + 20*4 + 20*4*4 + 20*4*4*4 + 20*4*4*4*4 ::
342
343 //For NUMBER_OF_SPHERE_LEVELS=6
344 //#define MAXDOT 12900 // 12800
345 //#define MAXTRI 20500 // 20480
346
347 //For NUMBER_OF_SPHERE_LEVELS=5
348 #define MAXDOT 2600 // 2562
349 #define MAXTRI 5200 // 5120
350
351 typedef int EdgeCol[MAXDOT]; /* should move these into dynamic storage to save 3MB mem */
352 typedef EdgeCol EdgeArray[MAXDOT];
353
354 typedef int Triangle[3];
355
356 typedef struct {
357
358 float *Dot;
359 EdgeArray *EdgeRef;
360 Triangle *Tri;
361 int NDot, NTri;
362
363 } SphereBuilderRec;
364
MakeVertex(SphereBuilderRec * S,int d1,int d2)365 static void MakeVertex(SphereBuilderRec * S, int d1, int d2)
366 {
367 if((*S->EdgeRef)[d1][d2] < 0) {
368 average3f(S->Dot + (3 * d1), S->Dot + (3 * d2), S->Dot + (3 * S->NDot));
369 (*S->EdgeRef)[d1][d2] = S->NDot;
370 (*S->EdgeRef)[d2][d1] = S->NDot;
371 normalize3f(S->Dot + (3 * S->NDot));
372 S->NDot++;
373 }
374 }
375
SphericalAngle(SphereBuilderRec * S,int d0,int d1,int d2)376 static float SphericalAngle(SphereBuilderRec * S, int d0, int d1, int d2)
377 {
378 Vector3f v1, v2, s1, s2;
379
380 /* map vector onto surface of sphere and measure angle */
381 subtract3f(S->Dot + (3 * d1), S->Dot + (3 * d0), v1);
382 subtract3f(S->Dot + (3 * d2), S->Dot + (3 * d0), v2);
383
384 remove_component3f(v1, S->Dot + (3 * d0), s1);
385 remove_component3f(v2, S->Dot + (3 * d0), s2);
386 return (get_angle3f(s1, s2));
387
388 }
389
MakeDotSphere(PyMOLGlobals * G,int level)390 static SphereRec *MakeDotSphere(PyMOLGlobals * G, int level)
391 {
392 SphereRec *result;
393 int *TriFlag;
394 int a, b, c, h, k, l, curTri, n, it;
395 float area, sumArea = 0.0;
396 int nStrip, *q, *s;
397 int nVertTot;
398 int flag;
399 float vt1[3], vt2[3], vt[3];
400 SphereBuilderRec SBuild, *S;
401 S = &SBuild;
402
403 S->Dot = pymol::malloc<float>(3 * MAXDOT);
404 ErrChkPtr(G, S->Dot);
405 S->EdgeRef = pymol::malloc<EdgeArray>(1);
406 ErrChkPtr(G, S->EdgeRef);
407 S->Tri = pymol::malloc<Triangle>(MAXTRI);
408 ErrChkPtr(G, S->Tri);
409 TriFlag = pymol::malloc<int>(MAXTRI);
410 ErrChkPtr(G, TriFlag);
411
412 S->NDot = 12;
413 for(a = 0; a < S->NDot; a++) {
414 for(c = 0; c < 3; c++)
415 S->Dot[3 * a + c] = start_points[a][c];
416 normalize3f(S->Dot + (3 * a));
417 }
418
419 S->NTri = 20;
420 for(a = 0; a < S->NTri; a++)
421 for(c = 0; c < 3; c++)
422 S->Tri[a][c] = icosahedron[a][c];
423
424 for(a = 0; a < MAXDOT; a++)
425 for(b = 0; b < MAXDOT; b++)
426 (*S->EdgeRef)[a][b] = -1;
427
428 if(level > (NUMBER_OF_SPHERE_LEVELS-1))
429 level = (NUMBER_OF_SPHERE_LEVELS-1);
430
431 for(c = 0; c < level; c++) {
432 /* create new vertices */
433 for(a = 0; a < S->NTri; a++) {
434 MakeVertex(S, S->Tri[a][0], S->Tri[a][1]);
435 MakeVertex(S, S->Tri[a][1], S->Tri[a][2]);
436 MakeVertex(S, S->Tri[a][0], S->Tri[a][2]);
437 }
438 /* create new triangles */
439 curTri = S->NTri;
440 for(a = 0; a < curTri; a++) {
441 h = S->Tri[a][0];
442 k = S->Tri[a][1];
443 l = S->Tri[a][2];
444
445 S->Tri[a][0] = h;
446 S->Tri[a][1] = (*S->EdgeRef)[h][k];
447 S->Tri[a][2] = (*S->EdgeRef)[h][l];
448
449 S->Tri[S->NTri][0] = k;
450 S->Tri[S->NTri][1] = (*S->EdgeRef)[k][h];
451 S->Tri[S->NTri][2] = (*S->EdgeRef)[k][l];
452 S->NTri++;
453
454 S->Tri[S->NTri][0] = l;
455 S->Tri[S->NTri][1] = (*S->EdgeRef)[l][h];
456 S->Tri[S->NTri][2] = (*S->EdgeRef)[l][k];
457 S->NTri++;
458
459 S->Tri[S->NTri][0] = (*S->EdgeRef)[h][k];
460 S->Tri[S->NTri][1] = (*S->EdgeRef)[k][l];
461 S->Tri[S->NTri][2] = (*S->EdgeRef)[l][h];
462 S->NTri++;
463 }
464 // printf( "MakeDotSphere: Level: %i S->NTri: %i\n",c, S->NTri);
465 }
466 // printf(" MakeDotSphere: NDot %i S->NTri %i\n",S->NDot,S->NTri);
467 result = pymol::malloc<SphereRec>(1);
468 ErrChkPtr(G, result);
469 result->dot = pymol::malloc<Vector3f>(S->NDot);
470 ErrChkPtr(G, result->dot);
471 result->area = pymol::malloc<float>(S->NDot);
472 ErrChkPtr(G, result->area);
473 result->StripLen = pymol::malloc<int>(S->NTri * 3);
474 ErrChkPtr(G, result->StripLen);
475 result->Sequence = pymol::malloc<int>(S->NTri * 3);
476 ErrChkPtr(G, result->Sequence);
477
478 for(a = 0; a < S->NDot; a++) {
479 for(c = 0; c < 3; c++)
480 result->dot[a][c] = *(S->Dot + (3 * a + c));
481 result->area[a] = 0.0;
482 }
483
484 /* fix normals so that v1-v0 x v2-v0 is the correct normal */
485
486 for(a = 0; a < S->NTri; a++) {
487 subtract3f(result->dot[S->Tri[a][1]], result->dot[S->Tri[a][0]], vt1);
488 subtract3f(result->dot[S->Tri[a][2]], result->dot[S->Tri[a][0]], vt2);
489 cross_product3f(vt1, vt2, vt);
490 if(dot_product3f(vt, result->dot[S->Tri[a][0]]) < 0.0) { /* if wrong, then interchange */
491 it = S->Tri[a][2];
492 S->Tri[a][2] = S->Tri[a][1];
493 S->Tri[a][1] = it;
494 }
495 }
496
497 for(a = 0; a < S->NTri; a++) {
498 area = (float) (SphericalAngle(S, S->Tri[a][0], S->Tri[a][1], S->Tri[a][2]) +
499 SphericalAngle(S, S->Tri[a][1], S->Tri[a][0], S->Tri[a][2]) +
500 SphericalAngle(S, S->Tri[a][2], S->Tri[a][0], S->Tri[a][1]) - cPI);
501 /* multiply by r^2 to get area */
502 sumArea += area;
503 area /= 3.0;
504 result->area[S->Tri[a][0]] += area;
505 result->area[S->Tri[a][1]] += area;
506 result->area[S->Tri[a][2]] += area;
507 }
508
509 if(fabs(sumArea - (4 * cPI)) > 0.001) {
510 printf(" MakeDotSphere: sumArea: %8.6f which is %8.6f Pi\n", sumArea, sumArea / cPI);
511 ErrFatal(G, "MakeDotSphere", "Area of sphere does not sum to 4*pi!\n");
512 }
513
514 for(a = 0; a < S->NTri; a++)
515 TriFlag[a] = false;
516
517 nStrip = 0;
518 nVertTot = 0;
519 s = result->StripLen;
520 q = result->Sequence;
521
522 /* tesselate the sphere in a semi-efficient fashion...this could definitely be improved */
523
524 flag = true;
525 while(flag) {
526 flag = false;
527 a = 0;
528 while(a < S->NTri) {
529 if(!TriFlag[a]) {
530 flag = true;
531
532 TriFlag[a] = true;
533 *(q++) = S->Tri[a][0];
534 *(q++) = S->Tri[a][1];
535 *(q++) = S->Tri[a][2];
536 n = 3;
537
538 b = 0;
539 while(b < S->NTri) {
540 if(!TriFlag[b]) {
541 if(((S->Tri[b][0] == q[-2]) && (S->Tri[b][1] == q[-1])) ||
542 ((S->Tri[b][0] == q[-1]) && (S->Tri[b][1] == q[-2]))) {
543 *(q++) = S->Tri[b][2];
544 TriFlag[b] = true;
545 b = 0;
546 n++;
547 } else if(((S->Tri[b][0] == q[-2]) && (S->Tri[b][2] == q[-1])) ||
548 ((S->Tri[b][0] == q[-1]) && (S->Tri[b][2] == q[-2]))) {
549 *(q++) = S->Tri[b][1];
550 TriFlag[b] = true;
551 b = 0;
552 n++;
553 } else if(((S->Tri[b][2] == q[-2]) && (S->Tri[b][1] == q[-1])) ||
554 ((S->Tri[b][2] == q[-1]) && (S->Tri[b][1] == q[-2]))) {
555 *(q++) = S->Tri[b][0];
556 TriFlag[b] = true;
557 b = 0;
558 n++;
559 }
560 }
561 b++;
562 }
563 if(n == 3) {
564 q[-3] = S->Tri[a][1];
565 q[-2] = S->Tri[a][2];
566 q[-1] = S->Tri[a][0];
567
568 b = 0;
569 while(b < S->NTri) {
570 if(!TriFlag[b]) {
571 if(((S->Tri[b][0] == q[-2]) && (S->Tri[b][1] == q[-1])) ||
572 ((S->Tri[b][0] == q[-1]) && (S->Tri[b][1] == q[-2]))) {
573 *(q++) = S->Tri[b][2];
574 TriFlag[b] = true;
575 b = 0;
576 n++;
577 } else if(((S->Tri[b][0] == q[-2]) && (S->Tri[b][2] == q[-1])) ||
578 ((S->Tri[b][0] == q[-1]) && (S->Tri[b][2] == q[-2]))) {
579 *(q++) = S->Tri[b][1];
580 TriFlag[b] = true;
581 b = 0;
582 n++;
583 } else if(((S->Tri[b][2] == q[-2]) && (S->Tri[b][1] == q[-1])) ||
584 ((S->Tri[b][2] == q[-1]) && (S->Tri[b][1] == q[-2]))) {
585 *(q++) = S->Tri[b][0];
586 TriFlag[b] = true;
587 b = 0;
588 n++;
589 }
590 }
591 b++;
592 }
593 }
594 if(n == 3) {
595 q[-3] = S->Tri[a][2];
596 q[-2] = S->Tri[a][0];
597 q[-1] = S->Tri[a][1];
598 b = 0;
599 while(b < S->NTri) {
600 if(!TriFlag[b]) {
601 if(((S->Tri[b][0] == q[-2]) && (S->Tri[b][1] == q[-1])) ||
602 ((S->Tri[b][0] == q[-1]) && (S->Tri[b][1] == q[-2]))) {
603 *(q++) = S->Tri[b][2];
604 TriFlag[b] = true;
605 b = 0;
606 n++;
607 } else if(((S->Tri[b][0] == q[-2]) && (S->Tri[b][2] == q[-1])) ||
608 ((S->Tri[b][0] == q[-1]) && (S->Tri[b][2] == q[-2]))) {
609 *(q++) = S->Tri[b][1];
610 TriFlag[b] = true;
611 b = 0;
612 n++;
613 } else if(((S->Tri[b][2] == q[-2]) && (S->Tri[b][1] == q[-1])) ||
614 ((S->Tri[b][2] == q[-1]) && (S->Tri[b][1] == q[-2]))) {
615 *(q++) = S->Tri[b][0];
616 TriFlag[b] = true;
617 b = 0;
618 n++;
619 }
620 }
621 b++;
622 }
623 }
624 *(s++) = n;
625 nVertTot += n;
626 nStrip++;
627 }
628 a++;
629 }
630 }
631 mfree(S->Dot);
632 mfree(S->EdgeRef);
633 mfree(TriFlag);
634 result->Tri = (int *) S->Tri;
635 result->Tri = pymol::realloc(result->Tri, S->NTri * 3);
636 result->NTri = S->NTri;
637 result->StripLen = pymol::realloc(result->StripLen, nStrip);
638 result->Sequence = pymol::realloc(result->Sequence, nVertTot);
639 result->dot = pymol::realloc(result->dot, S->NDot);
640 result->area = pymol::realloc(result->area, S->NDot);
641 result->nDot = S->NDot;
642 result->NStrip = nStrip;
643 result->NVertTot = nVertTot;
644 result->Mesh = NULL;
645 result->NMesh = 0;
646 if(!level) { /* provide mesh for S->Sphere[0] only...rest, to do. */
647 result->Mesh = (int *) mesh;
648 result->NMesh = 30;
649 }
650 /*
651 q=result->Sequence;
652 for(a=0;a<result->NStrip;a++)
653 {
654 printf("%d:",result->StripLen[a]);
655 for(b=0;b<result->StripLen[a];b++)
656 {
657 printf("%d ",*(q++));
658 }
659 printf("\n");
660 }
661 */
662
663 return (result);
664 }
665
666 #endif
667
SphereRender(PyMOLGlobals * G,int level,const float * centroid,const float * color,float alpha,float radius)668 void SphereRender(PyMOLGlobals * G, int level, const float *centroid, const float *color, float alpha, float radius){
669 #ifndef PURE_OPENGL_ES_2
670 SphereRec *sp = G->Sphere->Sphere[level];
671 int a, cc;
672 int *q = sp->Sequence;
673 float pt[3];
674 if (color)
675 glColor4f(color[0], color[1], color[2], alpha);
676 for(a = 0; a < sp->NStrip; a++) {
677 glBegin(GL_TRIANGLE_STRIP);
678 cc = sp->StripLen[a];
679 while(cc--) {
680 glNormal3fv(sp->dot[*q]);
681 mult3f(sp->dot[*q], radius, pt);
682 add3f(centroid, pt, pt);
683 glVertex3fv(pt);
684 q++;
685 }
686 glEnd();
687 }
688 #endif
689 }
690
GetSpheroidSphereRec(PyMOLGlobals * G)691 SphereRec* GetSpheroidSphereRec(PyMOLGlobals* G)
692 {
693 return G->Sphere->Sphere[2];
694 }
695