void Branch::spawnSubBranches(const int level, const double length, const double thickness) { if (level == recursiveDepth) return; // Spawn subbranches (make more as we get smaller) int numBranches = rand(0.2, 0.8, (level == 0 ? 2 : level) * initialBranches); for (int i = 0; i < numBranches; i++) { add_child(new Branch("SubBranch", level + 1, nextThickness(thickness, level), nextLength(length, level))); totalBranches++; } // Tree branches seem to split in two at the ends so simulate that. add_child(new Branch("SplitBranch", level + 1, nextThickness(thickness, level), nextLength(length, level), length, -30.0, 0.0)); add_child(new Branch("SplitBranch", level + 1, nextThickness(thickness, level), nextLength(length, level), length, 30.0, 0.0)); // Two branches coming out of the top looks a little weird so add a sphere. Sphere* p_sphere = new Sphere(); GeometryNode* sphere = new GeometryNode("BranchTop", p_sphere); sphere->set_material(&wood); sphere->translate(Vector3D(0.0, 0.0, length)); sphere->scale(Vector3D(thickness, thickness, thickness)); add_child(sphere); totalBranches += 3; }
void SceneGraph::recomputeBoundingBox() { Node *node; float center[3]; float size[3]; BoundingBox bbox; for (node=getNodes(); node; node=node->nextTraversal()) { if (node->isGroupingNode()) { GroupingNode *gnode = (GroupingNode *)node; gnode->getBoundingBoxCenter(center); gnode->getBoundingBoxSize(size); bbox.addBoundingBox(center, size); } else if (node->isGeometryNode()) { GeometryNode *gnode = (GeometryNode *)node; gnode->getBoundingBoxCenter(center); gnode->getBoundingBoxSize(size); bbox.addBoundingBox(center, size); } } setBoundingBox(&bbox); }
void GBufferPass::update_ubershader_from_scene(SerializedScene const& scene, SceneGraph const& graph) { bool ubershader_available = true; for (auto const& geometry_pair : scene.geometrynodes_) { ubershader_available = ubershader_available && ubershaders_.count(geometry_pair.first); } if (!ubershader_available) { auto get_ubershader = [&](Node * n) { GeometryNode* geode = dynamic_cast<GeometryNode*>(n); if (geode) { std::type_index type(typeid(*geode)); if (!ubershaders_.count(type)) { auto const& ressource = GeometryDatabase::instance()->lookup(geode->get_filename()); if (ressource) { auto ubershader = ressource->get_ubershader(); ubershader->create(materials_); ubershaders_[type] = ubershader; } } } } ; gua::dfs_traverse(graph.get_root().get(), get_ubershader); } }
void BallAndStick::process(const Molecule &molecule, Rendering::GroupNode &node) { // Add a sphere node to contain all of the spheres. GeometryNode *geometry = new GeometryNode; node.addChild(geometry); SphereGeometry *spheres = new SphereGeometry; spheres->identifier().molecule = &molecule; spheres->identifier().type = Rendering::AtomType; geometry->addDrawable(spheres); for (Index i = 0; i < molecule.atomCount(); ++i) { Core::Atom atom = molecule.atom(i); unsigned char atomicNumber = atom.atomicNumber(); const unsigned char *c = Elements::color(atomicNumber); Vector3ub color(c[0], c[1], c[2]); spheres->addSphere(atom.position3d().cast<float>(), color, static_cast<float>(Elements::radiusVDW(atomicNumber)) * 0.3f); } float bondRadius = 0.1f; CylinderGeometry *cylinders = new CylinderGeometry; cylinders->identifier().molecule = &molecule; cylinders->identifier().type = Rendering::BondType; geometry->addDrawable(cylinders); for (Index i = 0; i < molecule.bondCount(); ++i) { Core::Bond bond = molecule.bond(i); Vector3f pos1 = bond.atom1().position3d().cast<float>(); Vector3f pos2 = bond.atom2().position3d().cast<float>(); Vector3ub color1(Elements::color(bond.atom1().atomicNumber())); Vector3ub color2(Elements::color(bond.atom2().atomicNumber())); Vector3f bondVector = pos2 - pos1; float bondLength = bondVector.norm(); bondVector /= bondLength; switch (bond.order()) { case 3: { Vector3f delta = bondVector.unitOrthogonal() * (2.0f * bondRadius); cylinders->addCylinder(pos1 + delta, bondVector, bondLength, bondRadius, color1, color2, i); cylinders->addCylinder(pos1 - delta, bondVector, bondLength, bondRadius, color1, color2, i); } default: case 1: cylinders->addCylinder(pos1, bondVector, bondLength, bondRadius, color1, color2, i); break; case 2: { Vector3f delta = bondVector.unitOrthogonal() * bondRadius; cylinders->addCylinder(pos1 + delta, bondVector, bondLength, bondRadius, color1, color2, i); cylinders->addCylinder(pos1 - delta, bondVector, bondLength, bondRadius, color1, color2, i); } } } }
// ---|> NodeVisitor NodeVisitor::status enter(Node * node) override { GeometryNode * geometry = dynamic_cast<GeometryNode*>(node); if (geometry != nullptr) { currentTriangleCount += geometry->getTriangleCount(); ++currentNodeCount; } if (currentTriangleCount > maxTriangleCount || currentNodeCount > maxNodeCount) { return BREAK_TRAVERSAL; } return CONTINUE_TRAVERSAL; }
void Branch::createGeometryNode(const double length, const double thickness, const double upDist, const double upAngle, const double zAngle) { Cylinder* c_branch= new Cylinder; GeometryNode* branch = new GeometryNode("TreeTrunk", c_branch); branch->set_material(&wood); this->rotate('z', zAngle); this->translate(Vector3D(0.0, 0.0, upDist)); this->rotate('y', upAngle); branch->scale(Vector3D(thickness, thickness, length)); add_child(branch); }
int gr_node_set_bump_cmd(lua_State* L) { GRLUA_DEBUG_CALL; gr_node_ud* selfdata = (gr_node_ud*)luaL_checkudata(L, 1, "gr.node"); luaL_argcheck(L, selfdata != 0, 1, "Node expected"); GeometryNode* self = dynamic_cast<GeometryNode*>(selfdata->node); luaL_argcheck(L, self != 0, 1, "Geometry node expected"); const char* filename = luaL_checkstring(L, 2); self->set_bump(filename); return 0; }
//Render meshes as they are traversed in the scene graph void NMS_SceneRenderer::sg_before(Matrix transform, SceneGraphNode * node) { GeometryNode * geomNode = (GeometryNode *) node; NMS_Mesh* model = geomNode->getModel(); btRigidBody *b = geomNode->getCollisionBody(); glLoadIdentity(); Matrix t_transposed = ~transform; glMultMatrixf(t_transposed.getElements()); if(b != NULL) applyPhysics(b); setWireframeModeGL(wireframe); (*model).setMaterialGL(); (*model).render(currentTime); }
int gr_node_set_texture_scale_cmd(lua_State* L) { GRLUA_DEBUG_CALL; gr_node_ud* selfdata = (gr_node_ud*)luaL_checkudata(L, 1, "gr.node"); luaL_argcheck(L, selfdata != 0, 1, "Node expected"); GeometryNode* self = dynamic_cast<GeometryNode*>(selfdata->node); luaL_argcheck(L, self != 0, 1, "Geometry node expected"); int scale_x = luaL_checknumber(L, 2); int scale_y = luaL_checknumber(L, 3); self->set_texture_scale(scale_x, scale_y); return 0; }
Leaf::Leaf(const std::string& name, const double branchThickness, const double branchLength) : SceneNode(name) { ImagePrimitive* i_leaf = new ImagePrimitive(); GeometryNode* leaf = new GeometryNode("Leaf", i_leaf); leaf->set_material(&leafTexture); double upDist = rand(1.0/3.0, 1.0, branchLength); double zAngle = rand(0.0, 1.0, 360.0); double diagonalDist = branchThickness + sqrt(2.0) - 0.25; double xyDist = -diagonalDist * sqrt(2.0) / 2.0; leaf->rotate('z', zAngle); leaf->translate(Vector3D(xyDist, xyDist, upDist)); add_child(leaf); }
int gr_node_set_refractionIndex_cmd(lua_State* L) { GRLUA_DEBUG_CALL; gr_node_ud* selfdata = (gr_node_ud*)luaL_checkudata(L, 1, "gr.node"); luaL_argcheck(L, selfdata != 0, 1, "Node expected"); GeometryNode* self = dynamic_cast<GeometryNode*>(selfdata->node); luaL_argcheck(L, self != 0, 1, "Geometry node expected"); double index = luaL_checknumber(L, 2); PhongMaterial * pM = (PhongMaterial*)self->get_material(); if (pM == NULL) { std::cerr << "LUA:You are using a non-phong Material!" << std::endl; return 0; } pM->setRefractiveIndex(index); return 0; }
void VanDerWaals::process(const Core::Molecule &molecule, Rendering::GroupNode &node) { // Add a sphere node to contain all of the VdW spheres. GeometryNode *geometry = new GeometryNode; node.addChild(geometry); SphereGeometry *spheres = new SphereGeometry; spheres->identifier().molecule = &molecule; spheres->identifier().type = Rendering::AtomType; geometry->addDrawable(spheres); for (size_t i = 0; i < molecule.atomCount(); ++i) { Core::Atom atom = molecule.atom(i); unsigned char atomicNumber = atom.atomicNumber(); const unsigned char *c = Elements::color(atomicNumber); Vector3ub color(c[0], c[1], c[2]); spheres->addSphere(atom.position3d().cast<float>(), color, static_cast<float>(Elements::radiusVDW(atomicNumber))); } }
int gr_node_set_material_cmd(lua_State* L) { GRLUA_DEBUG_CALL; gr_node_ud* selfdata = (gr_node_ud*)luaL_checkudata(L, 1, "gr.node"); luaL_argcheck(L, selfdata != 0, 1, "Node expected"); GeometryNode* self = dynamic_cast<GeometryNode*>(selfdata->node); luaL_argcheck(L, self != 0, 1, "Geometry node expected"); gr_material_ud* matdata = (gr_material_ud*)luaL_checkudata(L, 2, "gr.material"); luaL_argcheck(L, matdata != 0, 2, "Material expected"); Material* material = matdata->material; self->set_material(material); return 0; }
int gr_node_set_km_cmd(lua_State* L) { GRLUA_DEBUG_CALL; gr_node_ud* selfdata = (gr_node_ud*)luaL_checkudata(L, 1, "gr.node"); luaL_argcheck(L, selfdata != 0, 1, "Node expected"); GeometryNode* self = dynamic_cast<GeometryNode*>(selfdata->node); luaL_argcheck(L, self != 0, 1, "Geometry node expected"); double km[3]; for (int i = 0; i < 3; i++) { km[i] = luaL_checknumber(L, i + 2); } PhongMaterial * pM = (PhongMaterial*)self->get_material(); if (pM == NULL) { std::cerr << "LUA:You are using a non-phong Material!" << std::endl; return 0; } pM->setKM(Colour(km[0], km[1], km[2])); return 0; }
int gr_node_set_bump_cmd(lua_State* L) { GRLUA_DEBUG_CALL; gr_node_ud* selfdata = (gr_node_ud*)luaL_checkudata(L, 1, "gr.node"); luaL_argcheck(L, selfdata != 0, 1, "Node expected"); GeometryNode* self = dynamic_cast<GeometryNode*>(selfdata->node); luaL_argcheck(L, self != 0, 1, "Geometry node expected"); const char* name = luaL_checkstring(L, 2); Image * bump = new Image(); if (!bump->loadPng(name)) { std::cerr << "LUA:Loading PNG Failed!!" << std::endl; return -1; } self->apply_bump(bump); return 0; }
int glwidgettest(int argc, char* argv[]) { // Set up the default format for our GL contexts. QSurfaceFormat defaultFormat = QSurfaceFormat::defaultFormat(); defaultFormat.setSamples(4); QSurfaceFormat::setDefaultFormat(defaultFormat); QApplication app(argc, argv); GLWidget widget; widget.setGeometry(10, 10, 250, 250); widget.show(); GeometryNode* geometry = new GeometryNode; SphereGeometry* spheres = new SphereGeometry; geometry->addDrawable(spheres); spheres->addSphere(Vector3f(0, 0, 0), Vector3ub(255, 0, 0), 0.5); spheres->addSphere(Vector3f(2, 0, 0), Vector3ub(0, 255, 0), 1.5); spheres->addSphere(Vector3f(0, 2, 1), Vector3ub(0, 0, 255), 1.0); widget.renderer().scene().rootNode().addChild(geometry); // Make sure the widget renders the scene, and store it in a QImage. widget.raise(); widget.repaint(); // Run the application for a while, and then quit so we can save an image. QTimer timer; timer.setSingleShot(true); app.connect(&timer, SIGNAL(timeout()), SLOT(quit())); timer.start(200); app.exec(); // Grab the frame buffer of the GLWidget and save it to a QImage. QImage image = widget.grabFramebuffer(); // Set up the image regression test. ImageRegressionTest test(argc, argv); // Do the image threshold test, printing output to the std::cout for ctest. return test.imageThresholdTest(image, std::cout); }
static void describeGeometryNode(ExporterContext & /*ctxt*/,DescriptionMap & desc, Node * node) { desc.setString(Consts::ATTR_NODE_TYPE, Consts::NODE_TYPE_GEOMETRY); std::unique_ptr<DescriptionMap> dataDesc(new DescriptionMap); GeometryNode * gn = dynamic_cast<GeometryNode*>(node); // annotate with bounding box const Geometry::Box bb = gn->getBB(); const Geometry::Vec3 center = bb.getCenter(); std::stringstream s; s << center.getX() << " " << center.getY() << " " << center.getZ() << " " << bb.getExtentX() << " " << bb.getExtentY() << " " << bb.getExtentZ(); dataDesc->setString(Consts::ATTR_MESH_BB, s.str()); Rendering::Mesh * m = gn->getMesh(); if(m!=nullptr) { // mesh present? // no filename -> store data in .minsg if(m->getFileName().empty()) { std::ostringstream meshStream; if(Rendering::Serialization::saveMesh(gn->getMesh(), "mmf", meshStream)) { dataDesc->setString(Consts::ATTR_DATA_TYPE,"mesh"); dataDesc->setString(Consts::ATTR_DATA_ENCODING,"base64"); const std::string streamString = meshStream.str(); const std::string meshString = Util::encodeBase64(std::vector<uint8_t>(streamString.begin(), streamString.end())); dataDesc->setString(Consts::DATA_BLOCK,meshString); } } else { // filename given? Util::FileName meshFilename(m->getFileName()); // // make path to mesh relative to scene (if mesh lies below the scene) // Util::FileUtils::makeRelativeIfPossible(ctxt.sceneFile, meshFilename); dataDesc->setString(Consts::ATTR_DATA_TYPE,"mesh"); dataDesc->setString(Consts::ATTR_MESH_FILENAME,meshFilename.toShortString()); } ExporterTools::addDataEntry(desc, std::move(dataDesc)); } }
void QTAIMEngine::process(const Core::Molecule &coreMolecule, Rendering::GroupNode &node) { const QtGui::Molecule *molecule = dynamic_cast<const QtGui::Molecule*>(&coreMolecule); if (!molecule) return; // Create sphere/cylinder nodes. GeometryNode *geometry = new GeometryNode; node.addChild(geometry); SphereGeometry *spheres = new SphereGeometry; geometry->addDrawable(spheres); CylinderGeometry *cylinders = new CylinderGeometry; geometry->addDrawable(cylinders); // Render the bond paths if( molecule->property("QTAIMFirstNCPIndexVariantList").isValid() && molecule->property("QTAIMSecondNCPIndexVariantList").isValid() && molecule->property("QTAIMLaplacianAtBondCriticalPoints").isValid() && molecule->property("QTAIMEllipticityAtBondCriticalPoints").isValid() && molecule->property("QTAIMBondPathSegmentStartIndex").isValid() && molecule->property("QTAIMBondPathSegmentEndIndex").isValid() && molecule->property("QTAIMXBondPaths").isValid() && molecule->property("QTAIMYBondPaths").isValid() && molecule->property("QTAIMZBondPaths").isValid() ) { QVariant firstNCPIndexVariant=molecule->property("QTAIMFirstNCPIndexVariantList"); QVariant secondNCPIndexVariant=molecule->property("QTAIMSecondNCPIndexVariantList"); QVariant laplacianAtBondCriticalPointsVariant=molecule->property("QTAIMLaplacianAtBondCriticalPoints"); QVariant ellipticityAtBondCriticalPointsVariant=molecule->property("QTAIMEllipticityAtBondCriticalPoints"); QVariant bondPathSegmentStartIndexVariant=molecule->property("QTAIMBondPathSegmentStartIndex"); QVariant bondPathSegmentEndIndexVariant=molecule->property("QTAIMBondPathSegmentEndIndex"); QVariant xBondPathsVariant=molecule->property("QTAIMXBondPaths"); QVariant yBondPathsVariant=molecule->property("QTAIMYBondPaths"); QVariant zBondPathsVariant=molecule->property("QTAIMZBondPaths"); QVariantList firstNCPIndexVariantList=firstNCPIndexVariant.toList(); QVariantList secondNCPIndexVariantList=secondNCPIndexVariant.toList(); QVariantList laplacianAtBondCriticalPointsVariantList=laplacianAtBondCriticalPointsVariant.toList(); QVariantList ellipticityAtBondCriticalPointsVariantList=ellipticityAtBondCriticalPointsVariant.toList(); QVariantList bondPathSegmentStartIndexVariantList=bondPathSegmentStartIndexVariant.toList(); QVariantList bondPathSegmentEndIndexVariantList=bondPathSegmentEndIndexVariant.toList(); QVariantList xBondPathsVariantList=xBondPathsVariant.toList(); QVariantList yBondPathsVariantList=yBondPathsVariant.toList(); QVariantList zBondPathsVariantList=zBondPathsVariant.toList(); for( qint64 i=0 ; i < firstNCPIndexVariantList.length() ; ++i ) { qint64 start=bondPathSegmentStartIndexVariantList.at(i).toLongLong(); qint64 end=bondPathSegmentEndIndexVariantList.at(i).toLongLong(); if( laplacianAtBondCriticalPointsVariantList.at(i).toReal() > 0.0 ) { const qint64 step=4; Vector3f xyz; Vector3ub color(255, 255, 255); for( qint64 j=start ; j < end-1 ; j=j+step ) { xyz << xBondPathsVariantList.at(j).toFloat(), yBondPathsVariantList.at(j).toFloat(), zBondPathsVariantList.at(j).toFloat(); spheres->addSphere(xyz, color, 0.025f); } } else { const qint64 step=1; Vector3ub color(255, 255, 255); double radius=0.025; Vector3f v1; Vector3f v2; Vector3f direction; for( qint64 j=start ; j < end-1 ; j=j+step ) { v1 << xBondPathsVariantList.at(j).toFloat(), yBondPathsVariantList.at(j).toFloat(), zBondPathsVariantList.at(j).toFloat(); v2 << xBondPathsVariantList.at(j+1).toFloat(), yBondPathsVariantList.at(j+1).toFloat(), zBondPathsVariantList.at(j+1).toFloat(); direction = v2 - v1; float length = direction.norm(); direction /= length; cylinders->addCylinder(v1, direction, length, radius, color); } } } // bond path } if( molecule->property("QTAIMXNuclearCriticalPoints").isValid() && molecule->property("QTAIMYNuclearCriticalPoints").isValid() && molecule->property("QTAIMZNuclearCriticalPoints").isValid() ) { QVariant xNuclearCriticalPointsVariant=molecule->property("QTAIMXNuclearCriticalPoints"); QVariant yNuclearCriticalPointsVariant=molecule->property("QTAIMYNuclearCriticalPoints"); QVariant zNuclearCriticalPointsVariant=molecule->property("QTAIMZNuclearCriticalPoints"); QVariantList xNuclearCriticalPointsVariantList=xNuclearCriticalPointsVariant.toList(); QVariantList yNuclearCriticalPointsVariantList=yNuclearCriticalPointsVariant.toList(); QVariantList zNuclearCriticalPointsVariantList=zNuclearCriticalPointsVariant.toList(); if( xNuclearCriticalPointsVariantList.length() == yNuclearCriticalPointsVariantList.length() && xNuclearCriticalPointsVariantList.length() == zNuclearCriticalPointsVariantList.length() ) { Vector3f xyz; Vector3ub color(255, 64, 255); for( qint64 i=0 ; i < xNuclearCriticalPointsVariantList.length() ; ++i ) { xyz << xNuclearCriticalPointsVariantList.at(i).toFloat(), yNuclearCriticalPointsVariantList.at(i).toFloat(), zNuclearCriticalPointsVariantList.at(i).toFloat(); // map->setFromPrimitive(ncp); spheres->addSphere(xyz, color, 0.1f); } } } if( molecule->property("QTAIMXBondCriticalPoints").isValid() && molecule->property("QTAIMYBondCriticalPoints").isValid() && molecule->property("QTAIMZBondCriticalPoints").isValid() ) { QVariant xBondCriticalPointsVariant=molecule->property("QTAIMXBondCriticalPoints"); QVariant yBondCriticalPointsVariant=molecule->property("QTAIMYBondCriticalPoints"); QVariant zBondCriticalPointsVariant=molecule->property("QTAIMZBondCriticalPoints"); QVariantList xBondCriticalPointsVariantList=xBondCriticalPointsVariant.toList(); QVariantList yBondCriticalPointsVariantList=yBondCriticalPointsVariant.toList(); QVariantList zBondCriticalPointsVariantList=zBondCriticalPointsVariant.toList(); if( xBondCriticalPointsVariantList.length() == yBondCriticalPointsVariantList.length() && xBondCriticalPointsVariantList.length() == zBondCriticalPointsVariantList.length() ) { Vector3ub color(255, 255, 32); Vector3f xyz; for( qint64 i=0 ; i < xBondCriticalPointsVariantList.length() ; ++i ) { xyz << xBondCriticalPointsVariantList.at(i).toFloat(), yBondCriticalPointsVariantList.at(i).toFloat(), zBondCriticalPointsVariantList.at(i).toFloat(); // map->setFromPrimitive(ncp); spheres->addSphere(xyz, color, 0.1f); } } } if( molecule->property("QTAIMXElectronDensitySources").isValid() && molecule->property("QTAIMYElectronDensitySources").isValid() && molecule->property("QTAIMZElectronDensitySources").isValid() ) { QVariant xElectronDensitySourcesVariant=molecule->property("QTAIMXElectronDensitySources"); QVariant yElectronDensitySourcesVariant=molecule->property("QTAIMYElectronDensitySources"); QVariant zElectronDensitySourcesVariant=molecule->property("QTAIMZElectronDensitySources"); QVariantList xElectronDensitySourcesVariantList=xElectronDensitySourcesVariant.toList(); QVariantList yElectronDensitySourcesVariantList=yElectronDensitySourcesVariant.toList(); QVariantList zElectronDensitySourcesVariantList=zElectronDensitySourcesVariant.toList(); if( xElectronDensitySourcesVariantList.length() == yElectronDensitySourcesVariantList.length() && xElectronDensitySourcesVariantList.length() == zElectronDensitySourcesVariantList.length() ) { Vector3ub color(64, 64, 255); Vector3f xyz; for( qint64 i=0 ; i < xElectronDensitySourcesVariantList.length() ; ++i ) { xyz << xElectronDensitySourcesVariantList.at(i).toFloat(), yElectronDensitySourcesVariantList.at(i).toFloat(), zElectronDensitySourcesVariantList.at(i).toFloat(); // map->setFromPrimitive(ncp); spheres->addSphere(xyz, color, 0.1f); } } } }
int qttextlabeltest(int argc, char *argv[]) { // Set up the default format for our GL contexts. QGLFormat defaultFormat = QGLFormat::defaultFormat(); defaultFormat.setSampleBuffers(true); QGLFormat::setDefaultFormat(defaultFormat); // Create and show widget QApplication app(argc, argv); GLWidget widget; widget.setGeometry(10, 10, 500, 500); widget.show(); // Create scene GeometryNode *geometry = new GeometryNode; widget.renderer().scene().rootNode().addChild(geometry); // Add a small sphere at the origin for reference: SphereGeometry *spheres = new SphereGeometry; spheres->addSphere(Vector3f::Zero(), Vector3ub(128, 128, 128), 0.1f); geometry->addDrawable(spheres); // Default text property: TextProperties tprop; // Test alignment: TextLabel3D *l3 = NULL; TextLabel2D *l2 = NULL; // 3D: tprop.setColorRgb(255, 0, 0); tprop.setAlign(TextProperties::HLeft, TextProperties::VTop); l3 = new TextLabel3D; l3->setText("Upper Left Anchor"); l3->setAnchor(Vector3f::Zero()); l3->setTextProperties(tprop); geometry->addDrawable(l3); tprop.setColorRgb(0, 255, 0); tprop.setAlign(TextProperties::HLeft, TextProperties::VBottom); l3 = new TextLabel3D; l3->setText("Bottom Left Anchor"); l3->setAnchor(Vector3f::Zero()); l3->setTextProperties(tprop); geometry->addDrawable(l3); tprop.setColorRgb(0, 0, 255); tprop.setAlign(TextProperties::HRight, TextProperties::VTop); l3 = new TextLabel3D; l3->setText("Upper Right Anchor"); l3->setAnchor(Vector3f::Zero()); l3->setTextProperties(tprop); geometry->addDrawable(l3); tprop.setColorRgb(255, 255, 0); tprop.setAlign(TextProperties::HRight, TextProperties::VBottom); l3 = new TextLabel3D; l3->setText("Bottom Right Anchor"); l3->setAnchor(Vector3f::Zero()); l3->setTextProperties(tprop); geometry->addDrawable(l3); tprop.setColorRgba(255, 255, 255, 220); tprop.setRotationDegreesCW(90.f); tprop.setAlign(TextProperties::HCenter, TextProperties::VCenter); l3 = new TextLabel3D; l3->setText("Centered Anchor (3D)"); l3->setAnchor(Vector3f::Zero()); l3->setTextProperties(tprop); l3->setRenderPass(Avogadro::Rendering::TranslucentPass); geometry->addDrawable(l3); tprop.setRotationDegreesCW(0.f); tprop.setAlpha(255); // 2D: tprop.setColorRgb(255, 0, 0); tprop.setAlign(TextProperties::HLeft, TextProperties::VTop); l2 = new TextLabel2D; l2->setText("Upper Left Corner"); l2->setAnchor(Vector2i(0, widget.height())); l2->setTextProperties(tprop); geometry->addDrawable(l2); tprop.setColorRgb(0, 255, 0); tprop.setAlign(TextProperties::HLeft, TextProperties::VBottom); l2 = new TextLabel2D; l2->setText("Bottom Left Corner"); l2->setAnchor(Vector2i(0, 0)); l2->setTextProperties(tprop); geometry->addDrawable(l2); tprop.setColorRgb(0, 0, 255); tprop.setAlign(TextProperties::HRight, TextProperties::VTop); l2 = new TextLabel2D; l2->setText("Upper Right Corner"); l2->setAnchor(Vector2i(widget.width(), widget.height())); l2->setTextProperties(tprop); geometry->addDrawable(l2); tprop.setColorRgb(255, 255, 0); tprop.setAlign(TextProperties::HRight, TextProperties::VBottom); l2 = new TextLabel2D; l2->setText("Bottom Right Corner"); l2->setAnchor(Vector2i(widget.width(), 0)); l2->setTextProperties(tprop); geometry->addDrawable(l2); tprop.setColorRgba(255, 255, 255, 220); tprop.setAlign(TextProperties::HCenter, TextProperties::VCenter); l2 = new TextLabel2D; l2->setText("Centered Anchor (2D)"); l2->setAnchor(Vector2i(widget.width() / 2, widget.height() / 2)); l2->setTextProperties(tprop); geometry->addDrawable(l2); // Test the TextLabel3D's radius feature: spheres->addSphere(Vector3f(0.f, 6.f, 0.f), Vector3ub(255, 255, 255), 1.f); tprop.setColorRgba(255, 128, 64, 255); tprop.setRotationDegreesCW(90.f); l3 = new TextLabel3D; l3->setText("Clipped"); l3->setAnchor(Vector3f(0.f, 6.f, 0.f)); l3->setTextProperties(tprop); geometry->addDrawable(l3); tprop.setColorRgba(64, 128, 255, 255); tprop.setRotationDegreesCW(45.f); l3 = new TextLabel3D; l3->setText("Projected"); l3->setAnchor(Vector3f(0.f, 6.f, 0.f)); l3->setTextProperties(tprop); l3->setRadius(1.f); geometry->addDrawable(l3); // Make sure the widget renders the scene, and store it in a QImage. widget.raise(); widget.repaint(); // Run the application for a while, and then quit so we can save an image. QTimer timer; timer.setSingleShot(true); app.connect(&timer, SIGNAL(timeout()), SLOT(quit())); timer.start(200); app.exec(); // Grab the frame buffer of the GLWidget and save it to a QImage. QImage image = widget.grabFrameBuffer(false); // Set up the image regression test. ImageRegressionTest test(argc, argv); // Do the image threshold test, printing output to the std::cout for ctest. return test.imageThresholdTest(image, std::cout); }