std::shared_ptr<LayerRepresentation> Layer::createDefaultRepresentation() const { return createLayerRAM(getDimensions(), getLayerType(), getDataFormat()); }
inline int getWidth() const { return getDimensions().x; }
void ModelOverlay::update(float deltatime) { if (_updateModel) { _updateModel = false; _model->setSnapModelToCenter(true); Transform transform = evalRenderTransform(); if (_scaleToFit) { _model->setScaleToFit(true, transform.getScale() * getDimensions()); } else { _model->setScale(transform.getScale()); } _model->setRotation(transform.getRotation()); _model->setTranslation(transform.getTranslation()); _model->setURL(_url); _model->simulate(deltatime, true); } else { _model->simulate(deltatime); } _isLoaded = _model->isActive(); if (isAnimatingSomething()) { if (!jointsMapped()) { mapAnimationJoints(_model->getJointNames()); } animate(); } // check to see if when we added our model to the scene they were ready, if they were not ready, then // fix them up in the scene render::ScenePointer scene = qApp->getMain3DScene(); render::Transaction transaction; if (_model->needsFixupInScene()) { emit DependencyManager::get<scriptable::ModelProviderFactory>()->modelRemovedFromScene(getID(), NestableType::Overlay, _model); _model->removeFromScene(scene, transaction); _model->addToScene(scene, transaction); auto newRenderItemIDs{ _model->fetchRenderItemIDs() }; transaction.updateItem<Overlay>(getRenderItemID(), [newRenderItemIDs](Overlay& data) { auto modelOverlay = static_cast<ModelOverlay*>(&data); modelOverlay->setSubRenderItemIDs(newRenderItemIDs); }); processMaterials(); emit DependencyManager::get<scriptable::ModelProviderFactory>()->modelAddedToScene(getID(), NestableType::Overlay, _model); } if (_visibleDirty) { _visibleDirty = false; // don't show overlays in mirrors or spectator-cam unless _isVisibleInSecondaryCamera is true _model->setVisibleInScene(getVisible(), scene, render::ItemKey::TAG_BITS_0 | (_isVisibleInSecondaryCamera ? render::ItemKey::TAG_BITS_1 : render::ItemKey::TAG_BITS_NONE), false); } if (_drawInFrontDirty) { _drawInFrontDirty = false; _model->setLayeredInFront(getDrawInFront(), scene); } if (_drawInHUDDirty) { _drawInHUDDirty = false; _model->setLayeredInHUD(getDrawHUDLayer(), scene); } scene->enqueueTransaction(transaction); if (!_texturesLoaded && _model->getGeometry() && _model->getGeometry()->areTexturesLoaded()) { _texturesLoaded = true; _model->updateRenderItems(); } }
glm::vec2 RayPick::projectOntoEntityXYPlane(const QUuid& entityID, const glm::vec3& worldPos, bool unNormalized) { auto props = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(entityID); return projectOntoXYPlane(worldPos, props.getPosition(), props.getRotation(), props.getDimensions(), props.getRegistrationPoint(), unNormalized); }
void Image3DOverlay::render(RenderArgs* args) { if (!_isLoaded) { _isLoaded = true; _texture = DependencyManager::get<TextureCache>()->getTexture(_url); } if (!_visible || !getParentVisible() || !_texture || !_texture->isLoaded()) { return; } Q_ASSERT(args->_batch); gpu::Batch* batch = args->_batch; float imageWidth = _texture->getWidth(); float imageHeight = _texture->getHeight(); QRect fromImage; if (_fromImage.isNull()) { fromImage.setX(0); fromImage.setY(0); fromImage.setWidth(imageWidth); fromImage.setHeight(imageHeight); } else { float scaleX = imageWidth / _texture->getOriginalWidth(); float scaleY = imageHeight / _texture->getOriginalHeight(); fromImage.setX(scaleX * _fromImage.x()); fromImage.setY(scaleY * _fromImage.y()); fromImage.setWidth(scaleX * _fromImage.width()); fromImage.setHeight(scaleY * _fromImage.height()); } float maxSize = glm::max(fromImage.width(), fromImage.height()); float x = fromImage.width() / (2.0f * maxSize); float y = -fromImage.height() / (2.0f * maxSize); glm::vec2 topLeft(-x, -y); glm::vec2 bottomRight(x, y); glm::vec2 texCoordTopLeft(fromImage.x() / imageWidth, fromImage.y() / imageHeight); glm::vec2 texCoordBottomRight((fromImage.x() + fromImage.width()) / imageWidth, (fromImage.y() + fromImage.height()) / imageHeight); const float MAX_COLOR = 255.0f; xColor color = getColor(); float alpha = getAlpha(); applyTransformTo(_transform, true); Transform transform = _transform; transform.postScale(glm::vec3(getDimensions(), 1.0f)); batch->setModelTransform(transform); batch->setResourceTexture(0, _texture->getGPUTexture()); DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(*batch, true, false, _emissive, true); DependencyManager::get<GeometryCache>()->renderQuad( *batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, glm::vec4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha) ); batch->setResourceTexture(0, args->_whiteTexture); // restore default white color after me }
void RenderableWebEntityItem::render(RenderArgs* args) { QOpenGLContext * currentContext = QOpenGLContext::currentContext(); QSurface * currentSurface = currentContext->surface(); if (!_webSurface) { _webSurface = new OffscreenQmlSurface(); _webSurface->create(currentContext); _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/")); _webSurface->load("WebEntity.qml"); _webSurface->resume(); _webSurface->getRootItem()->setProperty("url", _sourceUrl); _connection = QObject::connect(_webSurface, &OffscreenQmlSurface::textureUpdated, [&](GLuint textureId) { _webSurface->lockTexture(textureId); assert(!glGetError()); // TODO change to atomic<GLuint>? withLock(_textureLock, [&] { std::swap(_texture, textureId); }); if (textureId) { _webSurface->releaseTexture(textureId); } if (_texture) { _webSurface->makeCurrent(); glBindTexture(GL_TEXTURE_2D, _texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, 0); _webSurface->doneCurrent(); } }); auto forwardMouseEvent = [=](const RayToEntityIntersectionResult& intersection, const QMouseEvent* event, unsigned int deviceId) { // Ignore mouse interaction if we're locked if (this->getLocked()) { return; } if (event->button() == Qt::MouseButton::RightButton) { if (event->type() == QEvent::MouseButtonPress) { const QMouseEvent* mouseEvent = static_cast<const QMouseEvent*>(event); _lastPress = toGlm(mouseEvent->pos()); } } if (intersection.entityID == getID()) { if (event->button() == Qt::MouseButton::RightButton) { if (event->type() == QEvent::MouseButtonRelease) { const QMouseEvent* mouseEvent = static_cast<const QMouseEvent*>(event); ivec2 dist = glm::abs(toGlm(mouseEvent->pos()) - _lastPress); if (!glm::any(glm::greaterThan(dist, ivec2(1)))) { AbstractViewStateInterface::instance()->postLambdaEvent([this] { QMetaObject::invokeMethod(_webSurface->getRootItem(), "goBack"); }); } _lastPress = ivec2(INT_MIN); } return; } // FIXME doesn't work... double click events not received if (event->type() == QEvent::MouseButtonDblClick) { AbstractViewStateInterface::instance()->postLambdaEvent([this] { _webSurface->getRootItem()->setProperty("url", _sourceUrl); }); } if (event->button() == Qt::MouseButton::MiddleButton) { if (event->type() == QEvent::MouseButtonRelease) { AbstractViewStateInterface::instance()->postLambdaEvent([this] { _webSurface->getRootItem()->setProperty("url", _sourceUrl); }); } return; } // Map the intersection point to an actual offscreen pixel glm::vec3 point = intersection.intersection; point -= getPosition(); point = glm::inverse(getRotation()) * point; point /= getDimensions(); point += 0.5f; point.y = 1.0f - point.y; point *= getDimensions() * METERS_TO_INCHES * DPI; // Forward the mouse event. QMouseEvent mappedEvent(event->type(), QPoint((int)point.x, (int)point.y), event->screenPos(), event->button(), event->buttons(), event->modifiers()); QCoreApplication::sendEvent(_webSurface->getWindow(), &mappedEvent); } }; EntityTreeRenderer* renderer = static_cast<EntityTreeRenderer*>(args->_renderer); QObject::connect(renderer, &EntityTreeRenderer::mousePressOnEntity, forwardMouseEvent); QObject::connect(renderer, &EntityTreeRenderer::mouseReleaseOnEntity, forwardMouseEvent); QObject::connect(renderer, &EntityTreeRenderer::mouseMoveOnEntity, forwardMouseEvent); } glm::vec2 dims = glm::vec2(getDimensions()); dims *= METERS_TO_INCHES * DPI; // The offscreen surface is idempotent for resizes (bails early // if it's a no-op), so it's safe to just call resize every frame // without worrying about excessive overhead. _webSurface->resize(QSize(dims.x, dims.y)); currentContext->makeCurrent(currentSurface); PerformanceTimer perfTimer("RenderableWebEntityItem::render"); Q_ASSERT(getType() == EntityTypes::Web); static const glm::vec2 texMin(0.0f), texMax(1.0f), topLeft(-0.5f), bottomRight(0.5f); Q_ASSERT(args->_batch); gpu::Batch& batch = *args->_batch; batch.setModelTransform(getTransformToCenter()); bool textured = false, culled = false, emissive = false; if (_texture) { batch._glActiveBindTexture(GL_TEXTURE0, GL_TEXTURE_2D, _texture); textured = emissive = true; } DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch, textured, culled, emissive); DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, texMin, texMax, glm::vec4(1.0f)); }
void BabyDragon::onCreate(int x, int y) { getDimensions()->x = x; getDimensions()->y = y; }
void TensorFlowEngine::run() { if(mInputNodes.empty()) throw Exception("At least one output node has to be given to the NeuralNetwork before execution"); if(mOutputNodes.empty()) throw Exception("At least one output node has to be given to the NeuralNetwork before execution"); // For each input, create a tensorflow tensor: std::vector <std::pair<std::string, tensorflow::Tensor>> input_tensors; for(auto inputNode : mInputNodes) { const std::string name = inputNode.first; if(!inputNode.second.data) throw Exception("Input node " + name + " has not received any data"); auto shape = inputNode.second.data->getShape(); if(shape.getUnknownDimensions() > 0) throw Exception("Input shape must be fully known when executing NN"); // Construct tensorflow tensor tensorflow::TensorShape tensorShape; for(auto i : shape.getAll()) { tensorShape.AddDim(i); } tensorflow::Tensor input_tensor( tensorflow::DT_FLOAT, tensorShape ); // Give tensor data to tensorflow // TODO is the data here actually moved? TensorAccess::pointer access = inputNode.second.data->getAccess(ACCESS_READ); switch(shape.getDimensions()) { case 2: input_tensor.tensor<float, 2>() = std::move(access->getData<2>()); break; case 3: input_tensor.tensor<float, 3>() = std::move(access->getData<3>()); break; case 4: input_tensor.tensor<float, 4>() = std::move(access->getData<4>()); break; case 5: input_tensor.tensor<float, 5>() = std::move(access->getData<5>()); break; case 6: input_tensor.tensor<float, 6>() = std::move(access->getData<6>()); break; default: throw Exception("Invalid tensor dimension size"); } // Add tensorflow tensor to list of input tensors input_tensors.push_back(std::make_pair(name, input_tensor)); } for(std::string name : mLearningPhaseTensors) { // Create a scalar tensor which tells the system we are NOT doing training tensorflow::Tensor input_tensor2( tensorflow::DT_BOOL, tensorflow::TensorShape() // Scalar ); auto input_tensor_mapped2 = input_tensor2.tensor<bool, 0>(); input_tensor_mapped2(0) = false; input_tensors.push_back(std::make_pair(name, input_tensor2)); } std::vector<tensorflow::Tensor> output_tensors; reportInfo() << "Running network" << reportEnd(); tensorflow::Status s; //mRuntimeManager->startRegularTimer("network_execution"); std::vector<std::string> outputNames; for(auto node : mOutputNodes) outputNames.push_back(node.first); s = mSession->Run(input_tensors, outputNames, {}, &output_tensors); //mRuntimeManager->stopRegularTimer("network_execution"); if (!s.ok()) { throw Exception("Error during inference: " + s.ToString()); } reportInfo() << "Finished executing network" << reportEnd(); // Collect all output data as FAST tensors for(int j = 0; j < outputNames.size(); ++j) { const std::string outputName = outputNames[j]; const NetworkNode node = mOutputNodes[outputName]; auto tensor = TensorflowTensor::New(); tensor->create(std::move(output_tensors[j])); mOutputNodes[outputName].data = tensor; } reportInfo() << "Finished parsing output" << reportEnd(); }
// mjmarin: this version works with cv::Mat cv::Mat FeatPyramid::process2( const IplImage *mximage, const float mxsbin ) { //cout << "Init process pyramid" << endl; float *im = getImgData <float> (mximage); int dims[3]; getDimensions (mximage, dims); if (dims[2] != 3) cout << "Invalid input" << endl; int sbin = (int) mxsbin; // memory for caching orientation histograms & their norms int blocks[2]; blocks[0] = (int)round((float)dims[0]/(float)sbin); blocks[1] = (int)round((float)dims[1]/(float)sbin); assert (blocks[0] > 0); assert (blocks[1] > 0); float *hist = new float [blocks[0]*blocks[1]*18]; for (int i = 0; i < blocks[0]*blocks[1]*18; i++) hist[i] = 0; float *norm = new float [blocks[0]*blocks[1]]; for (int i = 0; i < blocks[0]*blocks[1]; i++) norm[i] = 0; // memory for HOG features int out[3]; out[0] = max(blocks[0]-2, 0); out[1] = max(blocks[1]-2, 0); out[2] = 27+4+1; //CvMatND *mxfeat; cv::Mat mxfeat; //cout << "POS" << endl; if (out[0] == 0 && out[1] == 0 ) { cout << "Empty matrix" << endl; mxfeat = 0.0; } else { assert (out[0] > 0); assert (out[1] > 0); //mxfeat = createNDMatrix (3, out, CV_64FC1); //createMatrix (3, out, CV_64FC1, &mxfeat); mxfeat.create(3, out, CV_64FC1); //assert (mxfeat != NULL); assert (!mxfeat.empty()); //cout << "POS" << endl; //double *feat = new double [out[0] * out[1] * out[2]]; //float *feat = getMatNData <float> (mxfeat); float *feat = new float [out[0] * out[1] * out[2]]; assert (feat != NULL); //cout << "POS" << endl; int visible[2]; visible[0] = blocks[0]*sbin; visible[1] = blocks[1]*sbin; float *s; float dy, dx; float v; float dy2, dx2; float v2; float dy3, dx3; float v3; float best_dot = 0; int best_o = 0; float dot; float xp, yp; int ixp, iyp; float vx0, vy0, vx1, vy1; float *src1, *src2; float *dst, *end; float *dst2; float *src, *p, n1, n2, n3, n4; float t1 = 0; float t2 = 0; float t3 = 0; float t4 = 0; double h1, h2, h3, h4; // // // float sum = 0;// // for (int x = 1; x < visible[1]-1; x++) { for (int y = 1; y < visible[0]-1; y++) { // first color channel s = im + min(x, dims[1]-2)*dims[0] + min(y, dims[0]-2); dy = *(s+1) - *(s-1); dx = *(s+dims[0]) - *(s-dims[0]); v = dx*dx + dy*dy; // second color channel s += dims[0]*dims[1]; dy2 = *(s+1) - *(s-1); dx2 = *(s+dims[0]) - *(s-dims[0]); v2 = dx2*dx2 + dy2*dy2; // third color channel s += dims[0]*dims[1]; dy3 = *(s+1) - *(s-1); dx3 = *(s+dims[0]) - *(s-dims[0]); v3 = dx3*dx3 + dy3*dy3; // pick channel with strongest gradient if (v2 > v) { v = v2; dx = dx2; dy = dy2; } if (v3 > v) { v = v3; dx = dx3; dy = dy3; } // snap to one of 18 orientations best_dot = 0; best_o = 0; for (int o = 0; o < 9; o++) { dot = uu[o]*dx + vv[o]*dy; if (dot > best_dot) { best_dot = dot; best_o = o; } else if (-dot > best_dot) { best_dot = -dot; best_o = o+9; } } // add to 4 histograms around pixel using linear interpolation xp = ((float)x+0.5)/(float)sbin - 0.5; yp = ((float)y+0.5)/(float)sbin - 0.5; ixp = (int)floor(xp); iyp = (int)floor(yp); vx0 = xp-ixp; vy0 = yp-iyp; vx1 = 1.0-vx0; vy1 = 1.0-vy0; v = sqrt(v); //cout << "POS" << endl; if (ixp >= 0 && iyp >= 0) { *(hist + ixp*blocks[0] + iyp + best_o*blocks[0]*blocks[1]) += vx1*vy1*v; } if (ixp+1 < blocks[1] && iyp >= 0) { *(hist + (ixp+1)*blocks[0] + iyp + best_o*blocks[0]*blocks[1]) += vx0*vy1*v; } if (ixp >= 0 && iyp+1 < blocks[0]) { *(hist + ixp*blocks[0] + (iyp+1) + best_o*blocks[0]*blocks[1]) += vx1*vy0*v; } if (ixp+1 < blocks[1] && iyp+1 < blocks[0]) { *(hist + (ixp+1)*blocks[0] + (iyp+1) + best_o*blocks[0]*blocks[1]) += vx0*vy0*v; } } } //cout << "POS" << endl; // compute energy in each block by summing over orientations for (int o = 0; o < 9; o++) { src1 = hist + o*blocks[0]*blocks[1]; src2 = hist + (o+9)*blocks[0]*blocks[1]; dst = norm; end = norm + blocks[1]*blocks[0]; while (dst < end) { *(dst++) += (*src1 + *src2) * (*src1 + *src2); src1++; src2++; } } //cout << "POS" << endl; // compute features for (int x = 0; x < out[1]; x++) { for (int y = 0; y < out[0]; y++) { dst2 = feat + x*out[0] + y; p = norm + (x+1)*blocks[0] + y+1; n1 = 1.0 / sqrt(*p + *(p+1) + *(p+blocks[0]) + *(p+blocks[0]+1) + eps); p = norm + (x+1)*blocks[0] + y; n2 = 1.0 / sqrt(*p + *(p+1) + *(p+blocks[0]) + *(p+blocks[0]+1) + eps); p = norm + x*blocks[0] + y+1; n3 = 1.0 / sqrt(*p + *(p+1) + *(p+blocks[0]) + *(p+blocks[0]+1) + eps); p = norm + x*blocks[0] + y; n4 = 1.0 / sqrt(*p + *(p+1) + *(p+blocks[0]) + *(p+blocks[0]+1) + eps); t1 = 0; t2 = 0; t3 = 0; t4 = 0; // contrast-sensitive features src = hist + (x+1)*blocks[0] + (y+1); for (int o = 0; o < 18; o++) { h1 = min(*src * n1, 0.2); h2 = min(*src * n2, 0.2); h3 = min(*src * n3, 0.2); h4 = min(*src * n4, 0.2); *dst2 = 0.5 * (h1 + h2 + h3 + h4); t1 += h1; t2 += h2; t3 += h3; t4 += h4; dst2 += out[0]*out[1]; src += blocks[0]*blocks[1]; } // contrast-insensitive features src = hist + (x+1)*blocks[0] + (y+1); for (int o = 0; o < 9; o++) { sum = *src + *(src + 9*blocks[0]*blocks[1]); h1 = min(sum * n1, 0.2); h2 = min(sum * n2, 0.2); h3 = min(sum * n3, 0.2); h4 = min(sum * n4, 0.2); *dst2 = 0.5 * (h1 + h2 + h3 + h4); dst2 += out[0]*out[1]; src += blocks[0]*blocks[1]; } // texture features *dst2 = 0.2357 * t1; dst2 += out[0]*out[1]; *dst2 = 0.2357 * t2; dst2 += out[0]*out[1]; *dst2 = 0.2357 * t3; dst2 += out[0]*out[1]; *dst2 = 0.2357 * t4; // truncation feature dst2 += out[0]*out[1]; *dst2 = 0; } } delete[] hist; delete[] norm; // setMatNData (mxfeat, feat); delete[] feat; } // delete[] im; // return mxfeat; }
bool Region::operator==(const Region &o) const { if (initialized_ != o.initialized_ || outputs_.size() != o.outputs_.size() || inputs_.size() != o.inputs_.size()) { return false; } if (name_ != o.name_ || type_ != o.type_ || spec_ != o.spec_ || phases_ != o.phases_ ) { return false; } if (getDimensions() != o.getDimensions()) { return false; } // Compare Regions's Input (checking only input buffer names and type) static auto compareInput = [](decltype(*inputs_.begin()) a, decltype(*inputs_.begin()) b) { if (a.first != b.first) { return false; } auto input_a = a.second; auto input_b = b.second; if (input_a->getDimensions() != input_b->getDimensions()) return false; if (input_a->isInitialized() != input_b->isInitialized()) return false; if (input_a->isInitialized()) { if (input_a->getData().getType() != input_b->getData().getType() || input_a->getData().getCount() != input_b->getData().getCount()) return false; } auto links_a = input_a->getLinks(); auto links_b = input_b->getLinks(); if (links_a.size() != links_b.size()) { return false; } for (size_t i = 0; i < links_a.size(); i++) { if (*(links_a[i]) != *(links_b[i])) { return false; } } return true; }; if (!std::equal(inputs_.begin(), inputs_.end(), o.inputs_.begin(), compareInput)) { return false; } // Compare Regions's Output (checking only output buffer names and type.) static auto compareOutput = [](decltype(*outputs_.begin()) a, decltype(*outputs_.begin()) b) { if (a.first != b.first ) { return false; } auto output_a = a.second; auto output_b = b.second; if (output_a->getDimensions() != output_b->getDimensions()) return false; if (output_a->getData().getType() != output_b->getData().getType() || output_a->getData().getCount() != output_b->getData().getCount()) return false; return true; }; if (!std::equal(outputs_.begin(), outputs_.end(), o.outputs_.begin(), compareOutput)) { return false; } return true; }
Quad:: Quad ( Edge& edgeOne, Edge& edgeTwo, Edge& edgeThree, Edge& edgeFour, int id ) : PropertyContainer(), _edges( boost::assign::list_of(&edgeOne)(&edgeTwo)(&edgeThree)(&edgeFour).to_array(_edges) ), _vertexMap(), _id( id ), _normal( edgeOne.getDimensions() ), _center( edgeOne.getDimensions() ), _enclosingRadius ( 0.0 ) { assertion2(edgeOne.getDimensions() == edgeTwo.getDimensions(), edgeOne.getDimensions(), edgeTwo.getDimensions() ); assertion2(edgeTwo.getDimensions() == edgeThree.getDimensions(), edgeTwo.getDimensions(), edgeThree.getDimensions() ); assertion2(edgeThree.getDimensions() == edgeFour.getDimensions(), edgeThree.getDimensions(), edgeFour.getDimensions() ); assertion1(getDimensions() == 3, getDimensions()); // Determine vertex map Vertex& v0 = edge(0).vertex(0); Vertex& v1 = edge(0).vertex(1); // Check for edges 0 and 1 which vertex establishes connection if (&edge(1).vertex(0) == &v0){ _vertexMap[0] = 1; _vertexMap[1] = 0; } else if (&edge(1).vertex(1) == &v0){ _vertexMap[0] = 1; _vertexMap[1] = 1; } else if (&edge(1).vertex(0) == &v1){ _vertexMap[0] = 0; _vertexMap[1] = 0; } else { assertion(&edge(1).vertex(1) == &v1); _vertexMap[0] = 0; _vertexMap[1] = 1; } // Check for edges 1 and 2 which vertex establishes connection if (_vertexMap[1] == 0){ if (&edge(2).vertex(0) == &edge(1).vertex(1)){ _vertexMap[2] = 0; } else { assertion(&edge(2).vertex(1) == &edge(1).vertex(1)); _vertexMap[2] = 1; } } else if (_vertexMap[1] == 1){ if (&edge(2).vertex(0) == &edge(1).vertex(0)){ _vertexMap[2] = 0; } else { assertion(&edge(2).vertex(1) == &edge(1).vertex(0)); _vertexMap[2] = 1; } } // Check for edges 2 and 3 which vertex establishes connection if (_vertexMap[2] == 0){ if (&edge(3).vertex(0) == &edge(2).vertex(1)){ _vertexMap[3] = 0; } else { assertion(&edge(3).vertex(1) == &edge(2).vertex(1)); _vertexMap[3] = 1; } } else if (_vertexMap[2] == 1){ if (&edge(3).vertex(0) == &edge(2).vertex(0)){ _vertexMap[3] = 0; } else { assertion(&edge(3).vertex(1) == &edge(2).vertex(0)); _vertexMap[3] = 1; } } assertion(&vertex(0) != &vertex(1)); assertion(&vertex(0) != &vertex(2)); assertion(&vertex(0) != &vertex(3)); assertion(&vertex(1) != &vertex(2)); assertion(&vertex(1) != &vertex(3)); assertion(&vertex(2) != &vertex(3)); assertion1((_vertexMap[0] == 0) || (_vertexMap[0] == 1), _vertexMap[0]); assertion1((_vertexMap[1] == 0) || (_vertexMap[1] == 1), _vertexMap[1]); assertion1((_vertexMap[2] == 0) || (_vertexMap[2] == 1), _vertexMap[2]); assertion1((_vertexMap[2] == 0) || (_vertexMap[2] == 1), _vertexMap[3]); }
VolumeRAM* VolumeDiskRaw::loadBrick(const tgt::svec3& pOffset, const tgt::svec3& pDimensions) const throw (tgt::Exception) { //check for wrong parameter if(tgt::hmul(pDimensions) == 0) throw std::invalid_argument("requested brick dimensions are zero!"); if(!tgt::hand(tgt::lessThanEqual(pOffset+pDimensions,getDimensions()))) throw std::invalid_argument("requested brick outside volume date!"); //create new VolumeRam VolumeFactory vf; VolumeRAM* vr = vf.create(getFormat(), pDimensions); if (!vr) throw VoreenException("Failed to create VolumeRAM"); //open file FILE* fin; fin = fopen(getFileName().c_str(),"rb"); if (!fin) throw tgt::FileException("Failed to open file for reading: " + getFileName()); size_t bytesPerVoxel = static_cast<size_t>(vr->getBitsAllocated() / 8); size_t numVoxels = pDimensions.x; size_t numBytes = numVoxels * bytesPerVoxel; int64_t offset = getOffset(); if(offset < 0) { //Assume data is aligned to end of file. // get file size: fseek(fin, 0, SEEK_END); int64_t fileSize = ftell(fin); rewind(fin); //calculate real offset: offset = fileSize - hmul(getDimensions())*bytesPerVoxel; } //modify offset to start at first slice offset += getDimensions().x*getDimensions().y*pOffset.z*bytesPerVoxel; fseek(fin, static_cast<long>(offset), SEEK_SET); //read into ram size_t pointerOffset = 0; for(size_t z = 0; z < pDimensions.z; z++){ for(size_t y = 0; y < pDimensions.y; y++) { //read into ram if(fread(reinterpret_cast<char*>(vr->getData())+pointerOffset, numBytes, 1, fin) != 1) { fclose(fin); delete vr; throw tgt::FileException("Failed to read from file: " + getFileName()); } //move offset pointerOffset += numBytes; //move to next read if(y < pDimensions.y) fseek(fin, static_cast<long>(getDimensions().x-pDimensions.x),SEEK_SET); } //move to next read if(z < pDimensions.z) fseek(fin,static_cast<long>((getDimensions().x*getDimensions().y)-(pDimensions.x*pDimensions.y)),SEEK_SET); } fclose(fin); //swap endian if(getSwapEndian()) { Volume* tempHandle = new Volume(vr, vec3(1.0f), vec3(0.0f)); VolumeOperatorSwapEndianness::APPLY_OP(tempHandle); tempHandle->releaseAllRepresentations(); delete tempHandle; } return vr; }
VolumeRAM* VolumeDiskRaw::loadSlices(const size_t firstSlice, const size_t lastSlice) const throw (tgt::Exception) { //check for wrong parameter if(getDimensions().z <= lastSlice) throw std::invalid_argument("lastSlice is out of volume dimension!!!"); if(firstSlice > lastSlice) throw std::invalid_argument("firstSlice has to be less or equal lastSlice!!!"); //create new VolumeRam VolumeFactory vf; VolumeRAM* vr = vf.create(getFormat(), tgt::svec3(getDimensions().x,getDimensions().y, lastSlice-firstSlice+1)); if (!vr) throw VoreenException("Failed to create VolumeRAM"); //open file std::ifstream infile(getFileName().c_str(), std::ios::in | std::ios::binary); if (infile.fail()) throw tgt::FileException("Failed to open file for reading: " + getFileName()); size_t bytesPerVoxel = static_cast<size_t>(vr->getBitsAllocated() / 8); size_t numVoxels = getDimensions().x*getDimensions().y*(lastSlice-firstSlice+1); size_t numBytes = numVoxels * bytesPerVoxel; int64_t offset = getOffset(); if(offset < 0) { //Assume data is aligned to end of file. // get file size: infile.seekg( 0, infile.end); std::streampos fileSize = infile.tellg(); infile.seekg( 0, infile.beg); //calculate real offset: offset = static_cast<std::string::size_type>(fileSize) - hmul(getDimensions())*bytesPerVoxel; } //modify offset to start at first slice offset += getDimensions().x*getDimensions().y*firstSlice*bytesPerVoxel; infile.seekg(offset); //read into ram infile.read(reinterpret_cast<char*>(vr->getData()),numBytes); if (infile.fail()) { //LERRORC("voreen.RepresentationConverterLoadFromDisk", "read() failed"); infile.close(); delete vr; throw tgt::FileException("Failed to read from file: " + getFileName()); } infile.close(); //swap endian if(getSwapEndian()) { Volume* tempHandle = new Volume(vr, vec3(1.0f), vec3(0.0f)); VolumeOperatorSwapEndianness::APPLY_OP(tempHandle); tempHandle->releaseAllRepresentations(); delete tempHandle; } return vr; }
VolumeRAM* VolumeDiskRaw::loadVolume() const throw (tgt::Exception) { VolumeRAM* volume = 0; LDEBUG("Creating volume from diskrepr. " << getFileName() << " format: " << getFormat()); VolumeFactory vf; try { volume = vf.create(getFormat(), getDimensions()); } catch (std::bad_alloc&) { throw tgt::Exception("bad allocation"); } if (!volume) throw VoreenException("Failed to create VolumeRAM"); FILE* fin; fin = fopen(getFileName().c_str(),"rb"); if (fin == 0) { throw tgt::IOException("Unable to open raw file for reading", getFileName()); } size_t bytesPerVoxel = static_cast<size_t>(volume->getBitsAllocated() / 8); size_t numVoxels = hmul(getDimensions()); size_t numBytes = numVoxels * bytesPerVoxel; int64_t offset = getOffset(); if(offset < 0) { //Assume data is aligned to end of file. // get file size: fseek(fin, 0, SEEK_END); int64_t fileSize = ftell(fin); rewind(fin); //calculate real offset: offset = fileSize - numBytes; } #ifdef _MSC_VER _fseeki64(fin, offset, SEEK_SET); #else fseek(fin, offset, SEEK_SET); #endif if(fread(reinterpret_cast<char*>(volume->getData()), numBytes, 1, fin) != 1) { //LERRORC("voreen.RepresentationConverterLoadFromDisk", "fread() failed"); fclose(fin); delete volume; throw tgt::FileException("Failed to read from file: " + getFileName()); } fclose(fin); if (getSwapEndian()) { Volume* tempHandle = new Volume(volume, vec3(1.0f), vec3(0.0f)); VolumeOperatorSwapEndianness::APPLY_OP(tempHandle); tempHandle->releaseAllRepresentations(); delete tempHandle; } return volume; }
Transform Image3DOverlay::evalRenderTransform() { auto transform = Parent::evalRenderTransform(); transform.postScale(glm::vec3(getDimensions(), 1.0f)); return transform; }
void HeightFieldMapper::process() { if (!inport_.isReady()) return; auto srcImg = inport_.getData(); if (!srcImg) { LogWarn("No valid input image given"); return; } // check the number of channels const DataFormatBase *format = srcImg->getDataFormat(); std::size_t numInputChannels = format->getComponents(); size2_t dim = srcImg->getDimensions(); Image *outImg = nullptr; // check format of output image if (!outImg || (outImg->getDataFormat()->getId() != DataFormatId::Float32)) { // replace with new floating point image Image *img = new Image(dim, DataFloat32::get()); outport_.setData(img); outImg = img; } else if (outImg->getDimensions() != dim) { // adjust dimensions of output image outImg->setDimensions(dim); } LayerRAM *dstLayer = outImg->getColorLayer(0)->getEditableRepresentation<LayerRAM>(); float *data = static_cast<float *>(dstLayer->getData()); // convert input image to float image const LayerRAM *srcLayer = srcImg->getColorLayer(0)->getRepresentation<LayerRAM>(); // special case: input image is already FLOAT32 with 1 channel if ((numInputChannels == 1) && (format->getId() == DataFormatId::Float32)) { const float *srcData = static_cast<const float *>(srcLayer->getData()); std::copy(srcData, srcData + dim.x * dim.y, data); } else { switch (numInputChannels) { case 2: for (unsigned int y = 0; y < dim.y; ++y) { for (unsigned int x = 0; x < dim.x; ++x) { data[y * dim.x + x] = static_cast<float>(srcLayer->getValueAsVec2Double(glm::uvec2(x, y)).r); } } break; case 3: for (unsigned int y = 0; y < dim.y; ++y) { for (unsigned int x = 0; x < dim.x; ++x) { data[y * dim.x + x] = static_cast<float>(srcLayer->getValueAsVec3Double(glm::uvec2(x, y)).r); } } break; case 4: for (unsigned int y = 0; y < dim.y; ++y) { for (unsigned int x = 0; x < dim.x; ++x) { data[y * dim.x + x] = static_cast<float>(srcLayer->getValueAsVec4Double(glm::uvec2(x, y)).r); } } break; case 1: default: for (unsigned int y = 0; y < dim.y; ++y) { for (unsigned int x = 0; x < dim.x; ++x) { data[y * dim.x + x] = static_cast<float>(srcLayer->getValueAsSingleDouble(glm::uvec2(x, y))); } } break; } } // rescale data set std::size_t numValues = dim.x * dim.y; // determine min/max values float minVal = *std::min_element(data, data + numValues); float maxVal = *std::max_element(data, data + numValues); switch (scalingModeProp_.get()) { case HeightFieldScaling::SeaLevel: { // scale heightfield based on sea level and min/max height float sealevel = seaLevel_.get(); float aboveSea = maxVal - sealevel; float belowSea = minVal - sealevel; float factor = maxHeight_.get() / std::max(aboveSea, std::abs(belowSea)); for (std::size_t i = 0; i < numValues; ++i) { data[i] = (data[i] - sealevel) * factor; } } break; case HeightFieldScaling::DataRange: { // scale data to [heightRange_.min : heightRange_.max] glm::vec2 range(heightRange_.get()); float factor = (range.y - range.x) / (maxVal - minVal); for (std::size_t i = 0; i < numValues; ++i) { data[i] = (data[i] - minVal) * factor + range.x; } } break; case HeightFieldScaling::FixedRange: default: { // scale data to [0:1] range float delta = 1.0f / (maxVal - minVal); for (std::size_t i = 0; i < numValues; ++i) { data[i] = (data[i] - minVal) * delta; } } break; } }
std::shared_ptr<VolumeRepresentation> Volume::createDefaultRepresentation() const { return createVolumeRAM(getDimensions(), getDataFormat()); }
void Web3DOverlay::render(RenderArgs* args) { QOpenGLContext * currentContext = QOpenGLContext::currentContext(); QSurface * currentSurface = currentContext->surface(); if (!_webSurface) { _webSurface = DependencyManager::get<OffscreenQmlSurfaceCache>()->acquire(pickURL()); // FIXME, the max FPS could be better managed by being dynamic (based on the number of current surfaces // and the current rendering load) if (_currentMaxFPS != _desiredMaxFPS) { setMaxFPS(_desiredMaxFPS); } loadSourceURL(); _webSurface->resume(); _webSurface->resize(QSize(_resolution.x, _resolution.y)); _webSurface->getRootItem()->setProperty("url", _url); _webSurface->getRootItem()->setProperty("scriptURL", _scriptURL); currentContext->makeCurrent(currentSurface); auto selfOverlayID = getOverlayID(); std::weak_ptr<Web3DOverlay> weakSelf = std::dynamic_pointer_cast<Web3DOverlay>(qApp->getOverlays().getOverlay(selfOverlayID)); auto forwardPointerEvent = [=](OverlayID overlayID, const PointerEvent& event) { auto self = weakSelf.lock(); if (self && overlayID == selfOverlayID) { self->handlePointerEvent(event); } }; auto overlays = &(qApp->getOverlays()); QObject::connect(overlays, &Overlays::mousePressOnOverlay, this, forwardPointerEvent); QObject::connect(overlays, &Overlays::mouseReleaseOnOverlay, this, forwardPointerEvent); QObject::connect(overlays, &Overlays::mouseMoveOnOverlay, this, forwardPointerEvent); QObject::connect(overlays, &Overlays::hoverLeaveOverlay, this, [=](OverlayID overlayID, const PointerEvent& event) { auto self = weakSelf.lock(); if (!self) { return; } if (overlayID == selfOverlayID && (self->_pressed || (!self->_activeTouchPoints.empty() && self->_touchBeginAccepted))) { PointerEvent endEvent(PointerEvent::Release, event.getID(), event.getPos2D(), event.getPos3D(), event.getNormal(), event.getDirection(), event.getButton(), event.getButtons(), event.getKeyboardModifiers()); forwardPointerEvent(overlayID, endEvent); } }); QObject::connect(this, &Web3DOverlay::scriptEventReceived, _webSurface.data(), &OffscreenQmlSurface::emitScriptEvent); QObject::connect(_webSurface.data(), &OffscreenQmlSurface::webEventReceived, this, &Web3DOverlay::webEventReceived); } else { if (_currentMaxFPS != _desiredMaxFPS) { setMaxFPS(_desiredMaxFPS); } } if (_mayNeedResize) { _mayNeedResize = false; _webSurface->resize(QSize(_resolution.x, _resolution.y)); } if (!_visible || !getParentVisible()) { return; } vec2 halfSize = getSize() / 2.0f; vec4 color(toGlm(getColor()), getAlpha()); Transform transform = getTransform(); // FIXME: applyTransformTo causes tablet overlay to detach from tablet entity. // Perhaps rather than deleting the following code it should be run only if isFacingAvatar() is true? /* applyTransformTo(transform, true); setTransform(transform); */ if (glm::length2(getDimensions()) != 1.0f) { transform.postScale(vec3(getDimensions(), 1.0f)); } if (!_texture) { auto webSurface = _webSurface; _texture = gpu::Texture::createExternal(OffscreenQmlSurface::getDiscardLambda()); _texture->setSource(__FUNCTION__); } OffscreenQmlSurface::TextureAndFence newTextureAndFence; bool newTextureAvailable = _webSurface->fetchTexture(newTextureAndFence); if (newTextureAvailable) { _texture->setExternalTexture(newTextureAndFence.first, newTextureAndFence.second); } Q_ASSERT(args->_batch); gpu::Batch& batch = *args->_batch; batch.setResourceTexture(0, _texture); batch.setModelTransform(transform); auto geometryCache = DependencyManager::get<GeometryCache>(); if (color.a < OPAQUE_ALPHA_THRESHOLD) { geometryCache->bindTransparentWebBrowserProgram(batch, _isAA); } else { geometryCache->bindOpaqueWebBrowserProgram(batch, _isAA); } geometryCache->renderQuad(batch, halfSize * -1.0f, halfSize, vec2(0), vec2(1), color, _geometryId); batch.setResourceTexture(0, nullptr); // restore default white color after me }
bool AnimationThread::threadLoop() { if (android::uptimeMillis() - m_stallTime < MS_PER_FRAME) return true; m_stallTime = android::uptimeMillis(); m_idleTime += android::uptimeMillis() - m_startIdleTime; m_startExecutionTime = android::uptimeMillis(); bool reCreateFlag = false; int width, height; getDimensions(width, height); if (m_bitmap->width() != width || m_bitmap->height() != height) { delete m_canvas; delete m_bitmap; m_bitmap = constructBitmap(width, height); m_canvas = new SkCanvas(*m_bitmap); // change the ball's speed to match the size m_dx = width * .005f; m_dy = height * .007f; reCreateFlag = true; } // setup variables const float OW = width * .125f; const float OH = height * .125f; // clear the old oval m_bitmap->eraseColor(0x880000FF); // update the coordinates of the oval bounce(&m_x, &m_dx, width - OW); bounce(&m_y, &m_dy, height - OH); // draw the new oval m_oval.fLeft = m_x; m_oval.fTop = m_y; m_oval.fRight = m_x + OW; m_oval.fBottom = m_y + OH; m_paint->setColor(0xAAFF0000); m_canvas->drawOval(m_oval, *m_paint); if (!reCreateFlag) { updateNativeWindow(m_ANW, *m_bitmap); } else { setupNativeWindow(m_ANW, *m_bitmap); } m_executionTime += android::uptimeMillis() - m_startExecutionTime; m_counter++; if (android::uptimeMillis() - m_lastPrintTime > 5000) { float fps = m_counter / ((android::uptimeMillis() - m_startTime) / 1000); float spf = ((android::uptimeMillis() - m_startTime)) / m_counter; float lpf = (m_idleTime) / m_counter; float exe = (m_executionTime) / m_counter; gLogI.log(kError_ANPLogType, "TEXT: counter(%d) fps(%f) spf(%f) lock(%f) execution(%f)\n", (int)m_counter, fps, spf, lpf, exe); m_lastPrintTime = android::uptimeMillis(); m_counter = 0; m_executionTime = 0; m_idleTime = 0; m_startExecutionTime = 0; m_startTime = android::uptimeMillis(); } m_startIdleTime = android::uptimeMillis(); // count delay between frames return true; }
glm::vec2 Web3DOverlay::getSize() const { return _resolution / _dpi * INCHES_TO_METERS * getDimensions(); };
/** This function traces a single detection. * \param padX - is the horizontal padding used on the features pyramid * \param padY - is the vertical padding used on the features pyramid * \param scales - is the scales field of the <tt>FeatPyramid</tt> object * \param sx - indicates the current detection \e x coordinate * \param sy - indicates the current detection \e y coordinate * \param sl - indicates the current detection features pyramid level * \param sval - indicates the current detection score * \param out - contains learning information. Given in a linear vector way * \param dets - contains each detection coordinates and scores. Given in * a linear vector way * \param detsdim - indicates the dimension of the bidimensional matrix * <tt>dets</tt> * \param boxes - contains each part of the detection coordinates. Given in * a linear vector way * \param boxesdim - indicates the dimension of the bidimensional matrix * <tt>boxes</tt> */ static void trace(int padX, int padY, const float *scales, int sx, int sy, int sl, double sval, double *out, double *dets, int *detsdim, double *boxes, int *boxesdim) { // initial stack for tracing the detection int cur = 0; Q[cur].symbol = startSymbol; Q[cur].x = sx; Q[cur].y = sy; Q[cur].l = sl; Q[cur].ds = 0; Q[cur].val = sval; node n; double *info; char type; int fi; int *fsz; double scale; int x1; int y1; int x2; int y2; bool success = false; rules symRules; int rulesDim; int r = 0; int probeY; int probeX2; int probeX; int probeY2; CvMat *mxScore; double *score; int sz[2]; int *detwin; int *rhs; int rhsDim; anchor anch; int ax; int ay; int ds; int px; int py; int pl; CvMat *mxIx; CvMat *mxIy; int *Ix; int *Iy; int isz[2]; //cout << "Init trace" << endl; while (cur >= 0) { // Pop a node off the stack n = Q[cur]; cur--; // Detection information for the current symbol info = out + DET_SZ * n.symbol; info[DET_USE] = 1; info[DET_VAL] = n.val; type = model->getSymbols()[n.symbol].type; // Symbol is a terminal if (type == 'T') { // Detection info for terminal info[DET_IND] = -1; info[DET_X] = n.x + 1; info[DET_Y] = n.y + 1; info[DET_L] = n.l + 1; info[DET_DS] = n.ds; // Terminal symbol fi = model->getSymbols()[n.symbol].filter-1; // Filter size fsz = model->getFilters()[fi].size; // Detection scale scale = model->getSbin()/scales[n.l]; // Compute and record image coordinates for the filter x1 = cvRound((n.x-padX*pow2(n.ds))*scale); y1 = cvRound((n.y-padY*pow2(n.ds))*scale); x2 = cvRound(x1 + fsz[1]*scale - 1); y2 = cvRound(y1 + fsz[0]*scale - 1); boxes[boxesdim[0]*(4*fi + 0)] = x1 + 1; boxes[boxesdim[0]*(4*fi + 1)] = y1 + 1; boxes[boxesdim[0]*(4*fi + 2)] = x2 + 1; boxes[boxesdim[0]*(4*fi + 3)] = y2 + 1; continue; } // Find the rule that produced the current node by looking at // which score table holds n.val at the symbol's location success = false; symRules = rul[n.symbol]; rulesDim = symRules.n; for (r = 0; r < rulesDim; r++) { // probe location = symbol location minus virtual padding probeY = n.y - virtpadding(padY, n.ds); probeX = n.x - virtpadding(padX, n.ds); cv::Mat tmpScore; tmpScore = symRules.structure[r].getScore()[n.l]; CvMat mxScore2 = tmpScore; mxScore = &mxScore2; score = new double [mxScore->rows * mxScore->cols]; getMatData <double> (mxScore, score); getDimensions(mxScore, sz); // pick this rule if the score at the probe location matches n.val if (score[probeX*sz[0] + probeY] - 0.005 <= n.val && score[probeX*sz[0] + probeY] + 0.005 >= n.val) { success = true; delete [] score; break; } delete[] score; } // Record the rule index used (same as model "component" for mixtures of // star models) info[DET_IND] = r; // Record a detection window for the start symbol if (n.symbol == startSymbol) { // Get detection window for startSymbol and rule r detwin = symRules.structure[r].getDetwindow(); // Detection scale scale = model->getSbin()/scales[n.l]; // Compute and record image coordinates of the detection window x1 = cvRound((n.x-padX*pow2(n.ds))*scale); y1 = cvRound((n.y-padY*pow2(n.ds))*scale); x2 = cvRound(x1 + detwin[1]*scale - 1); y2 = cvRound(y1 + detwin[0]*scale - 1); dets[detsdim[0]*0] = x1 + 1; dets[detsdim[0]*1] = y1 + 1; dets[detsdim[0]*2] = x2 + 1; dets[detsdim[0]*3] = y2 + 1; dets[detsdim[0]*4] = r + 1; dets[detsdim[0]*5] = n.val; boxes[boxesdim[0]*(boxesdim[1]-2)] = r + 1; boxes[boxesdim[0]*(boxesdim[1]-1)] = n.val; info[DET_X] = n.x + 1; info[DET_Y] = n.y + 1; info[DET_L] = n.l + 1; info[DET_DS] = n.ds; } // Push rhs symbols from the selected rule type = symRules.structure[r].getType(); rhs = symRules.structure[r].getRhs(); rhsDim = symRules.structure[r].getRhsDim(); if (type == 'S') { // Structural rule for (int j = 0; j < rhsDim; j++) { anch = symRules.structure[r].getAnchor()[j]; ax = (int) anch.array[0]; ay = (int) anch.array[1]; ds = (int) anch.array[2]; // Compute location of the rhs symbol px = n.x * pow2(ds) + ax; py = n.y * pow2(ds) + ay; pl = n.l - (interval + 1) * ds; probeX = px - virtpadding(padX, n.ds+ds); // Remove virtual padding for to compute the probe location in the // score table probeY = py - virtpadding(padY, n.ds+ds); push(n, cur, probeX, probeY, px, py, pl, ds, rhs, j); } } else { // Deformation rule (only 1 rhs symbol) cv::Mat tmpMxIx; tmpMxIx = symRules.structure[r].getIx()[n.l]; CvMat mxIx2 = tmpMxIx; mxIx = &mxIx2; cv::Mat tmpMxIy; tmpMxIy = symRules.structure[r].getIy()[n.l]; CvMat mxIy2 = tmpMxIy; mxIy = &mxIy2; Ix = new int [mxIx->rows * mxIx->cols]; getMatData <int> (mxIx, Ix); Iy = new int [mxIy->rows * mxIy->cols]; getMatData <int> (mxIy, Iy); getDimensions (mxIx, isz); px = n.x; py = n.y; // Probe location for looking up displacement of rhs symbol probeX = n.x - virtpadding(padX, n.ds); probeY = n.y - virtpadding(padY, n.ds); // Probe location for accessing the score of the rhs symbol probeX2 = probeX; probeY2 = probeY; // If the probe location is in the feature pyramid retrieve the // deformation location from Ix and Iy // subtract 1 because Ix/Iy use 1-based indexing // *NOTE: Ix and Iy has values -1 yet px = Ix[probeX*isz[0] + probeY] + virtpadding(padX, n.ds); py = Iy[probeX*isz[0] + probeY] + virtpadding(padY, n.ds); // Remove virtual padding for score look up probeX2 = Ix[probeX*isz[0] + probeY]; probeY2 = Iy[probeX*isz[0] + probeY]; push(n, cur, probeX2, probeY2, px, py, n.l, 0, rhs, 0); // save detection information info[DET_X] = px + 1; // actual location (x) info[DET_Y] = py + 1; // actual location (y) info[DET_PX] = n.x + 1; // Ix probe location info[DET_PY] = n.y + 1; // Iy probe location delete[] Ix; delete[] Iy; } } }
void RenderableModelEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RMEIrender"); assert(getType() == EntityTypes::Model); bool drawAsModel = hasModel(); glm::vec3 position = getPosition() * (float)TREE_SCALE; float size = getSize() * (float)TREE_SCALE; glm::vec3 dimensions = getDimensions() * (float)TREE_SCALE; if (drawAsModel) { glPushMatrix(); { float alpha = getLocalRenderAlpha(); if (!_model || _needsModelReload) { // TODO: this getModel() appears to be about 3% of model render time. We should optimize PerformanceTimer perfTimer("getModel"); EntityTreeRenderer* renderer = static_cast<EntityTreeRenderer*>(args->_renderer); getModel(renderer); } if (_model) { // handle animations.. if (hasAnimation()) { if (!jointsMapped()) { QStringList modelJointNames = _model->getJointNames(); mapJoints(modelJointNames); } if (jointsMapped()) { QVector<glm::quat> frameData = getAnimationFrame(); for (int i = 0; i < frameData.size(); i++) { _model->setJointState(i, true, frameData[i]); } } } glm::quat rotation = getRotation(); if (needsSimulation() && _model->isActive()) { _model->setScaleToFit(true, dimensions); _model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); _model->setRotation(rotation); _model->setTranslation(position); // make sure to simulate so everything gets set up correctly for rendering { PerformanceTimer perfTimer("_model->simulate"); _model->simulate(0.0f); } _needsInitialSimulation = false; } // TODO: should we allow entityItems to have alpha on their models? Model::RenderMode modelRenderMode = args->_renderMode == OctreeRenderer::SHADOW_RENDER_MODE ? Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE; if (_model->isActive()) { // TODO: this is the majority of model render time. And rendering of a cube model vs the basic Box render // is significantly more expensive. Is there a way to call this that doesn't cost us as much? PerformanceTimer perfTimer("model->render"); _model->render(alpha, modelRenderMode, args); } else { // if we couldn't get a model, then just draw a cube glColor3ub(getColor()[RED_INDEX],getColor()[GREEN_INDEX],getColor()[BLUE_INDEX]); glPushMatrix(); glTranslatef(position.x, position.y, position.z); Application::getInstance()->getDeferredLightingEffect()->renderWireCube(size); glPopMatrix(); } } else { // if we couldn't get a model, then just draw a cube glColor3ub(getColor()[RED_INDEX],getColor()[GREEN_INDEX],getColor()[BLUE_INDEX]); glPushMatrix(); glTranslatef(position.x, position.y, position.z); Application::getInstance()->getDeferredLightingEffect()->renderWireCube(size); glPopMatrix(); } } glPopMatrix(); } else { glColor3ub(getColor()[RED_INDEX],getColor()[GREEN_INDEX],getColor()[BLUE_INDEX]); glPushMatrix(); glTranslatef(position.x, position.y, position.z); Application::getInstance()->getDeferredLightingEffect()->renderWireCube(size); glPopMatrix(); } }
void Button::draw() { Color *color; if(mHover && !mPressed) color = &mSelectedColor; else color = &mBackColor; /*mpBuffer->fill(*color); //Draw outline. mpBuffer->drawRect(Vec2d(0,0), mpBuffer->getDimensions()-2, mForeColor, 2.0); //Draw button caption. mpBuffer->writeText(mText,(getDimensions() - mTextDimensions)/2, *mpFont, mForeColor);*/ glPushMatrix(); glTranslatef(mPosition.X(), mPosition.Y(), 0); //*********** //Draw button. //*********** glBegin(GL_QUADS); color->setActiveColor(); glVertex2f(0,0); glVertex2f(mDimensions.X(), 0); glVertex2f(mDimensions.X(), mDimensions.Y()); glVertex2f(0, mDimensions.Y()); glEnd(); //************ //Draw outline //************ glBegin(GL_LINES); //Set line width to 2.0. glLineWidth(2.0f); mForeColor.setActiveColor(); glVertex2f(0,0); glVertex2f(mDimensions.X(), 0); glVertex2f(mDimensions.X(), 0); glVertex2f(mDimensions.X(), mDimensions.Y()); glVertex2f(mDimensions.X(), mDimensions.Y()); glVertex2f(0, mDimensions.Y()); glVertex2f(0, mDimensions.Y()); glVertex2f(0,0); glEnd(); glPopMatrix(); /*glPushMatrix(); Vec2d center = (getDimensions() - mTextDimensions)/2; glTranslatef(center.X(), center.Y(), 0); mpFont->print(mText.c_str()); glPopMatrix();*/ Vec2d center = mPosition + (getDimensions() - mTextDimensions)/2; mpFont->print(mText, center.X(), center.Y()); //mpBuffer->draw(buffer,mPosition); }
void BillboardOverlay::render(RenderArgs* args) { if (!_isLoaded) { _isLoaded = true; _texture = DependencyManager::get<TextureCache>()->getTexture(_url); } if (!_visible || !_texture->isLoaded()) { return; } glm::quat rotation; if (_isFacingAvatar) { // rotate about vertical to face the camera rotation = args->_viewFrustum->getOrientation(); rotation *= glm::angleAxis(glm::pi<float>(), IDENTITY_UP); rotation *= getRotation(); } else { rotation = getRotation(); } float imageWidth = _texture->getWidth(); float imageHeight = _texture->getHeight(); QRect fromImage; if (_fromImage.isNull()) { fromImage.setX(0); fromImage.setY(0); fromImage.setWidth(imageWidth); fromImage.setHeight(imageHeight); } else { float scaleX = imageWidth / _texture->getOriginalWidth(); float scaleY = imageHeight / _texture->getOriginalHeight(); fromImage.setX(scaleX * _fromImage.x()); fromImage.setY(scaleY * _fromImage.y()); fromImage.setWidth(scaleX * _fromImage.width()); fromImage.setHeight(scaleY * _fromImage.height()); } float maxSize = glm::max(fromImage.width(), fromImage.height()); float x = fromImage.width() / (2.0f * maxSize); float y = -fromImage.height() / (2.0f * maxSize); glm::vec2 topLeft(-x, -y); glm::vec2 bottomRight(x, y); glm::vec2 texCoordTopLeft(fromImage.x() / imageWidth, fromImage.y() / imageHeight); glm::vec2 texCoordBottomRight((fromImage.x() + fromImage.width()) / imageWidth, (fromImage.y() + fromImage.height()) / imageHeight); const float MAX_COLOR = 255.0f; xColor color = getColor(); float alpha = getAlpha(); auto batch = args->_batch; if (batch) { Transform transform = _transform; transform.postScale(glm::vec3(getDimensions(), 1.0f)); batch->setModelTransform(transform); batch->setUniformTexture(0, _texture->getGPUTexture()); DependencyManager::get<GeometryCache>()->renderQuad(*batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, glm::vec4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha)); batch->setUniformTexture(0, args->_whiteTexture); // restore default white color after me } else { glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.5f); glEnable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); glBindTexture(GL_TEXTURE_2D, _texture->getID()); glPushMatrix(); { glTranslatef(getPosition().x, getPosition().y, getPosition().z); glm::vec3 axis = glm::axis(rotation); glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); glScalef(_dimensions.x, _dimensions.y, 1.0f); DependencyManager::get<GeometryCache>()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, glm::vec4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha)); } glPopMatrix(); glDisable(GL_TEXTURE_2D); glEnable(GL_LIGHTING); glDisable(GL_ALPHA_TEST); glBindTexture(GL_TEXTURE_2D, 0); } }
void Text3DOverlay::render(RenderArgs* args) { if (!_visible) { return; // do nothing if we're not visible } glPushMatrix(); { glTranslatef(_position.x, _position.y, _position.z); glm::quat rotation; if (_isFacingAvatar) { // rotate about vertical to face the camera rotation = Application::getInstance()->getCamera()->getRotation(); } else { rotation = getRotation(); } glm::vec3 axis = glm::axis(rotation); glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); const float MAX_COLOR = 255.0f; xColor backgroundColor = getBackgroundColor(); glColor4f(backgroundColor.red / MAX_COLOR, backgroundColor.green / MAX_COLOR, backgroundColor.blue / MAX_COLOR, getBackgroundAlpha()); glm::vec2 dimensions = getDimensions(); glm::vec2 halfDimensions = dimensions * 0.5f; const float SLIGHTLY_BEHIND = -0.005f; glBegin(GL_QUADS); glVertex3f(-halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND); glVertex3f(halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND); glVertex3f(halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND); glVertex3f(-halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND); glEnd(); const int FIXED_FONT_SCALING_RATIO = FIXED_FONT_POINT_SIZE * 40.0f; // this is a ratio determined through experimentation // Same font properties as textWidth() TextRenderer* textRenderer = TextRenderer::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE); float maxHeight = (float)textRenderer->calculateHeight("Xy") * LINE_SCALE_RATIO; float scaleFactor = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight; glTranslatef(-(halfDimensions.x - _leftMargin), halfDimensions.y - _topMargin, 0.0f); glm::vec2 clipMinimum(0.0f, 0.0f); glm::vec2 clipDimensions((dimensions.x - (_leftMargin + _rightMargin)) / scaleFactor, (dimensions.y - (_topMargin + _bottomMargin)) / scaleFactor); glScalef(scaleFactor, -scaleFactor, 1.0); enableClipPlane(GL_CLIP_PLANE0, -1.0f, 0.0f, 0.0f, clipMinimum.x + clipDimensions.x); enableClipPlane(GL_CLIP_PLANE1, 1.0f, 0.0f, 0.0f, -clipMinimum.x); enableClipPlane(GL_CLIP_PLANE2, 0.0f, -1.0f, 0.0f, clipMinimum.y + clipDimensions.y); enableClipPlane(GL_CLIP_PLANE3, 0.0f, 1.0f, 0.0f, -clipMinimum.y); glColor3f(_color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR); float alpha = getAlpha(); QStringList lines = _text.split("\n"); int lineOffset = maxHeight; foreach(QString thisLine, lines) { textRenderer->draw(0, lineOffset, qPrintable(thisLine), alpha); lineOffset += maxHeight; } glDisable(GL_CLIP_PLANE0); glDisable(GL_CLIP_PLANE1); glDisable(GL_CLIP_PLANE2); glDisable(GL_CLIP_PLANE3); } glPopMatrix();
bool RenderableWebEntityItem::buildWebSurface(EntityTreeRenderer* renderer) { if (_currentWebCount >= MAX_CONCURRENT_WEB_VIEWS) { qWarning() << "Too many concurrent web views to create new view"; return false; } qDebug() << "Building web surface"; ++_currentWebCount; // Save the original GL context, because creating a QML surface will create a new context QOpenGLContext * currentContext = QOpenGLContext::currentContext(); QSurface * currentSurface = currentContext->surface(); _webSurface = new OffscreenQmlSurface(); _webSurface->create(currentContext); _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/")); _webSurface->load("WebEntity.qml"); _webSurface->resume(); _webSurface->getRootItem()->setProperty("url", _sourceUrl); _connection = QObject::connect(_webSurface, &OffscreenQmlSurface::textureUpdated, [&](GLuint textureId) { _texture = textureId; }); // Restore the original GL context currentContext->makeCurrent(currentSurface); auto forwardMouseEvent = [=](const RayToEntityIntersectionResult& intersection, const QMouseEvent* event) { // Ignore mouse interaction if we're locked if (this->getLocked()) { return; } if (event->button() == Qt::MouseButton::RightButton) { if (event->type() == QEvent::MouseButtonPress) { const QMouseEvent* mouseEvent = static_cast<const QMouseEvent*>(event); _lastPress = toGlm(mouseEvent->pos()); } } if (intersection.entityID == getID()) { if (event->button() == Qt::MouseButton::RightButton) { if (event->type() == QEvent::MouseButtonRelease) { const QMouseEvent* mouseEvent = static_cast<const QMouseEvent*>(event); ivec2 dist = glm::abs(toGlm(mouseEvent->pos()) - _lastPress); if (!glm::any(glm::greaterThan(dist, ivec2(1)))) { AbstractViewStateInterface::instance()->postLambdaEvent([this] { QMetaObject::invokeMethod(_webSurface->getRootItem(), "goBack"); }); } _lastPress = ivec2(INT_MIN); } return; } // FIXME doesn't work... double click events not received if (event->type() == QEvent::MouseButtonDblClick) { AbstractViewStateInterface::instance()->postLambdaEvent([this] { _webSurface->getRootItem()->setProperty("url", _sourceUrl); }); } if (event->button() == Qt::MouseButton::MiddleButton) { if (event->type() == QEvent::MouseButtonRelease) { AbstractViewStateInterface::instance()->postLambdaEvent([this] { _webSurface->getRootItem()->setProperty("url", _sourceUrl); }); } return; } // Map the intersection point to an actual offscreen pixel glm::vec3 point = intersection.intersection; glm::vec3 dimensions = getDimensions(); point -= getPosition(); point = glm::inverse(getRotation()) * point; point /= dimensions; point += 0.5f; point.y = 1.0f - point.y; point *= dimensions * (METERS_TO_INCHES * DPI); if (event->button() == Qt::MouseButton::LeftButton) { if (event->type() == QEvent::MouseButtonPress) { this->_pressed = true; this->_lastMove = ivec2((int)point.x, (int)point.y); } else if (event->type() == QEvent::MouseButtonRelease) { this->_pressed = false; } } if (event->type() == QEvent::MouseMove) { this->_lastMove = ivec2((int)point.x, (int)point.y); } // Forward the mouse event. QMouseEvent mappedEvent(event->type(), QPoint((int)point.x, (int)point.y), event->screenPos(), event->button(), event->buttons(), event->modifiers()); QCoreApplication::sendEvent(_webSurface->getWindow(), &mappedEvent); } }; _mousePressConnection = QObject::connect(renderer, &EntityTreeRenderer::mousePressOnEntity, forwardMouseEvent); _mouseReleaseConnection = QObject::connect(renderer, &EntityTreeRenderer::mouseReleaseOnEntity, forwardMouseEvent); _mouseMoveConnection = QObject::connect(renderer, &EntityTreeRenderer::mouseMoveOnEntity, forwardMouseEvent); _hoverLeaveConnection = QObject::connect(renderer, &EntityTreeRenderer::hoverLeaveEntity, [=](const EntityItemID& entityItemID, const MouseEvent& event) { if (this->_pressed && this->getID() == entityItemID) { // If the user mouses off the entity while the button is down, simulate a mouse release QMouseEvent mappedEvent(QEvent::MouseButtonRelease, QPoint(_lastMove.x, _lastMove.y), Qt::MouseButton::LeftButton, Qt::MouseButtons(), Qt::KeyboardModifiers()); QCoreApplication::sendEvent(_webSurface->getWindow(), &mappedEvent); } }); return true; }
inline int getHeight() const { return getDimensions().y; }
OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packetData, EncodeBitstreamParams& params, EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData) const { // ALL this fits... // object ID [16 bytes] // ByteCountCoded(type code) [~1 byte] // last edited [8 bytes] // ByteCountCoded(last_edited to last_updated delta) [~1-8 bytes] // PropertyFlags<>( everything ) [1-2 bytes] // ~27-35 bytes... OctreeElement::AppendState appendState = OctreeElement::COMPLETED; // assume the best // encode our ID as a byte count coded byte stream QByteArray encodedID = getID().toRfc4122(); // encode our type as a byte count coded byte stream ByteCountCoded<quint32> typeCoder = getType(); QByteArray encodedType = typeCoder; quint64 updateDelta = getLastUpdated() <= getLastEdited() ? 0 : getLastUpdated() - getLastEdited(); ByteCountCoded<quint64> updateDeltaCoder = updateDelta; QByteArray encodedUpdateDelta = updateDeltaCoder; EntityPropertyFlags propertyFlags(PROP_LAST_ITEM); EntityPropertyFlags requestedProperties = getEntityProperties(params); EntityPropertyFlags propertiesDidntFit = requestedProperties; // If we are being called for a subsequent pass at appendEntityData() that failed to completely encode this item, // then our entityTreeElementExtraEncodeData should include data about which properties we need to append. if (entityTreeElementExtraEncodeData && entityTreeElementExtraEncodeData->entities.contains(getEntityItemID())) { requestedProperties = entityTreeElementExtraEncodeData->entities.value(getEntityItemID()); } LevelDetails entityLevel = packetData->startLevel(); quint64 lastEdited = getLastEdited(); const bool wantDebug = false; if (wantDebug) { float editedAgo = getEditedAgo(); QString agoAsString = formatSecondsElapsed(editedAgo); qDebug() << "Writing entity " << getEntityItemID() << " to buffer, lastEdited =" << lastEdited << " ago=" << editedAgo << "seconds - " << agoAsString; } bool successIDFits = false; bool successTypeFits = false; bool successCreatedFits = false; bool successLastEditedFits = false; bool successLastUpdatedFits = false; bool successPropertyFlagsFits = false; int propertyFlagsOffset = 0; int oldPropertyFlagsLength = 0; QByteArray encodedPropertyFlags; int propertyCount = 0; successIDFits = packetData->appendValue(encodedID); if (successIDFits) { successTypeFits = packetData->appendValue(encodedType); } if (successTypeFits) { successCreatedFits = packetData->appendValue(_created); } if (successCreatedFits) { successLastEditedFits = packetData->appendValue(lastEdited); } if (successLastEditedFits) { successLastUpdatedFits = packetData->appendValue(encodedUpdateDelta); } if (successLastUpdatedFits) { propertyFlagsOffset = packetData->getUncompressedByteOffset(); encodedPropertyFlags = propertyFlags; oldPropertyFlagsLength = encodedPropertyFlags.length(); successPropertyFlagsFits = packetData->appendValue(encodedPropertyFlags); } bool headerFits = successIDFits && successTypeFits && successCreatedFits && successLastEditedFits && successLastUpdatedFits && successPropertyFlagsFits; int startOfEntityItemData = packetData->getUncompressedByteOffset(); if (headerFits) { bool successPropertyFits; propertyFlags -= PROP_LAST_ITEM; // clear the last item for now, we may or may not set it as the actual item // These items would go here once supported.... // PROP_PAGED_PROPERTY, // PROP_CUSTOM_PROPERTIES_INCLUDED, APPEND_ENTITY_PROPERTY(PROP_POSITION, appendPosition, getPosition()); APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, appendValue, getDimensions()); // NOTE: PROP_RADIUS obsolete if (wantDebug) { qDebug() << " APPEND_ENTITY_PROPERTY() PROP_DIMENSIONS:" << getDimensions(); } APPEND_ENTITY_PROPERTY(PROP_ROTATION, appendValue, getRotation()); APPEND_ENTITY_PROPERTY(PROP_MASS, appendValue, getMass()); APPEND_ENTITY_PROPERTY(PROP_VELOCITY, appendValue, getVelocity()); APPEND_ENTITY_PROPERTY(PROP_GRAVITY, appendValue, getGravity()); APPEND_ENTITY_PROPERTY(PROP_DAMPING, appendValue, getDamping()); APPEND_ENTITY_PROPERTY(PROP_LIFETIME, appendValue, getLifetime()); APPEND_ENTITY_PROPERTY(PROP_SCRIPT, appendValue, getScript()); APPEND_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, appendValue, getRegistrationPoint()); APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, appendValue, getAngularVelocity()); APPEND_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, appendValue, getAngularDamping()); APPEND_ENTITY_PROPERTY(PROP_VISIBLE, appendValue, getVisible()); APPEND_ENTITY_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, appendValue, getIgnoreForCollisions()); APPEND_ENTITY_PROPERTY(PROP_COLLISIONS_WILL_MOVE, appendValue, getCollisionsWillMove()); appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); } if (propertyCount > 0) { int endOfEntityItemData = packetData->getUncompressedByteOffset(); encodedPropertyFlags = propertyFlags; int newPropertyFlagsLength = encodedPropertyFlags.length(); packetData->updatePriorBytes(propertyFlagsOffset, (const unsigned char*)encodedPropertyFlags.constData(), encodedPropertyFlags.length()); // if the size of the PropertyFlags shrunk, we need to shift everything down to front of packet. if (newPropertyFlagsLength < oldPropertyFlagsLength) { int oldSize = packetData->getUncompressedSize(); const unsigned char* modelItemData = packetData->getUncompressedData(propertyFlagsOffset + oldPropertyFlagsLength); int modelItemDataLength = endOfEntityItemData - startOfEntityItemData; int newEntityItemDataStart = propertyFlagsOffset + newPropertyFlagsLength; packetData->updatePriorBytes(newEntityItemDataStart, modelItemData, modelItemDataLength); int newSize = oldSize - (oldPropertyFlagsLength - newPropertyFlagsLength); packetData->setUncompressedSize(newSize); } else { assert(newPropertyFlagsLength == oldPropertyFlagsLength); // should not have grown } packetData->endLevel(entityLevel); } else { packetData->discardLevel(entityLevel); appendState = OctreeElement::NONE; // if we got here, then we didn't include the item } // If any part of the model items didn't fit, then the element is considered partial if (appendState != OctreeElement::COMPLETED) { // add this item into our list for the next appendElementData() pass entityTreeElementExtraEncodeData->entities.insert(getEntityItemID(), propertiesDidntFit); } return appendState; }
virtual Vector2 getExtends() const { Vector2 ret = getDimensions(); ret = ret / 2; // cout << "Extends: " << ret << endl; return ret; }
void Cube3DOverlay::render(RenderArgs* args) { if (!_visible) { return; // do nothing if we're not visible } float alpha = getAlpha(); xColor color = getColor(); const float MAX_COLOR = 255.0f; glm::vec4 cubeColor(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha); // TODO: handle registration point?? glm::vec3 position = getPosition(); glm::vec3 dimensions = getDimensions(); glm::quat rotation = getRotation(); auto batch = args->_batch; if (batch) { Transform transform; transform.setTranslation(position); transform.setRotation(rotation); if (_isSolid) { // if (_borderSize > 0) { // // Draw a cube at a larger size behind the main cube, creating // // a border effect. // // Disable writing to the depth mask so that the "border" cube will not // // occlude the main cube. This means the border could be covered by // // overlays that are further back and drawn later, but this is good // // enough for the use-case. // transform.setScale(dimensions * _borderSize); // batch->setModelTransform(transform); // DependencyManager::get<GeometryCache>()->renderSolidCube(*batch, 1.0f, glm::vec4(1.0f, 1.0f, 1.0f, alpha)); // } transform.setScale(dimensions); batch->setModelTransform(transform); DependencyManager::get<GeometryCache>()->renderSolidCube(*batch, 1.0f, cubeColor); } else { if (getIsDashedLine()) { transform.setScale(1.0f); batch->setModelTransform(transform); glm::vec3 halfDimensions = dimensions / 2.0f; glm::vec3 bottomLeftNear(-halfDimensions.x, -halfDimensions.y, -halfDimensions.z); glm::vec3 bottomRightNear(halfDimensions.x, -halfDimensions.y, -halfDimensions.z); glm::vec3 topLeftNear(-halfDimensions.x, halfDimensions.y, -halfDimensions.z); glm::vec3 topRightNear(halfDimensions.x, halfDimensions.y, -halfDimensions.z); glm::vec3 bottomLeftFar(-halfDimensions.x, -halfDimensions.y, halfDimensions.z); glm::vec3 bottomRightFar(halfDimensions.x, -halfDimensions.y, halfDimensions.z); glm::vec3 topLeftFar(-halfDimensions.x, halfDimensions.y, halfDimensions.z); glm::vec3 topRightFar(halfDimensions.x, halfDimensions.y, halfDimensions.z); auto geometryCache = DependencyManager::get<GeometryCache>(); geometryCache->renderDashedLine(*batch, bottomLeftNear, bottomRightNear, cubeColor); geometryCache->renderDashedLine(*batch, bottomRightNear, bottomRightFar, cubeColor); geometryCache->renderDashedLine(*batch, bottomRightFar, bottomLeftFar, cubeColor); geometryCache->renderDashedLine(*batch, bottomLeftFar, bottomLeftNear, cubeColor); geometryCache->renderDashedLine(*batch, topLeftNear, topRightNear, cubeColor); geometryCache->renderDashedLine(*batch, topRightNear, topRightFar, cubeColor); geometryCache->renderDashedLine(*batch, topRightFar, topLeftFar, cubeColor); geometryCache->renderDashedLine(*batch, topLeftFar, topLeftNear, cubeColor); geometryCache->renderDashedLine(*batch, bottomLeftNear, topLeftNear, cubeColor); geometryCache->renderDashedLine(*batch, bottomRightNear, topRightNear, cubeColor); geometryCache->renderDashedLine(*batch, bottomLeftFar, topLeftFar, cubeColor); geometryCache->renderDashedLine(*batch, bottomRightFar, topRightFar, cubeColor); } else { transform.setScale(dimensions); batch->setModelTransform(transform); DependencyManager::get<DeferredLightingEffect>()->renderWireCube(*batch, 1.0f, cubeColor); } } } }