1
2 /*
3 A* -------------------------------------------------------------------
4 B* This file contains source code for the PyMOL computer program
5 C* copyright 1998-2000 by Warren Lyford Delano of DeLano Scientific.
6 D* -------------------------------------------------------------------
7 E* It is unlawful to modify or remove this copyright notice.
8 F* -------------------------------------------------------------------
9 G* Please see the accompanying LICENSE file for further information.
10 H* -------------------------------------------------------------------
11 I* Additional authors of this source file include:
12 -*
13 -*
14 -*
15 Z* -------------------------------------------------------------------
16 */
17 #include"os_python.h"
18
19 #include"os_predef.h"
20 #include"os_std.h"
21 #include"os_gl.h"
22
23 #include"OOMac.h"
24 #include"ObjectSurface.h"
25 #include"Base.h"
26 #include"MemoryDebug.h"
27 #include"Map.h"
28 #include"Parse.h"
29 #include"Tetsurf.h"
30 #include"Vector.h"
31 #include"Color.h"
32 #include"main.h"
33 #include"Scene.h"
34 #include"Setting.h"
35 #include"Executive.h"
36 #include"PConv.h"
37 #include"P.h"
38 #include"Util.h"
39 #include"PyMOLGlobals.h"
40 #include"Matrix.h"
41 #include"ShaderMgr.h"
42 #include"CGO.h"
43
44 static void ObjectSurfaceRecomputeExtent(ObjectSurface * I);
45
ObjectSurfaceStateAsPyList(ObjectSurfaceState * I)46 static PyObject *ObjectSurfaceStateAsPyList(ObjectSurfaceState * I)
47 {
48 PyObject *result = NULL;
49
50 result = PyList_New(17);
51
52 PyList_SetItem(result, 0, PyInt_FromLong(I->Active));
53 PyList_SetItem(result, 1, PyString_FromString(I->MapName));
54 PyList_SetItem(result, 2, PyInt_FromLong(I->MapState));
55 PyList_SetItem(result, 3, CrystalAsPyList(&I->Crystal));
56 PyList_SetItem(result, 4, PyInt_FromLong(I->ExtentFlag));
57 PyList_SetItem(result, 5, PConvFloatArrayToPyList(I->ExtentMin, 3));
58 PyList_SetItem(result, 6, PConvFloatArrayToPyList(I->ExtentMax, 3));
59 PyList_SetItem(result, 7, PConvIntArrayToPyList(I->Range, 6));
60 PyList_SetItem(result, 8, PyFloat_FromDouble(I->Level));
61 PyList_SetItem(result, 9, PyFloat_FromDouble(I->Radius));
62 PyList_SetItem(result, 10, PyInt_FromLong(I->CarveFlag));
63 PyList_SetItem(result, 11, PyFloat_FromDouble(I->CarveBuffer));
64 if(I->CarveFlag && I->AtomVertex) {
65 PyList_SetItem(result, 12, PConvFloatVLAToPyList(I->AtomVertex));
66 } else {
67 PyList_SetItem(result, 12, PConvAutoNone(NULL));
68 }
69 PyList_SetItem(result, 13, PyInt_FromLong(I->DotFlag));
70 PyList_SetItem(result, 14, PyInt_FromLong(I->Mode));
71 PyList_SetItem(result, 15, PyInt_FromLong(I->Side));
72 PyList_SetItem(result, 16, PyInt_FromLong(I->quiet));
73
74 return (PConvAutoNone(result));
75 }
76
ObjectSurfaceAllStatesAsPyList(ObjectSurface * I)77 static PyObject *ObjectSurfaceAllStatesAsPyList(ObjectSurface * I)
78 {
79
80 auto result = PyList_New(I->State.size());
81 for(int a = 0; a < I->State.size(); a++) {
82 if(I->State[a].Active) {
83 PyList_SetItem(result, a, ObjectSurfaceStateAsPyList(&I->State[a]));
84 } else {
85 PyList_SetItem(result, a, PConvAutoNone(NULL));
86 }
87 }
88 return (PConvAutoNone(result));
89
90 }
91
ObjectSurfaceStateFromPyList(PyMOLGlobals * G,ObjectSurfaceState * I,PyObject * list)92 static int ObjectSurfaceStateFromPyList(PyMOLGlobals * G, ObjectSurfaceState * I,
93 PyObject * list)
94 {
95 int ok = true;
96 int ll = 0;
97 PyObject *tmp;
98 if(ok)
99 ok = (list != NULL);
100 if(ok) {
101 if(!PyList_Check(list))
102 I->Active = false;
103 else {
104 *I = ObjectSurfaceState(G);
105 if(ok)
106 ok = PyList_Check(list);
107 if(ok)
108 ll = PyList_Size(list);
109 if(ok)
110 ok = PConvPyIntToInt(PyList_GetItem(list, 0), &I->Active);
111 if(ok)
112 ok = PConvPyStrToStr(PyList_GetItem(list, 1), I->MapName, WordLength);
113 if(ok)
114 ok = PConvPyIntToInt(PyList_GetItem(list, 2), &I->MapState);
115 if(ok)
116 ok = CrystalFromPyList(&I->Crystal, PyList_GetItem(list, 3));
117 if(ok)
118 ok = PConvPyIntToInt(PyList_GetItem(list, 4), &I->ExtentFlag);
119 if(ok)
120 ok = PConvPyListToFloatArrayInPlace(PyList_GetItem(list, 5), I->ExtentMin, 3);
121 if(ok)
122 ok = PConvPyListToFloatArrayInPlace(PyList_GetItem(list, 6), I->ExtentMax, 3);
123 if(ok)
124 ok = PConvPyListToIntArrayInPlace(PyList_GetItem(list, 7), I->Range, 6);
125 if(ok)
126 ok = PConvPyFloatToFloat(PyList_GetItem(list, 8), &I->Level);
127 if(ok)
128 ok = PConvPyFloatToFloat(PyList_GetItem(list, 9), &I->Radius);
129 if(ok)
130 ok = PConvPyIntToInt(PyList_GetItem(list, 10), &I->CarveFlag);
131 if(ok)
132 ok = PConvPyFloatToFloat(PyList_GetItem(list, 11), &I->CarveBuffer);
133 if(ok) {
134 tmp = PyList_GetItem(list, 12);
135 if(tmp == Py_None)
136 I->AtomVertex = NULL;
137 else
138 ok = PConvPyListToFloatVLA(tmp, &I->AtomVertex);
139 }
140 if(ok)
141 ok = PConvPyIntToInt(PyList_GetItem(list, 13), &I->DotFlag);
142 if(ok)
143 ok = PConvPyIntToInt(PyList_GetItem(list, 14), &I->Mode);
144
145 if(ok && (ll > 15))
146 PConvPyIntToInt(PyList_GetItem(list, 15), &I->Side);
147 if(ok && (ll > 16))
148 PConvPyIntToInt(PyList_GetItem(list, 16), &I->quiet);
149
150 if(ok) {
151 I->RefreshFlag = true;
152 I->ResurfaceFlag = true;
153 }
154 }
155 }
156 return (ok);
157 }
158
ObjectSurfaceAllStatesFromPyList(ObjectSurface * I,PyObject * list,int size)159 static int ObjectSurfaceAllStatesFromPyList(ObjectSurface * I, PyObject * list, int size)
160 {
161 int ok = true;
162 I->State.reserve(size);
163 if(ok)
164 ok = PyList_Check(list);
165 if(ok) {
166 for(int a = 0; a < size; a++) {
167 CPythonVal *val = CPythonVal_PyList_GetItem(I->G, list, a);
168 I->State.emplace_back(I->G);
169 ok = ObjectSurfaceStateFromPyList(I->G, &I->State.back(), val);
170 CPythonVal_Free(val);
171 if(!ok)
172 break;
173 }
174 }
175 return (ok);
176 }
177
ObjectSurfaceNewFromPyList(PyMOLGlobals * G,PyObject * list,ObjectSurface ** result)178 int ObjectSurfaceNewFromPyList(PyMOLGlobals * G, PyObject * list, ObjectSurface ** result)
179 {
180 int ok = true;
181 ObjectSurface *I = NULL;
182 (*result) = NULL;
183
184 if(ok)
185 ok = (list != NULL);
186 if(ok)
187 ok = PyList_Check(list);
188
189 I = new ObjectSurface(G);
190 if(ok)
191 ok = (I != NULL);
192
193 if(ok){
194 auto *val = PyList_GetItem(list, 0);
195 ok = ObjectFromPyList(G, val, I);
196 }
197 int size = 0;
198 if(ok)
199 ok = CPythonVal_PConvPyIntToInt_From_List(G, list, 1, &size);
200 if(ok){
201 CPythonVal *val = CPythonVal_PyList_GetItem(G, list, 2);
202 ok = ObjectSurfaceAllStatesFromPyList(I, val, size);
203 CPythonVal_Free(val);
204 }
205 if(ok) {
206 (*result) = I;
207 ObjectSurfaceRecomputeExtent(I);
208 } else {
209 /* cleanup? */
210 }
211 return (ok);
212 }
213
ObjectSurfaceAsPyList(ObjectSurface * I)214 PyObject *ObjectSurfaceAsPyList(ObjectSurface * I)
215 {
216 PyObject *result = NULL;
217
218 result = PyList_New(3);
219 PyList_SetItem(result, 0, ObjectAsPyList(I));
220 PyList_SetItem(result, 1, PyInt_FromLong(I->State.size()));
221 PyList_SetItem(result, 2, ObjectSurfaceAllStatesAsPyList(I));
222
223 return (PConvAutoNone(result));
224 }
225
ObjectSurfaceDump(ObjectSurface * I,const char * fname,int state,int quiet)226 void ObjectSurfaceDump(ObjectSurface * I, const char *fname, int state, int quiet)
227 {
228 FILE* f = fopen(fname, "wb");
229 if(!f)
230 ErrMessage(I->G, "ObjectSurfaceDump", "can't open file for writing");
231 else {
232 if(state < I->State.size()) {
233 auto n = I->State[state].N.data();
234 auto v = I->State[state].V.data();
235 if(n && v)
236 while(*n) {
237 v += 12;
238 int c = *(n++);
239 c -= 4;
240 bool backface = true;
241 const float *v1, *v2;
242 while(c > 0) {
243 if ((backface = !backface)) {
244 v1 = v - 6;
245 v2 = v - 12;
246 } else {
247 v1 = v - 12;
248 v2 = v - 6;
249 }
250 fprintf(f,
251 "%10.4f%10.4f%10.4f%10.4f%10.4f%10.4f\n%10.4f%10.4f%10.4f%10.4f%10.4f%10.4f\n%10.4f%10.4f%10.4f%10.4f%10.4f%10.4f\n",
252 *(v1 + 3), *(v1 + 4), *(v1 + 5), *(v1), *(v1 + 1), *(v1 + 2),
253 *(v2 + 3), *(v2 + 4), *(v2 + 5), *(v2), *(v2 + 1), *(v2 + 2),
254 *(v + 3), *(v + 4), *(v + 5), *(v), *(v + 1), *(v + 2));
255
256 v += 6;
257 c -= 2;
258 }
259 }
260 }
261 fclose(f);
262 if (!quiet) {
263 PRINTFB(I->G, FB_ObjectSurface, FB_Actions)
264 " ObjectSurfaceDump: %s written to %s\n", I->Name, fname ENDFB(I->G);
265 }
266 }
267 }
268
invalidate(int rep,int level,int state)269 void ObjectSurface::invalidate(int rep, int level, int state)
270 {
271 auto I = this;
272 int once_flag = true;
273 if(level >= cRepInvExtents) {
274 I->ExtentFlag = false;
275 }
276 if((rep == cRepSurface) || (rep == cRepMesh) || (rep == cRepAll)) {
277 for(int a = 0; a < I->State.size(); a++) {
278 if(state < 0)
279 once_flag = false;
280 if(!once_flag)
281 state = a;
282 I->State[state].RefreshFlag = true;
283 if(level >= cRepInvRep) {
284 I->State[state].ResurfaceFlag = true;
285 if(I->State[state].shaderCGO){
286 I->State[state].shaderCGO.reset();
287 }
288 SceneChanged(I->G);
289 } else if(level >= cRepInvColor) {
290 I->State[state].RecolorFlag = true;
291 if(I->State[state].shaderCGO){
292 I->State[state].shaderCGO.reset();
293 }
294 SceneChanged(I->G);
295 } else {
296 SceneInvalidate(I->G);
297 }
298 if(once_flag)
299 break;
300 }
301 }
302 }
303
ObjectSurfaceInvalidateMapName(ObjectSurface * I,const char * name,const char * new_name)304 int ObjectSurfaceInvalidateMapName(ObjectSurface * I, const char *name, const char * new_name)
305 {
306 int result = false;
307 for(int a = 0; a < I->State.size(); a++) {
308 auto ms = &I->State[a];
309 if(ms->Active) {
310 if(strcmp(ms->MapName, name) == 0) {
311 if (new_name)
312 strcpy(ms->MapName, new_name);
313 I->invalidate(cRepAll, cRepInvAll, a);
314 result = true;
315 }
316 }
317 }
318 return result;
319 }
320
ObjectSurfaceStateUpdateColors(ObjectSurface * I,ObjectSurfaceState * ms)321 static void ObjectSurfaceStateUpdateColors(ObjectSurface * I, ObjectSurfaceState * ms)
322 {
323 int one_color_flag = true;
324 int cur_color =
325 SettingGet_color(I->G, I->Setting, NULL, cSetting_surface_color);
326
327 if(cur_color == -1)
328 cur_color = I->Color;
329
330 if(ColorCheckRamped(I->G, cur_color))
331 one_color_flag = false;
332
333 ms->OneColor = cur_color;
334 if(ms->V) {
335 int ramped_flag = false;
336 float *v = ms->V.data();
337 float *vc;
338 int *rc;
339 int a;
340 int state = std::distance(I->State.data(), ms);
341 int base_n_vert = ms->base_n_V;
342 switch (ms->Mode) {
343 case 3:
344 case 2:
345 {
346 int n_vert = VLAGetSize(ms->V) / 6;
347 base_n_vert /= 6;
348
349 if(!ms->VC.empty() && (ms->VCsize() < n_vert)) {
350 ms->VC.clear();
351 ms->RC.clear();
352 }
353
354 if(ms->VC.empty()) {
355 ms->VC.resize(n_vert * 3);
356 }
357 if(ms->RC.empty()) {
358 ms->RC.resize(n_vert);
359 }
360 rc = ms->RC.data();
361 vc = ms->VC.data();
362 v += 3;
363 if(vc) {
364 for(a = 0; a < n_vert; a++) {
365 if(a == base_n_vert) {
366 int new_color = SettingGet_color(I->G, I->Setting,
367 NULL, cSetting_surface_negative_color);
368 if(new_color == -1)
369 new_color = cur_color;
370 if(new_color != cur_color) {
371 one_color_flag = false;
372 cur_color = new_color;
373 }
374 }
375 if(ColorCheckRamped(I->G, cur_color)) {
376 ColorGetRamped(I->G, cur_color, v, vc, state);
377 *rc = cur_color;
378 ramped_flag = true;
379 } else {
380 const float *col = ColorGet(I->G, cur_color);
381 copy3f(col, vc);
382 }
383 rc++;
384 vc += 3;
385 v += 6; /* alternates with normals */
386 }
387 }
388 }
389 break;
390 case 1:
391 case 0:
392 default:
393 {
394 int n_vert = VLAGetSize(ms->V) / 3;
395 base_n_vert /= 3;
396 if(!ms->VC.empty() && (ms->VCsize() < n_vert)) {
397 ms->VC.clear();
398 ms->RC.clear();
399 }
400
401 if(ms->VC.empty()) {
402 ms->VC.resize(n_vert * 3);
403 }
404 if(ms->RC.empty()) {
405 ms->RC.resize(n_vert);
406 }
407 rc = ms->RC.data();
408 vc = ms->VC.data();
409 if(vc) {
410 for(a = 0; a < n_vert; a++) {
411 if(a == base_n_vert) {
412 int new_color = SettingGet_color(I->G, I->Setting,
413 NULL, cSetting_surface_negative_color);
414 if(new_color == -1)
415 new_color = cur_color;
416 if(new_color != cur_color)
417 one_color_flag = false;
418 cur_color = new_color;
419 }
420
421 if(ColorCheckRamped(I->G, cur_color)) {
422 ColorGetRamped(I->G, cur_color, v, vc, state);
423 *rc = cur_color;
424 ramped_flag = true;
425 } else {
426 const float *col = ColorGet(I->G, cur_color);
427 copy3f(col, vc);
428 }
429 rc++;
430 vc += 3;
431 v += 3;
432 }
433 }
434 }
435 break;
436 }
437
438 if(one_color_flag && (!ramped_flag)) {
439 ms->VC.clear();
440 ms->RC.clear();
441 } else if((!ramped_flag)
442 ||
443 (!SettingGet_b(I->G, NULL, I->Setting, cSetting_ray_color_ramps))) {
444 ms->RC.clear();
445 }
446 }
447 }
448
update()449 void ObjectSurface::update()
450 {
451 auto I = this;
452 float carve_buffer;
453 for(auto& msref : I->State) {
454 ObjectSurfaceState *ms = &msref;
455 ObjectMapState *oms = NULL;
456 ObjectMap *map = NULL;
457 MapType *voxelmap = NULL; /* this has nothing to do with isosurfaces... */
458
459 if(ms->Active) {
460 map = ExecutiveFindObjectMapByName(I->G, ms->MapName);
461 if(!map) {
462 PRINTFB(I->G, FB_ObjectSurface, FB_Errors)
463 "ObjectSurfaceUpdate-Error: map '%s' has been deleted.\n", ms->MapName
464 ENDFB(I->G);
465 ms->ResurfaceFlag = false;
466 }
467 if(map) {
468 oms = ObjectMapGetState(map, ms->MapState);
469 }
470 if(oms) {
471 if(!oms->Matrix.empty()) {
472 ObjectStateSetMatrix(ms, oms->Matrix.data());
473 } else if(!ms->Matrix.empty()) {
474 ObjectStateResetMatrix(ms);
475 }
476
477 if(I->visRep & cRepCellBit){
478 if (!ms->UnitCellCGO || ms->RefreshFlag || ms->ResurfaceFlag) {
479 ms->Crystal = oms->Symmetry->Crystal;
480 if((I->visRep & cRepCellBit)) {
481 ms->UnitCellCGO.reset(CrystalGetUnitCellCGO(&ms->Crystal));
482 }
483 }
484 ms->RefreshFlag = false;
485 }
486 }
487 if(map && ms && oms && ms->N && ms->V && (I->visRep & cRepSurfaceBit)) {
488 if(ms->ResurfaceFlag) {
489 ms->ResurfaceFlag = false;
490 ms->RecolorFlag = true;
491 if(!ms->quiet) {
492 PRINTFB(I->G, FB_ObjectSurface, FB_Details)
493 " ObjectSurface: updating \"%s\".\n", I->Name ENDFB(I->G);
494 }
495
496 ms->shaderCGO.reset();
497
498 if(oms->Field) {
499
500 {
501 float *min_ext, *max_ext;
502 float tmp_min[3], tmp_max[3];
503 if(MatrixInvTransformExtentsR44d3f(ms->Matrix.data(),
504 ms->ExtentMin, ms->ExtentMax,
505 tmp_min, tmp_max)) {
506 min_ext = tmp_min;
507 max_ext = tmp_max;
508 } else {
509 min_ext = ms->ExtentMin;
510 max_ext = ms->ExtentMax;
511 }
512
513 TetsurfGetRange(I->G, oms->Field.get(), &oms->Symmetry->Crystal,
514 min_ext, max_ext, ms->Range);
515 }
516
517 if(ms->CarveFlag && ms->AtomVertex) {
518 carve_buffer = ms->CarveBuffer;
519 if(carve_buffer < 0.0F) {
520 carve_buffer = -carve_buffer;
521 }
522
523 voxelmap = MapNew(I->G, -carve_buffer, ms->AtomVertex,
524 VLAGetSize(ms->AtomVertex) / 3, NULL);
525 if(voxelmap)
526 MapSetupExpress(voxelmap);
527 }
528
529 ms->nT = TetsurfVolume(I->G, oms->Field.get(),
530 ms->Level,
531 &ms->N, &ms->V,
532 ms->Range,
533 ms->Mode,
534 voxelmap, ms->AtomVertex, ms->CarveBuffer, ms->Side);
535
536 if(!SettingGet_b
537 (I->G, I->Setting, NULL, cSetting_surface_negative_visible)) {
538 ms->base_n_V = VLAGetSize(ms->V);
539 } else {
540 /* do we want the negative surface too? */
541
542 int nT2;
543 int *N2 = VLAlloc(int, 10000);
544 float *V2 = VLAlloc(float, 10000);
545
546 nT2 = TetsurfVolume(I->G, oms->Field.get(),
547 -ms->Level,
548 &N2, &V2,
549 ms->Range,
550 ms->Mode,
551 voxelmap, ms->AtomVertex.data(), ms->CarveBuffer, ms->Side);
552 if(N2 && V2) {
553
554 int base_n_N = VLAGetSize(ms->N);
555 int base_n_V = VLAGetSize(ms->V);
556 int addl_n_N = VLAGetSize(N2);
557 int addl_n_V = VLAGetSize(V2);
558
559 ms->base_n_V = base_n_V;
560
561 /* make room */
562
563 VLASize(ms->N, int, base_n_N + addl_n_N);
564 VLASize(ms->V, float, base_n_V + addl_n_V);
565
566 /* copy vertex data */
567
568 memcpy(((char *) ms->V.data()) + (sizeof(float) * base_n_V),
569 V2, sizeof(float) * addl_n_V);
570
571 /* copy strip counts */
572
573 memcpy(((char *) ms->N.data()) + (sizeof(int) * (base_n_N - 1)),
574 N2, sizeof(int) * addl_n_N);
575 ms->N[base_n_N + addl_n_N - 1] = 0;
576
577 ms->nT += nT2;
578 VLAFreeP(N2);
579 VLAFreeP(V2);
580 }
581 }
582
583 if(voxelmap)
584 MapFree(voxelmap);
585
586 if(!ms->Matrix.empty()) { /* in we're in a different reference frame... */
587 double *matrix = ms->Matrix.data();
588 auto v = ms->V.data();
589 auto n = ms->N.data();
590
591 if(n && v) {
592
593 while(*n) {
594 int c = *(n++);
595 switch (ms->Mode) {
596 case 3:
597 case 2:
598 transform44d3fas33d3f(matrix, v, v);
599 transform44d3f(matrix, v + 3, v + 3);
600 transform44d3fas33d3f(matrix, v + 6, v + 6);
601 transform44d3f(matrix, v + 9, v + 9);
602 v += 12;
603 c -= 4;
604 while(c > 0) {
605 transform44d3fas33d3f(matrix, v, v);
606 transform44d3f(matrix, v + 3, v + 3);
607 v += 6;
608 c -= 2;
609 }
610 break;
611 case 1:
612 transform44d3f(matrix, v, v);
613 c--;
614 v += 3;
615 while(c > 0) {
616 transform44d3f(matrix, v, v);
617 v += 3;
618 c--;
619 }
620 break;
621 case 0:
622 default:
623 while(c > 0) {
624 transform44d3f(matrix, v, v);
625 v += 3;
626 c--;
627 }
628 break;
629 }
630 }
631 }
632 }
633 }
634 }
635 if(ms->RecolorFlag) {
636 ObjectSurfaceStateUpdateColors(I, ms);
637 ms->RecolorFlag = false;
638 }
639 }
640 }
641 }
642 if(!I->ExtentFlag) {
643 ObjectSurfaceRecomputeExtent(I);
644 }
645 SceneInvalidate(I->G);
646 }
647
ObjectSurfaceRenderGlobalTransparency(PyMOLGlobals * G,RenderInfo * info,ObjectSurfaceState * ms,const float * col,float alpha)648 static void ObjectSurfaceRenderGlobalTransparency(PyMOLGlobals * G,
649 RenderInfo * info, ObjectSurfaceState *ms, const float *col, float alpha)
650 {
651 auto v = ms->V.data();
652 auto vc = ms->VC.data();
653 auto n = ms->N.data();
654
655 while(*n) {
656 int parity = 1;
657 int c = *(n++);
658
659 v += 6;
660 if(vc)
661 vc += 3;
662 c -= 2;
663
664 v += 6;
665 if(vc)
666 vc += 3;
667 c -= 2;
668
669 while(c > 0) {
670 if(vc) {
671 CGOAlphaTriangle(info->alpha_cgo,
672 v + (3 - 6), v + (3 - 12), v + 3,
673 v - 6, v - 12, v,
674 vc - 3, vc - 6, vc,
675 alpha, alpha, alpha, parity);
676 } else {
677 CGOAlphaTriangle(info->alpha_cgo,
678 v + (3 - 6), v + (3 - 12), v + 3,
679 v - 6, v - 12, v,
680 col, col, col,
681 alpha, alpha, alpha, parity);
682 }
683 v += 6;
684 if(vc)
685 vc += 3;
686 c -= 2;
687 parity = !parity;
688 }
689 }
690 }
691
ObjectSurfaceRenderUnOptimizedTransparency(ObjectSurfaceState * ms,float alpha)692 static void ObjectSurfaceRenderUnOptimizedTransparency(ObjectSurfaceState *ms, float alpha){
693 auto v = ms->V.data();
694 auto vc = ms->VC.data();
695 auto n = ms->N.data();
696
697 while(*n) {
698 int c = *(n++);
699 CGOBegin(ms->shaderCGO.get(), GL_TRIANGLE_STRIP);
700 while(c > 0) {
701 CGONormalv(ms->shaderCGO.get(), v);
702 v += 3;
703 if(vc) {
704 CGOColorv(ms->shaderCGO.get(), vc);
705 vc += 3;
706 }
707 CGOVertexv(ms->shaderCGO.get(), v);
708 v += 3;
709 c -= 2;
710 }
711 CGOEnd(ms->shaderCGO.get());
712 }
713 }
714
ObjectSurfaceRenderOpaque(PyMOLGlobals * G,ObjectSurface * I,ObjectSurfaceState * ms)715 static void ObjectSurfaceRenderOpaque(PyMOLGlobals * G, ObjectSurface * I, ObjectSurfaceState *ms){
716 auto v = ms->V.data();
717 auto n = ms->N.data();
718 CGOSpecial(ms->shaderCGO.get(), LINEWIDTH_DYNAMIC_MESH);
719 auto vc = ms->VC.data();
720
721 while(*n) {
722 int c = *(n++);
723 switch (ms->Mode) {
724 case 3:
725 case 2:
726 CGOBegin(ms->shaderCGO.get(), GL_TRIANGLE_STRIP);
727 while(c > 0) {
728 CGONormalv(ms->shaderCGO.get(), v);
729 v += 3;
730 if(vc) {
731 CGOColorv(ms->shaderCGO.get(), vc);
732 vc += 3;
733 }
734 CGOVertexv(ms->shaderCGO.get(), v);
735 v += 3;
736 c -= 2;
737 }
738 CGOEnd(ms->shaderCGO.get());
739 break;
740 case 1:
741 CGOBegin(ms->shaderCGO.get(), GL_LINES);
742 while(c > 0) {
743 if(vc) {
744 CGOColorv(ms->shaderCGO.get(), vc);
745 vc += 3;
746 }
747 CGOVertexv(ms->shaderCGO.get(), v);
748 v += 3;
749 c--;
750 }
751 CGOEnd(ms->shaderCGO.get());
752 break;
753 case 0:
754 default:
755 CGOBegin(ms->shaderCGO.get(), GL_POINTS);
756 while(c > 0) {
757 if(vc) {
758 CGOColorv(ms->shaderCGO.get(), vc);
759 vc += 3;
760 }
761 CGOVertexv(ms->shaderCGO.get(), v);
762 v += 3;
763 c--;
764 }
765 CGOEnd(ms->shaderCGO.get());
766 }
767 }
768 }
769
ObjectSurfaceRenderRay(PyMOLGlobals * G,ObjectSurface * I,RenderInfo * info,ObjectSurfaceState * ms)770 static void ObjectSurfaceRenderRay(PyMOLGlobals * G, ObjectSurface *I,
771 RenderInfo * info, ObjectSurfaceState *ms)
772 {
773 float *v = ms->V.data();
774 float *vc = ms->VC.data();
775 int *rc;
776 int c;
777 int* n = ms->N.data();
778 float alpha = 1.0F - SettingGet_f(G, NULL, I->Setting, cSetting_transparency);
779 if(fabs(alpha - 1.0) < R_SMALL4)
780 alpha = 1.0F;
781
782
783 CRay *ray = info->ray;
784 if(ms->UnitCellCGO && (I->visRep & cRepCellBit)){
785 int rayok = CGORenderRay(ms->UnitCellCGO.get(), ray, info, ColorGet(G, I->Color),
786 NULL, I->Setting, NULL);
787 if (!rayok){
788 ms->UnitCellCGO.reset();
789 }
790 }
791
792 ray->transparentf(1.0F - alpha);
793 ms->Radius = SettingGet_f(G, I->Setting, NULL, cSetting_mesh_radius);
794 if(ms->Radius == 0.0F) {
795 ms->Radius = ray->PixelRadius *
796 SettingGet_f(I->G, I->Setting, NULL, cSetting_mesh_width) / 2.0F;
797 }
798
799 if(n && v && (I->visRep & cRepSurfaceBit)) {
800 float cc[3];
801 float colA[3], colB[3], colC[3];
802 ColorGetEncoded(G, ms->OneColor, cc);
803 vc = ms->VC.data();
804
805 rc = ms->RC.data();
806 while(*n) {
807 c = *(n++);
808 switch (ms->Mode) {
809 case 3:
810 case 2:
811 v += 12;
812 if(vc)
813 vc += 6;
814 c -= 4;
815 while(c > 0) {
816 if(vc) {
817 float *cA = vc - 6, *cB = vc - 3, *cC = vc;
818 if(rc) {
819 if(rc[0] < -1)
820 ColorGetEncoded(G, rc[0], (cA = colA));
821 if(rc[1] < -1)
822 ColorGetEncoded(G, rc[1], (cB = colB));
823 if(rc[2] < -1)
824 ColorGetEncoded(G, rc[2], (cC = colC));
825 rc++;
826 }
827 ray->triangle3fv(v - 9, v - 3, v + 3,
828 v - 12, v - 6, v, cA, cB, cC);
829 vc += 3;
830 } else {
831 ray->triangle3fv(v - 9, v - 3, v + 3,
832 v - 12, v - 6, v, cc, cc, cc);
833 }
834 v += 6;
835 c -= 2;
836 }
837 break;
838 case 1:
839 c--;
840 v += 3;
841 if(vc)
842 vc += 3;
843 while(c > 0) {
844 if(vc) {
845 float *cA = vc - 3, *cB = vc;
846 if(rc) {
847 if(rc[0] < -1)
848 ColorGetEncoded(G, rc[0], (cA = colA));
849 if(rc[1] < -1)
850 ColorGetEncoded(G, rc[1], (cB = colB));
851 rc++;
852 }
853 ray->sausage3fv(v - 3, v, ms->Radius, cA, cB);
854 vc += 3;
855 } else
856 ray->sausage3fv(v - 3, v, ms->Radius, cc, cc);
857 v += 3;
858 c--;
859 }
860 break;
861 case 0:
862 default:
863 while(c > 0) {
864 if(vc) {
865 ray->color3fv(vc);
866 vc += 3;
867 }
868 ray->sphere3fv(v, ms->Radius);
869 v += 3;
870 c--;
871 }
872 break;
873 }
874 }
875 }
876 ray->transparentf(0.0);
877 }
878
ObjectSurfaceRenderCell(PyMOLGlobals * G,ObjectSurface * I,RenderInfo * info,ObjectSurfaceState * ms,short use_shader)879 static void ObjectSurfaceRenderCell(PyMOLGlobals *G, ObjectSurface * I,
880 RenderInfo * info, ObjectSurfaceState *ms, short use_shader)
881 {
882 const float *color = ColorGet(G, I->Color);
883 if (use_shader != ms->UnitCellCGO->has_draw_buffers){
884 if (use_shader){
885 CGO *convertcgo = CGOOptimizeToVBONotIndexed(ms->UnitCellCGO.get(), 0);
886 ms->UnitCellCGO.reset(convertcgo);
887 ms->UnitCellCGO->use_shader = true;
888 } else {
889 ms->UnitCellCGO.reset(CrystalGetUnitCellCGO(&ms->Crystal));
890 }
891 }
892 CGORenderGL(ms->UnitCellCGO.get(), color,
893 I->Setting, NULL, info, NULL);
894 }
895
render(RenderInfo * info)896 void ObjectSurface::render(RenderInfo * info)
897 {
898 auto I = this;
899 int state = info->state;
900 CRay *ray = info->ray;
901 auto pick = info->pick;
902 int pass = info->pass;
903 const float *col;
904 ObjectSurfaceState *ms = NULL;
905 float alpha;
906 ObjectPrepareContext(I, info);
907
908 alpha = 1.0F - SettingGet_f(G, NULL, I->Setting, cSetting_transparency);
909 if(fabs(alpha - 1.0) < R_SMALL4)
910 alpha = 1.0F;
911
912 StateIterator iter(G, I->Setting, state, I->State.size());
913 while(iter.next()) {
914 ms = &I->State[iter.state];
915 if(ms && ms->Active && ms->V && ms->N) {
916 if(ray) {
917 ObjectSurfaceRenderRay(G, I, info, ms);
918 } else if(G->HaveGUI && G->ValidContext) {
919 if(!pick) { // no picking for ObjectSurfaces
920 int render_now = false;
921 short use_shader;
922 use_shader = SettingGetGlobal_b(G, cSetting_surface_use_shader) &
923 SettingGetGlobal_b(G, cSetting_use_shaders);
924
925 if(info && info->alpha_cgo) {
926 render_now = (pass == 1);
927 use_shader = false;
928 } else if(alpha < 1.0F) {
929 render_now = (pass == -1);
930 } else {
931 render_now = (pass == 1);
932 }
933
934 if((I->visRep & cRepCellBit) && ms->UnitCellCGO && (pass == 1)){
935 ObjectSurfaceRenderCell(G, I, info, ms, use_shader);
936 }
937
938 if(render_now) {
939 if (ms->shaderCGO && use_shader != ms->shaderCGO->has_draw_buffers){
940 ms->shaderCGO.reset();
941 }
942
943 if (ms->shaderCGO){
944 CGORenderGL(ms->shaderCGO.get(), NULL, NULL, NULL, info, NULL);
945 continue;
946 }
947
948 // Generating CGO
949 ms->shaderCGO.reset(CGONew(G));
950 ms->shaderCGO->use_shader = true;
951
952 CGOResetNormal(ms->shaderCGO.get(), false);
953
954 col = ColorGet(G, ms->OneColor);
955 if((alpha != 1.0)) {
956 CGOAlpha(ms->shaderCGO.get(), alpha);
957 }
958 CGOColorv(ms->shaderCGO.get(), col);
959
960 if(I->visRep & cRepSurfaceBit) {
961 if((ms->Mode > 1) && (alpha != 1.0)) { /* transparent */
962 if(info->alpha_cgo) { /* global transparency */
963 ObjectSurfaceRenderGlobalTransparency(G, info, ms, col, alpha);
964 } else { /* cgo transparency with sorting if needed */
965 ObjectSurfaceRenderUnOptimizedTransparency(ms, alpha);
966 }
967 } else { /* opaque, triangles */
968 ObjectSurfaceRenderOpaque(G, I, ms);
969 }
970 }
971 CGOStop(ms->shaderCGO.get());
972
973 if (use_shader){
974 auto convertcgo = CGOCombineBeginEnd(ms->shaderCGO.get(), 0);
975 ms->shaderCGO.reset(convertcgo);
976 convertcgo = CGOOptimizeToVBOIndexed(ms->shaderCGO.get(), 0, NULL, true, (alpha != 1.0) /* embedTransparency */);
977 if (convertcgo){
978 ms->shaderCGO.reset(convertcgo);
979 }
980 ms->shaderCGO->use_shader = true;
981 CGORenderGL(ms->shaderCGO.get(), NULL, NULL, NULL, info, NULL);
982 } else {
983 if (alpha != 1.0){
984 // use_shader = 0
985 CGO *convertcgo = CGOConvertTrianglesToAlpha(ms->shaderCGO.get());
986 ms->shaderCGO.reset(convertcgo);
987 ms->shaderCGO->render_alpha = 1;
988 }
989 ms->shaderCGO->use_shader = false;
990 CGORenderGL(ms->shaderCGO.get(), NULL, NULL, NULL, info, NULL);
991 }
992 }
993 }
994 }
995 }
996 }
997 }
998
999
1000 /*========================================================================*/
1001
getNFrame() const1002 int ObjectSurface::getNFrame() const
1003 {
1004 return State.size();
1005 }
1006
1007
1008 /*========================================================================*/
ObjectSurface(PyMOLGlobals * G)1009 ObjectSurface::ObjectSurface(PyMOLGlobals* G)
1010 : CObject(G)
1011 {
1012 type = cObjectSurface;
1013 }
1014
1015 /*========================================================================*/
ObjectSurfaceState(PyMOLGlobals * G)1016 ObjectSurfaceState::ObjectSurfaceState(PyMOLGlobals* G)
1017 : CObjectState(G)
1018 , Crystal(G)
1019 , Active(true)
1020 {
1021 V = pymol::vla<float>(10000);
1022 N = pymol::vla<int>(10000);
1023 }
1024
1025 /*========================================================================*/
ObjectSurfaceFromBox(PyMOLGlobals * G,ObjectSurface * obj,ObjectMap * map,int map_state,int state,float * mn,float * mx,float level,int mode,float carve,float * vert_vla,int side,int quiet)1026 ObjectSurface *ObjectSurfaceFromBox(PyMOLGlobals * G, ObjectSurface * obj,
1027 ObjectMap * map, int map_state, int state, float *mn,
1028 float *mx, float level, int mode, float carve,
1029 float *vert_vla, int side, int quiet)
1030 {
1031 ObjectSurface *I;
1032 ObjectSurfaceState *ms;
1033 ObjectMapState *oms;
1034
1035 if(!obj) {
1036 I = new ObjectSurface(G);
1037 } else {
1038 I = obj;
1039 }
1040
1041 if(state < 0)
1042 state = I->State.size();
1043 if(I->State.size() <= state) {
1044 VecCheckEmplace(I->State, state, G);
1045 }
1046
1047 ms = &I->State[state];
1048 *ms = ObjectSurfaceState(G);
1049
1050 strcpy(ms->MapName, map->Name);
1051 ms->MapState = map_state;
1052 oms = ObjectMapGetState(map, map_state);
1053
1054 ms->Level = level;
1055 ms->Mode = mode;
1056 ms->Side = side;
1057 ms->quiet = quiet;
1058 if(oms) {
1059
1060 if(!oms->Matrix.empty()) {
1061 ObjectStateSetMatrix(ms, oms->Matrix.data());
1062 } else if(!ms->Matrix.empty()) {
1063 ObjectStateResetMatrix(ms);
1064 }
1065
1066 copy3f(mn, ms->ExtentMin); /* this is not exactly correct...should actually take vertex points from range */
1067 copy3f(mx, ms->ExtentMax);
1068
1069 {
1070 float *min_ext, *max_ext;
1071 float tmp_min[3], tmp_max[3];
1072 if(MatrixInvTransformExtentsR44d3f(ms->Matrix.data(),
1073 ms->ExtentMin, ms->ExtentMax,
1074 tmp_min, tmp_max)) {
1075 min_ext = tmp_min;
1076 max_ext = tmp_max;
1077 } else {
1078 min_ext = ms->ExtentMin;
1079 max_ext = ms->ExtentMax;
1080 }
1081
1082 TetsurfGetRange(G, oms->Field.get(), &oms->Symmetry->Crystal, min_ext, max_ext, ms->Range);
1083 }
1084 ms->ExtentFlag = true;
1085 }
1086 if(carve != 0.0) {
1087 ms->CarveFlag = true;
1088 ms->CarveBuffer = carve;
1089 ms->AtomVertex = pymol::vla_take_ownership(vert_vla);
1090
1091 double *matrix = ObjectStateGetInvMatrix(ms);
1092
1093 if(matrix) {
1094 int n = VLAGetSize(ms->AtomVertex) / 3;
1095 float *v = ms->AtomVertex.data();
1096 while(n--) {
1097 /* convert back into original map coordinates
1098 for surface carving operation */
1099 transform44d3f(matrix, v, v);
1100 v += 3;
1101 }
1102 }
1103
1104 }
1105 if(I) {
1106 ObjectSurfaceRecomputeExtent(I);
1107 }
1108 I->ExtentFlag = true;
1109 /* printf("Brick %d %d %d %d %d %d\n",I->Range[0],I->Range[1],I->Range[2],I->Range[3],I->Range[4],I->Range[5]); */
1110 SceneChanged(G);
1111 SceneCountFrames(G);
1112 return (I);
1113 }
1114
ObjectSurfaceGetLevel(ObjectSurface * I,int state)1115 pymol::Result<float> ObjectSurfaceGetLevel(ObjectSurface * I, int state)
1116 {
1117 if(state >= I->State.size()) {
1118 return pymol::make_error("Invalid surface state");
1119 } else {
1120 if(state < 0) {
1121 state = 0;
1122 }
1123 auto ms = &I->State[state];
1124 if(ms->Active) {
1125 return ms->Level;
1126 } else {
1127 return pymol::make_error("Invalid Surface state");
1128 }
1129 }
1130 }
1131
ObjectSurfaceSetLevel(ObjectSurface * I,float level,int state,int quiet)1132 int ObjectSurfaceSetLevel(ObjectSurface * I, float level, int state, int quiet)
1133 {
1134 int ok = true;
1135 int once_flag = true;
1136 if(state >= I->State.size()) {
1137 ok = false;
1138 } else {
1139 for(int a = 0; a < I->State.size(); a++) {
1140 if(state < 0) {
1141 once_flag = false;
1142 }
1143 if(!once_flag) {
1144 state = a;
1145 }
1146 auto ms = &I->State[state];
1147 if(ms->Active) {
1148 ms->ResurfaceFlag = true;
1149 ms->RefreshFlag = true;
1150 ms->Level = level;
1151 ms->quiet = quiet;
1152 }
1153 if(once_flag) {
1154 break;
1155 }
1156 }
1157 }
1158 return (ok);
1159 }
1160
1161
1162 /*========================================================================*/
1163
ObjectSurfaceRecomputeExtent(ObjectSurface * I)1164 void ObjectSurfaceRecomputeExtent(ObjectSurface * I)
1165 {
1166 int extent_flag = false;
1167
1168 for(auto& msr : I->State) {
1169 auto ms = &msr;
1170 if(ms->Active) {
1171 if(ms->ExtentFlag) {
1172 if(!extent_flag) {
1173 extent_flag = true;
1174 copy3f(ms->ExtentMax, I->ExtentMax);
1175 copy3f(ms->ExtentMin, I->ExtentMin);
1176 } else {
1177 max3f(ms->ExtentMax, I->ExtentMax, I->ExtentMax);
1178 min3f(ms->ExtentMin, I->ExtentMin, I->ExtentMin);
1179 }
1180 }
1181 }
1182 }
1183 I->ExtentFlag = extent_flag;
1184
1185 if(I->TTTFlag && I->ExtentFlag) {
1186 const float *ttt;
1187 double tttd[16];
1188 if(ObjectGetTTT(I, &ttt, -1)) {
1189 convertTTTfR44d(ttt, tttd);
1190 MatrixTransformExtentsR44d3f(tttd,
1191 I->ExtentMin, I->ExtentMax,
1192 I->ExtentMin, I->ExtentMax);
1193 }
1194 }
1195 }
1196
1197 /*========================================================================*/
1198
clone() const1199 CObject* ObjectSurface::clone() const
1200 {
1201 return new ObjectSurface(*this);
1202 }
1203
1204