Files
pymol-open-source/layer2/GadgetSet.cpp
Jarrett Johnson 74894e01da Generic CGO Render
2022-03-08 15:16:16 -05:00

389 lines
9.9 KiB
C++

/*
A* -------------------------------------------------------------------
B* This file contains source code for the PyMOL computer program
C* copyright 1998-2000 by Warren Lyford Delano of DeLano Scientific.
D* -------------------------------------------------------------------
E* It is unlawful to modify or remove this copyright notice.
F* -------------------------------------------------------------------
G* Please see the accompanying LICENSE file for further information.
H* -------------------------------------------------------------------
I* Additional authors of this source file include:
-*
-*
-*
Z* -------------------------------------------------------------------
*/
#include"os_python.h"
#include"os_predef.h"
#include"os_std.h"
#include"Base.h"
#include"MemoryDebug.h"
#include"Err.h"
#include"Scene.h"
#include"GadgetSet.h"
#include"ObjectGadget.h"
#include"Color.h"
#include"PConv.h"
#include"main.h"
#include"CGO.h"
#include"ShaderMgr.h"
#include"Ray.h"
int GadgetSetGetVertex(const GadgetSet * I, int index, int base, float *v)
{
int ok = true;
float *v0, *v1;
if(index < I->NCoord) {
v0 = I->Coord + 3 * index;
if(base < 0) {
copy3f(v0, v);
if(index){
add3f(I->Coord, v, v);
}
} else if(base < I->NCoord) {
v1 = I->Coord + 3 * base;
add3f(v1, v0, v);
if(index)
add3f(I->Coord, v, v);
} else {
ok = false;
}
} else
ok = false;
return (ok);
}
int GadgetSetSetVertex(GadgetSet * I, int index, int base, const float *v)
{
int ok = true;
float *v0, *v1;
if(index < I->NCoord) {
v0 = I->Coord + 3 * index;
if(base < 0) {
copy3f(v, v0);
if(index){
subtract3f(v0, I->Coord, v0);
} else {
if (I->offsetPtOP)
copy3f(v0, &I->StdCGO->op[I->offsetPtOP]);
if (I->offsetPtOPick)
copy3f(v0, &I->PickCGO->op[I->offsetPtOPick]);
}
} else if(base < I->NCoord) {
v1 = I->Coord + 3 * base;
subtract3f(v, v1, v0);
if(index)
subtract3f(v0, I->Coord, v0);
} else {
ok = false;
}
} else
ok = false;
return (ok);
}
int GadgetSetFromPyList(PyMOLGlobals * G, PyObject * list, GadgetSet ** gs, int version)
{
int ok = true;
GadgetSet *I = NULL;
PyObject *tmp = NULL;
if(*gs) {
delete *gs;
*gs = NULL;
}
if(list == Py_None) { /* allow None for GSet */
*gs = NULL;
} else {
if(ok)
I = GadgetSetNew(G);
if(ok)
ok = (I != NULL);
if(ok)
ok = (list != NULL);
if(ok)
ok = PyList_Check(list);
/* TO SUPPORT BACKWARDS COMPATIBILITY...
Always check ll when adding new PyList_GetItem's */
if(ok)
ok = PConvPyIntToInt(PyList_GetItem(list, 0), &I->NCoord);
if(ok && I->NCoord)
ok = PConvPyListToFloatVLA(PyList_GetItem(list, 1), &I->Coord);
if(ok)
ok = PConvPyIntToInt(PyList_GetItem(list, 2), &I->NNormal);
if(ok && I->NNormal)
ok = PConvPyListToFloatVLA(PyList_GetItem(list, 3), &I->Normal);
if(ok)
ok = PConvPyIntToInt(PyList_GetItem(list, 4), &I->NColor);
if(ok && I->NColor)
ok = PConvPyListToFloatVLA(PyList_GetItem(list, 5), &I->Color);
if(ok)
ok = ((tmp = PyList_GetItem(list, 6)) != NULL);
if(ok && (tmp != Py_None))
ok = ((I->ShapeCGO = CGONewFromPyList(I->G, tmp, version)) != NULL);
if(ok)
ok = ((tmp = PyList_GetItem(list, 7)) != NULL);
if(ok && (tmp != Py_None))
ok = ((I->PickShapeCGO = CGONewFromPyList(I->G, tmp, version)) != NULL);
if(ok && I->ShapeCGO)
if(CGOCheckForText(I->ShapeCGO)) {
CGOPreloadFonts(I->ShapeCGO);
}
if(!ok) {
if(I)
delete I;
} else {
*gs = I;
}
}
return (ok);
}
PyObject *GadgetSetAsPyList(GadgetSet * I, bool incl_cgos)
{
PyObject *result = NULL;
if(I) {
result = PyList_New(8);
PyList_SetItem(result, 0, PyInt_FromLong(I->NCoord));
if(I->NCoord) {
PyList_SetItem(result, 1, PConvFloatArrayToPyList(I->Coord, I->NCoord * 3));
} else {
PyList_SetItem(result, 1, PConvAutoNone(NULL));
}
PyList_SetItem(result, 2, PyInt_FromLong(I->NNormal));
if(I->NNormal) {
PyList_SetItem(result, 3, PConvFloatArrayToPyList(I->Normal, I->NNormal * 3));
} else {
PyList_SetItem(result, 3, PConvAutoNone(NULL));
}
PyList_SetItem(result, 4, PyInt_FromLong(I->NColor));
if(I->NColor) {
PyList_SetItem(result, 5, PConvFloatArrayToPyList(I->Color, I->NColor));
} else {
PyList_SetItem(result, 5, PConvAutoNone(NULL));
}
if(incl_cgos && I->ShapeCGO) {
PyList_SetItem(result, 6, CGOAsPyList(I->ShapeCGO));
} else {
PyList_SetItem(result, 6, PConvAutoNone(NULL));
}
if(incl_cgos && I->PickShapeCGO) {
PyList_SetItem(result, 7, CGOAsPyList(I->PickShapeCGO));
} else {
PyList_SetItem(result, 7, PConvAutoNone(NULL));
}
}
return (PConvAutoNone(result));
}
/*========================================================================*/
int GadgetSetGetExtent(GadgetSet * I, float *mn, float *mx)
{
float *v;
int a;
v = I->Coord;
for(a = 0; a < I->NCoord; a++) {
min3f(v, mn, mn);
max3f(v, mx, mx);
v += 3;
}
return (I->NCoord);
}
/*========================================================================*/
void GadgetSet::invalidateRep(cRep_t type, cRepInv_t level)
{
}
/*========================================================================*/
void GadgetSet::update()
{
GadgetSet * I = this;
if(I->StdCGO) {
CGOFree(I->StdCGO);
I->offsetPtOP = 0;
I->StdCGO = NULL;
}
if(I->PickCGO) {
CGOFree(I->PickCGO);
I->offsetPtOPick = 0;
I->PickCGO = NULL;
}
}
/*========================================================================*/
void GadgetSet::render(RenderInfo * info)
{
GadgetSet * I = this;
const RenderPass pass = info->pass;
CRay *ray = info->ray;
auto pick = info->pick;
const float *color;
PickContext context;
context.object = I->Obj;
context.state = I->State;
color = ColorGet(I->G, I->Obj->Color);
if(pass == RenderPass::Transparent || ray || pick) {
PyMOLGlobals *G = I->G;
if(ray) {
if(I->ShapeCGO){
float mat[16] = { 1.f, 0.f, 0.f, I->Coord[0],
0.f, 1.f, 0.f, I->Coord[1],
0.f, 0.f, 1.f, I->Coord[2],
0.f, 0.f, 0.f, 1.f };
RayPushTTT(ray);
RaySetTTT(ray, true, mat); /* Used to set the ray-tracing matrix,
this works, but is there another way to do this? */
CGORenderRay(I->ShapeCGO, ray, info, color, NULL, I->Obj->Setting.get(), NULL);
RayPopTTT(ray);
}
} else if(G->HaveGUI && G->ValidContext) {
short use_shader = (short) SettingGetGlobal_b(I->G, cSetting_use_shaders);
if(pick) {
if (!I->PickCGO && I->PickShapeCGO){
CGO *convertcgo;
int ok = true;
convertcgo = CGOCombineBeginEnd(I->PickShapeCGO, 0);
CHECKOK(ok, convertcgo);
if (ok){
if (use_shader){
CGO *tmpCGO;
tmpCGO = CGOOptimizeToVBOIndexedNoShader(convertcgo, 0);
I->PickCGO = CGONew(G);
CGODisable(I->PickCGO, GL_DEPTH_TEST);
CGOEnable(I->PickCGO, GL_RAMP_SHADER);
I->offsetPtOPick = CGOUniform3f(I->PickCGO, RAMP_OFFSETPT, (const float*)I->Coord);
CGOAppendNoStop(I->PickCGO, tmpCGO);
CGOFreeWithoutVBOs(tmpCGO);
CGODisable(I->PickCGO, GL_RAMP_SHADER);
CGOEnable(I->PickCGO, GL_DEPTH_TEST);
CGOStop(I->PickCGO);
I->PickCGO->use_shader = true;
CGOFree(convertcgo);
} else {
I->PickCGO = convertcgo;
}
} else {
CGOFree(convertcgo);
}
}
if(I->PickCGO) {
if (use_shader){
CGORenderPicking(I->PickCGO, info, &context, I->Obj->Setting.get(), NULL);
#ifndef PURE_OPENGL_ES_2
} else {
glDisable(GL_DEPTH_TEST);
glTranslatef(I->Coord[0],I->Coord[1],I->Coord[2]);
CGORenderPicking(I->PickShapeCGO, info, &context, I->Obj->Setting.get(), NULL);
glTranslatef(-I->Coord[0],-I->Coord[1],-I->Coord[2]);
glEnable(GL_DEPTH_TEST);
#endif
}
}
} else {
if (!I->StdCGO && I->ShapeCGO){
if (!use_shader) {
I->StdCGO = CGOCombineBeginEnd(I->ShapeCGO);
assert(!I->StdCGO->has_begin_end);
} else {
I->StdCGO = CGONew(G);
CGODisable(I->StdCGO, GL_DEPTH_TEST);
CGOEnable(I->StdCGO, GL_RAMP_SHADER);
I->offsetPtOP = CGOUniform3f(I->StdCGO, RAMP_OFFSETPT, I->Coord);
I->StdCGO->free_append(
CGOOptimizeToVBONotIndexedNoShader(I->ShapeCGO));
CGODisable(I->StdCGO, GL_RAMP_SHADER);
CGOEnable(I->StdCGO, GL_DEPTH_TEST);
CGOStop(I->StdCGO);
assert(I->StdCGO->use_shader);
assert(!I->StdCGO->has_begin_end);
}
}
if(I->StdCGO) {
if (use_shader){
if (color)
CGORender(I->StdCGO, NULL, I->Obj->Setting.get(), NULL, info, NULL);
#ifndef PURE_OPENGL_ES_2
} else {
glDisable(GL_DEPTH_TEST);
glTranslatef(I->Coord[0],I->Coord[1],I->Coord[2]);
CGORender(I->ShapeCGO, NULL, I->Obj->Setting.get(), NULL, info, NULL);
glTranslatef(-I->Coord[0],-I->Coord[1],-I->Coord[2]);
glEnable(GL_DEPTH_TEST);
#endif
}
}
}
}
}
}
/*========================================================================*/
GadgetSet *GadgetSetNew(PyMOLGlobals * G)
{
auto I = new GadgetSet();
I->G = G;
return (I);
}
/*========================================================================*/
GadgetSet::~GadgetSet()
{
GadgetSet * I = this;
if(I) {
CGOFree(I->PickCGO);
CGOFree(I->PickShapeCGO);
CGOFree(I->StdCGO);
CGOFree(I->ShapeCGO);
VLAFreeP(I->Coord);
VLAFreeP(I->Normal);
VLAFreeP(I->Color);
}
}
/**
* Retrieve coordinate buffer of Gadget set
* @param I target Gadget set
*/
std::vector<float> GadgetSetGetCoord(const GadgetSet* I)
{
std::vector<float> result;
result.resize(VLAGetSize(I->Coord));
std::copy_n(I->Coord, result.size(), result.data());
return result;
}