// protected void EntitySimulation::sortEntitiesThatMoved() { // NOTE: this is only for entities that have been moved by THIS EntitySimulation. // External changes to entity position/shape are expected to be sorted outside of the EntitySimulation. PerformanceTimer perfTimer("sortingEntities"); MovingEntitiesOperator moveOperator(_entityTree); AACube domainBounds(glm::vec3(0.0f,0.0f,0.0f), (float)TREE_SCALE); SetOfEntities::iterator itemItr = _entitiesToSort.begin(); while (itemItr != _entitiesToSort.end()) { EntityItemPointer entity = *itemItr; // check to see if this movement has sent the entity outside of the domain. AACube newCube = entity->getMaximumAACube(); if (!domainBounds.touches(newCube)) { qCDebug(entities) << "Entity " << entity->getEntityItemID() << " moved out of domain bounds."; _entitiesToDelete.insert(entity); _mortalEntities.remove(entity); _entitiesToUpdate.remove(entity); _simpleKinematicEntities.remove(entity); removeEntityInternal(entity); _allEntities.remove(entity); entity->_simulated = false; itemItr = _entitiesToSort.erase(itemItr); } else { moveOperator.addEntityToMoveList(entity, newCube); ++itemItr; } } if (moveOperator.hasMovingEntities()) { PerformanceTimer perfTimer("recurseTreeWithOperator"); _entityTree->recurseTreeWithOperator(&moveOperator); } _entitiesToSort.clear(); }
// protected void EntitySimulation::sortEntitiesThatMoved() { QMutexLocker lock(&_mutex); // NOTE: this is only for entities that have been moved by THIS EntitySimulation. // External changes to entity position/shape are expected to be sorted outside of the EntitySimulation. PerformanceTimer perfTimer("sortingEntities"); MovingEntitiesOperator moveOperator(_entityTree); AACube domainBounds(glm::vec3((float)-HALF_TREE_SCALE), (float)TREE_SCALE); SetOfEntities::iterator itemItr = _entitiesToSort.begin(); while (itemItr != _entitiesToSort.end()) { EntityItemPointer entity = *itemItr; // check to see if this movement has sent the entity outside of the domain. bool success; AACube newCube = entity->getQueryAACube(success); if (success && !domainBounds.touches(newCube)) { qCDebug(entities) << "Entity " << entity->getEntityItemID() << " moved out of domain bounds."; itemItr = _entitiesToSort.erase(itemItr); entity->die(); prepareEntityForDelete(entity); } else { moveOperator.addEntityToMoveList(entity, newCube); ++itemItr; } } if (moveOperator.hasMovingEntities()) { PerformanceTimer perfTimer("recurseTreeWithOperator"); _entityTree->recurseTreeWithOperator(&moveOperator); } _entitiesToSort.clear(); }
// TODO: we need a solution for changes to the postion/rotation/etc of a model... // this current code path only addresses that in this setup case... not the changing/moving case bool RenderableModelEntityItem::readyToAddToScene(RenderArgs* renderArgs) { if (!_model && renderArgs) { // TODO: this getModel() appears to be about 3% of model render time. We should optimize PerformanceTimer perfTimer("getModel"); EntityTreeRenderer* renderer = static_cast<EntityTreeRenderer*>(renderArgs->_renderer); getModel(renderer); } if (renderArgs && _model && _needsInitialSimulation && _model->isActive() && _model->isLoaded()) { _model->setScaleToFit(true, getDimensions()); _model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); _model->setRotation(getRotation()); _model->setTranslation(getPosition()); // make sure to simulate so everything gets set up correctly for rendering { PerformanceTimer perfTimer("_model->simulate"); _model->simulate(0.0f); } _needsInitialSimulation = false; _model->renderSetup(renderArgs); } bool ready = !_needsInitialSimulation && _model && _model->readyToAddToScene(renderArgs); return ready; }
void RenderableZoneEntityItem::render(RenderArgs* args) { Q_ASSERT(getType() == EntityTypes::Zone); if (_drawZoneBoundaries) { switch (getShapeType()) { case SHAPE_TYPE_COMPOUND: { PerformanceTimer perfTimer("zone->renderCompound"); updateGeometry(); if (_model && _model->needsFixupInScene()) { // check to see if when we added our models to the scene they were ready, if they were not ready, then // fix them up in the scene render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); render::PendingChanges pendingChanges; _model->removeFromScene(scene, pendingChanges); _model->addToScene(scene, pendingChanges); scene->enqueuePendingChanges(pendingChanges); _model->setVisibleInScene(getVisible(), scene); } break; } case SHAPE_TYPE_BOX: case SHAPE_TYPE_SPHERE: { PerformanceTimer perfTimer("zone->renderPrimitive"); glm::vec4 DEFAULT_COLOR(1.0f, 1.0f, 1.0f, 1.0f); Q_ASSERT(args->_batch); gpu::Batch& batch = *args->_batch; batch.setModelTransform(getTransformToCenter()); auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>(); if (getShapeType() == SHAPE_TYPE_SPHERE) { const int SLICES = 15, STACKS = 15; deferredLightingEffect->renderWireSphere(batch, 0.5f, SLICES, STACKS, DEFAULT_COLOR); } else { deferredLightingEffect->renderWireCube(batch, 1.0f, DEFAULT_COLOR); } break; } default: // Not handled break; } } if ((!_drawZoneBoundaries || getShapeType() != SHAPE_TYPE_COMPOUND) && _model && !_model->needsFixupInScene()) { // If the model is in the scene but doesn't need to be, remove it. render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); render::PendingChanges pendingChanges; _model->removeFromScene(scene, pendingChanges); scene->enqueuePendingChanges(pendingChanges); } }
void RenderableZoneEntityItem::render(RenderArgs* args) { if (_drawZoneBoundaries) { switch (getShapeType()) { case SHAPE_TYPE_COMPOUND: { updateGeometry(); if (_model && _model->isActive()) { PerformanceTimer perfTimer("zone->renderCompound"); glPushMatrix(); _model->renderInScene(getLocalRenderAlpha(), args); glPopMatrix(); } break; } case SHAPE_TYPE_BOX: case SHAPE_TYPE_SPHERE: { PerformanceTimer perfTimer("zone->renderPrimitive"); glm::vec3 position = getPosition(); glm::vec3 center = getCenter(); glm::vec3 dimensions = getDimensions(); glm::quat rotation = getRotation(); glm::vec4 DEFAULT_COLOR(1.0f, 1.0f, 1.0f, getLocalRenderAlpha()); glPushMatrix(); { glTranslatef(position.x, position.y, position.z); glm::vec3 axis = glm::axis(rotation); glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); glPushMatrix(); { glm::vec3 positionToCenter = center - position; glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); glScalef(dimensions.x, dimensions.y, dimensions.z); auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>(); if (getShapeType() == SHAPE_TYPE_SPHERE) { const int SLICES = 15; const int STACKS = 15; deferredLightingEffect->renderWireSphere(0.5f, SLICES, STACKS, DEFAULT_COLOR); } else { deferredLightingEffect->renderWireCube(1.0f, DEFAULT_COLOR); } } glPopMatrix(); } glPopMatrix(); break; } default: // Not handled break; } } }
void PhysicsSimulation::stepForward(float deltaTime, float minError, int maxIterations, quint64 maxUsec) { ++_frameCount; if (!_ragdoll) { return; } quint64 now = usecTimestampNow(); quint64 startTime = now; quint64 expiry = startTime + maxUsec; moveRagdolls(deltaTime); enforceContacts(); int numDolls = _otherRagdolls.size(); { PerformanceTimer perfTimer("enforce"); _ragdoll->enforceConstraints(); for (int i = 0; i < numDolls; ++i) { _otherRagdolls[i]->enforceConstraints(); } } bool collidedWithOtherRagdoll = false; int iterations = 0; float error = 0.0f; do { collidedWithOtherRagdoll = computeCollisions() || collidedWithOtherRagdoll; updateContacts(); resolveCollisions(); { // enforce constraints PerformanceTimer perfTimer("enforce"); error = _ragdoll->enforceConstraints(); for (int i = 0; i < numDolls; ++i) { error = glm::max(error, _otherRagdolls[i]->enforceConstraints()); } } applyContactFriction(); ++iterations; now = usecTimestampNow(); } while (_collisions.size() != 0 && (iterations < maxIterations) && (error > minError) && (now < expiry)); // the collisions may have moved the main ragdoll from the simulation center // so we remove this offset (potentially storing it as movement of the Ragdoll owner) _ragdoll->removeRootOffset(collidedWithOtherRagdoll); // also remove any offsets from the other ragdolls for (int i = 0; i < numDolls; ++i) { _otherRagdolls[i]->removeRootOffset(false); } pruneContacts(); }
void RenderableLightEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableLightEntityItem::render"); assert(getType() == EntityTypes::Light); glm::vec3 position = getPosition(); glm::vec3 dimensions = getDimensions(); glm::quat rotation = getRotation(); float largestDiameter = glm::max(dimensions.x, dimensions.y, dimensions.z); glm::vec3 color = toGlm(getXColor()); float intensity = getIntensity(); float exponent = getExponent(); float cutoff = glm::radians(getCutoff()); if (_isSpotlight) { DependencyManager::get<DeferredLightingEffect>()->addSpotLight(position, largestDiameter / 2.0f, color, intensity, rotation, exponent, cutoff); } else { DependencyManager::get<DeferredLightingEffect>()->addPointLight(position, largestDiameter / 2.0f, color, intensity); } #ifdef WANT_DEBUG Q_ASSERT(args->_batch); gpu::Batch& batch = *args->_batch; batch.setModelTransform(getTransformToCenter()); DependencyManager::get<GeometryCache>()->renderWireSphere(batch, 0.5f, 15, 15, glm::vec4(color, 1.0f)); #endif };
void RenderableBoxEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableBoxEntityItem::render"); Q_ASSERT(getType() == EntityTypes::Box); Q_ASSERT(args->_batch); if (!_procedural) { _procedural.reset(new Procedural(this->getUserData())); _procedural->_vertexSource = simple_vert; _procedural->_fragmentSource = simple_frag; _procedural->_state->setCullMode(gpu::State::CULL_NONE); _procedural->_state->setDepthTest(true, true, gpu::LESS_EQUAL); _procedural->_state->setBlendFunction(false, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); } gpu::Batch& batch = *args->_batch; glm::vec4 cubeColor(toGlm(getXColor()), getLocalRenderAlpha()); if (_procedural->ready()) { batch.setModelTransform(getTransformToCenter()); // we want to include the scale as well _procedural->prepare(batch, this->getDimensions()); auto color = _procedural->getColor(cubeColor); batch._glColor4f(color.r, color.g, color.b, color.a); DependencyManager::get<GeometryCache>()->renderCube(batch); } else { DependencyManager::get<DeferredLightingEffect>()->renderSolidCubeInstance(batch, getTransformToCenter(), cubeColor); } RenderableDebugableEntityItem::render(this, args); };
void RenderablePolyLineEntityItem::render(RenderArgs* args) { QWriteLocker lock(&_quadReadWriteLock); if (_points.size() < 2 || _normals.size () < 2 || _vertices.size() < 2) { return; } if (!_pipeline) { createPipeline(); } PerformanceTimer perfTimer("RenderablePolyLineEntityItem::render"); Q_ASSERT(getType() == EntityTypes::PolyLine); Q_ASSERT(args->_batch); if (_pointsChanged) { updateGeometry(); } gpu::Batch& batch = *args->_batch; Transform transform = Transform(); transform.setTranslation(getPosition()); transform.setRotation(getRotation()); batch.setModelTransform(transform); batch.setPipeline(_pipeline); batch.setResourceTexture(PAINTSTROKE_GPU_SLOT, _texture); batch.setInputFormat(_format); batch.setInputBuffer(0, _verticesBuffer, 0, _format->getChannels().at(0)._stride); batch.draw(gpu::TRIANGLE_STRIP, _numVertices, 0); RenderableDebugableEntityItem::render(this, args); };
void PrioVR::update(float deltaTime) { #ifdef HAVE_PRIOVR if (!_skeletalDevice) { return; } PerformanceTimer perfTimer("PrioVR"); unsigned int timestamp; yei_getLastStreamDataAll(_skeletalDevice, (char*)_jointRotations.data(), _jointRotations.size() * sizeof(glm::quat), ×tamp); // convert to our expected coordinate system, average with last rotations to smooth for (int i = 0; i < _jointRotations.size(); i++) { _jointRotations[i].y *= -1.0f; _jointRotations[i].z *= -1.0f; glm::quat lastRotation = _lastJointRotations.at(i); _lastJointRotations[i] = _jointRotations.at(i); _jointRotations[i] = safeMix(lastRotation, _jointRotations.at(i), 0.5f); } // convert the joysticks into palm data setPalm(deltaTime, LEFT_HAND_INDEX); setPalm(deltaTime, RIGHT_HAND_INDEX); #endif }
void RenderableParticleEffectEntityItem::render(RenderArgs* args) { Q_ASSERT(getType() == EntityTypes::ParticleEffect); PerformanceTimer perfTimer("RenderableParticleEffectEntityItem::render"); if (_texturesChangedFlag) { if (_textures.isEmpty()) { _texture.clear(); } else { // for now use the textures string directly. // Eventually we'll want multiple textures in a map or array. _texture = DependencyManager::get<TextureCache>()->getTexture(_textures); } _texturesChangedFlag = false; } bool textured = _texture && _texture->isLoaded(); updateQuads(args, textured); Q_ASSERT(args->_batch); gpu::Batch& batch = *args->_batch; if (textured) { batch.setUniformTexture(0, _texture->getGPUTexture()); } batch.setModelTransform(getTransformToCenter()); DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch, textured); DependencyManager::get<GeometryCache>()->renderVertices(batch, gpu::QUADS, _cacheID); };
void AvatarManager::updateOtherAvatars(float deltaTime) { if (_avatarHash.size() < 2 && _avatarFades.isEmpty()) { return; } bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateAvatars()"); PerformanceTimer perfTimer("otherAvatars"); // simulate avatars AvatarHash::iterator avatarIterator = _avatarHash.begin(); while (avatarIterator != _avatarHash.end()) { auto avatar = std::dynamic_pointer_cast<Avatar>(avatarIterator.value()); if (avatar == _myAvatar || !avatar->isInitialized()) { // DO NOT update _myAvatar! Its update has already been done earlier in the main loop. // DO NOT update or fade out uninitialized Avatars ++avatarIterator; } else if (avatar->shouldDie()) { removeAvatarMotionState(avatar); _avatarFades.push_back(avatarIterator.value()); avatarIterator = _avatarHash.erase(avatarIterator); } else { avatar->simulate(deltaTime); ++avatarIterator; } } // simulate avatar fades simulateAvatarFades(deltaTime); }
void AvatarManager::updateMyAvatar(float deltaTime) { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "AvatarManager::updateMyAvatar()"); AvatarTransit::Status status = _myAvatar->updateTransit(deltaTime, _myAvatar->getNextPosition(), _myAvatar->getSensorToWorldScale(), _transitConfig); handleTransitAnimations(status); _myAvatar->update(deltaTime); render::Transaction transaction; _myAvatar->updateRenderItem(transaction); qApp->getMain3DScene()->enqueueTransaction(transaction); quint64 now = usecTimestampNow(); quint64 dt = now - _lastSendAvatarDataTime; if (dt > MIN_TIME_BETWEEN_MY_AVATAR_DATA_SENDS && !_myAvatarDataPacketsPaused) { // send head/hand data to the avatar mixer and voxel server PerformanceTimer perfTimer("send"); _myAvatar->sendAvatarDataPacket(); _lastSendAvatarDataTime = now; _myAvatarSendRate.increment(); } static AvatarCertifyBanner theftBanner; if (_myAvatar->isCertifyFailed()) { theftBanner.show(_myAvatar->getSessionUUID()); } else { theftBanner.clear(); } }
void PhysicsSimulation::computeCollisions() { PerformanceTimer perfTimer("collide"); _collisions.clear(); const QVector<Shape*> shapes = _entity->getShapes(); int numShapes = shapes.size(); // collide main ragdoll with self for (int i = 0; i < numShapes; ++i) { const Shape* shape = shapes.at(i); if (!shape) { continue; } for (int j = i+1; j < numShapes; ++j) { const Shape* otherShape = shapes.at(j); if (otherShape && _entity->collisionsAreEnabled(i, j)) { ShapeCollider::collideShapes(shape, otherShape, _collisions); } } } // collide main ragdoll with others int numEntities = _otherEntities.size(); for (int i = 0; i < numEntities; ++i) { const QVector<Shape*> otherShapes = _otherEntities.at(i)->getShapes(); ShapeCollider::collideShapesWithShapes(shapes, otherShapes, _collisions); } }
void RenderableBoxEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableBoxEntityItem::render"); assert(getType() == EntityTypes::Box); glm::vec3 position = getPositionInMeters(); glm::vec3 center = getCenter() * (float)TREE_SCALE; glm::vec3 dimensions = getDimensions() * (float)TREE_SCALE; glm::quat rotation = getRotation(); const float MAX_COLOR = 255.0f; glColor4f(getColor()[RED_INDEX] / MAX_COLOR, getColor()[GREEN_INDEX] / MAX_COLOR, getColor()[BLUE_INDEX] / MAX_COLOR, getLocalRenderAlpha()); glPushMatrix(); glTranslatef(position.x, position.y, position.z); glm::vec3 axis = glm::axis(rotation); glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); glPushMatrix(); glm::vec3 positionToCenter = center - position; glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); glScalef(dimensions.x, dimensions.y, dimensions.z); DependencyManager::get<DeferredLightingEffect>()->renderSolidCube(1.0f); glPopMatrix(); glPopMatrix(); };
bool AvatarUpdate::process() { PerformanceTimer perfTimer("AvatarUpdate"); quint64 start = usecTimestampNow(); quint64 deltaMicroseconds = start - _lastAvatarUpdate; _lastAvatarUpdate = start; float deltaSeconds = (float) deltaMicroseconds / (float) USECS_PER_SECOND; Application::getInstance()->setAvatarSimrateSample(1.0f / deltaSeconds); QSharedPointer<AvatarManager> manager = DependencyManager::get<AvatarManager>(); MyAvatar* myAvatar = manager->getMyAvatar(); //loop through all the other avatars and simulate them... //gets current lookat data, removes missing avatars, etc. manager->updateOtherAvatars(deltaSeconds); myAvatar->startUpdate(); Application::getInstance()->updateMyAvatarLookAtPosition(); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes manager->updateMyAvatar(deltaSeconds); myAvatar->endUpdate(); if (!isThreaded()) { return true; } int elapsed = (usecTimestampNow() - start); int usecToSleep = _targetInterval - elapsed; if (usecToSleep < 0) { usecToSleep = 1; // always yield } usleep(usecToSleep); return true; }
void AvatarManager::updateOtherAvatars(float deltaTime) { if (_avatarHash.size() < 2 && _avatarFades.isEmpty()) { return; } bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateAvatars()"); PerformanceTimer perfTimer("otherAvatars"); // simulate avatars AvatarHash::iterator avatarIterator = _avatarHash.begin(); while (avatarIterator != _avatarHash.end()) { AvatarSharedPointer sharedAvatar = avatarIterator.value(); Avatar* avatar = reinterpret_cast<Avatar*>(sharedAvatar.data()); if (sharedAvatar == _myAvatar || !avatar->isInitialized()) { // DO NOT update _myAvatar! Its update has already been done earlier in the main loop. // DO NOT update uninitialized Avatars ++avatarIterator; continue; } if (!shouldKillAvatar(sharedAvatar)) { // this avatar's mixer is still around, go ahead and simulate it avatar->simulate(deltaTime); ++avatarIterator; } else { // the mixer that owned this avatar is gone, give it to the vector of fades and kill it avatarIterator = erase(avatarIterator); } } // simulate avatar fades simulateAvatarFades(deltaTime); }
void RenderableWebEntityItem::render(RenderArgs* args) { checkFading(); #ifdef WANT_EXTRA_DEBUGGING { gpu::Batch& batch = *args->_batch; batch.setModelTransform(getTransformToCenter()); // we want to include the scale as well glm::vec4 cubeColor{ 1.0f, 0.0f, 0.0f, 1.0f}; DependencyManager::get<GeometryCache>()->renderWireCube(batch, 1.0f, cubeColor); } #endif if (!_webSurface) { #if defined(Q_OS_LINUX) // these don't seem to work on Linux return; #else if (!buildWebSurface(static_cast<EntityTreeRenderer*>(args->_renderer))) { return; } _fadeStartTime = usecTimestampNow(); #endif } _lastRenderTime = usecTimestampNow(); glm::vec2 windowSize = getWindowSize(); // 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(windowSize.x, windowSize.y)); 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; bool success; batch.setModelTransform(getTransformToCenter(success)); if (!success) { return; } if (_texture) { batch._glActiveBindTexture(GL_TEXTURE0, GL_TEXTURE_2D, _texture); } float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; batch._glColor4f(1.0f, 1.0f, 1.0f, fadeRatio); if (fadeRatio < OPAQUE_ALPHA_THRESHOLD) { DependencyManager::get<GeometryCache>()->bindTransparentWebBrowserProgram(batch); } else { DependencyManager::get<GeometryCache>()->bindOpaqueWebBrowserProgram(batch); } DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, texMin, texMax, glm::vec4(1.0f, 1.0f, 1.0f, fadeRatio)); }
void PhysicsSimulation::applyContactFriction() { PerformanceTimer perfTimer("contacts"); QMap<quint64, ContactPoint>::iterator itr = _contacts.begin(); while (itr != _contacts.end()) { itr.value().applyFriction(); ++itr; } }
void PhysicsSimulation::enforceContactConstraints() { PerformanceTimer perfTimer("contacts"); QMap<quint64, ContactPoint>::iterator itr = _contacts.begin(); while (itr != _contacts.end()) { itr.value().enforce(); ++itr; } }
void PhysicsSimulation::moveRagdolls(float deltaTime) { PerformanceTimer perfTimer("integrate"); _ragdoll->stepRagdollForward(deltaTime); int numDolls = _otherRagdolls.size(); for (int i = 0; i < numDolls; ++i) { _otherRagdolls[i]->stepRagdollForward(deltaTime); } }
template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args) { if (Menu::getInstance()->isOptionChecked(MenuOption::WorldAxes)) { PerformanceTimer perfTimer("worldBox"); auto& batch = *args->_batch; DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch); WorldBoxRenderData::renderWorldBox(args, batch); } }
void RenderableModelEntityItem::loader() { _needsModelReload = true; EntityTreeRenderer* renderer = DependencyManager::get<EntityTreeRenderer>().data(); assert(renderer); { PerformanceTimer perfTimer("getModel"); getModel(renderer); } }
void RenderableShapeEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableShapeEntityItem::render"); //Q_ASSERT(getType() == EntityTypes::Shape); Q_ASSERT(args->_batch); checkFading(); if (!_procedural) { _procedural.reset(new Procedural(getUserData())); _procedural->_vertexSource = simple_vert; _procedural->_fragmentSource = simple_frag; _procedural->_opaqueState->setCullMode(gpu::State::CULL_NONE); _procedural->_opaqueState->setDepthTest(true, true, gpu::LESS_EQUAL); PrepareStencil::testMaskDrawShape(*_procedural->_opaqueState); _procedural->_opaqueState->setBlendFunction(false, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); } gpu::Batch& batch = *args->_batch; glm::vec4 color(toGlm(getXColor()), getLocalRenderAlpha()); bool success; Transform modelTransform = getTransformToCenter(success); if (!success) { return; } if (_shape == entity::Sphere) { modelTransform.postScale(SPHERE_ENTITY_SCALE); } batch.setModelTransform(modelTransform); // use a transform with scale, rotation, registration point and translation if (_procedural->ready()) { _procedural->prepare(batch, getPosition(), getDimensions(), getOrientation()); auto outColor = _procedural->getColor(color); outColor.a *= _procedural->isFading() ? Interpolate::calculateFadeRatio(_procedural->getFadeStartTime()) : 1.0f; batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a); if (render::ShapeKey(args->_globalShapeKey).isWireframe()) { DependencyManager::get<GeometryCache>()->renderWireShape(batch, MAPPING[_shape]); } else { DependencyManager::get<GeometryCache>()->renderShape(batch, MAPPING[_shape]); } } else { // FIXME, support instanced multi-shape rendering using multidraw indirect color.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; auto geometryCache = DependencyManager::get<GeometryCache>(); auto pipeline = color.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline(); if (render::ShapeKey(args->_globalShapeKey).isWireframe()) { geometryCache->renderWireShapeInstance(args, batch, MAPPING[_shape], color, pipeline); } else { geometryCache->renderSolidShapeInstance(args, batch, MAPPING[_shape], color, pipeline); } } static const auto triCount = DependencyManager::get<GeometryCache>()->getShapeTriangleCount(MAPPING[_shape]); args->_details._trianglesRendered += (int)triCount; }
void PhysicsSimulation::stepForward(float deltaTime, float minError, int maxIterations, quint64 maxUsec) { ++_frameCount; if (!_ragdoll) { return; } quint64 now = usecTimestampNow(); quint64 startTime = now; quint64 expiry = startTime + maxUsec; moveRagdolls(deltaTime); buildContactConstraints(); int numDolls = _otherRagdolls.size(); { PerformanceTimer perfTimer("enforce"); _ragdoll->enforceRagdollConstraints(); for (int i = 0; i < numDolls; ++i) { _otherRagdolls[i]->enforceRagdollConstraints(); } } int iterations = 0; float error = 0.0f; do { computeCollisions(); updateContacts(); resolveCollisions(); { // enforce constraints PerformanceTimer perfTimer("enforce"); error = _ragdoll->enforceRagdollConstraints(); for (int i = 0; i < numDolls; ++i) { error = glm::max(error, _otherRagdolls[i]->enforceRagdollConstraints()); } } enforceContactConstraints(); ++iterations; now = usecTimestampNow(); } while (_collisions.size() != 0 && (iterations < maxIterations) && (error > minError) && (now < expiry)); pruneContacts(); }
void Application::runRenderFrame(RenderArgs* renderArgs) { PROFILE_RANGE(render, __FUNCTION__); PerformanceTimer perfTimer("display"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::runRenderFrame()"); // The pending changes collecting the changes here render::Transaction transaction; if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderEntities()) { // render models... PerformanceTimer perfTimer("entities"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::runRenderFrame() ... entities..."); RenderArgs::DebugFlags renderDebugFlags = RenderArgs::RENDER_DEBUG_NONE; if (Menu::getInstance()->isOptionChecked(MenuOption::PhysicsShowHulls)) { renderDebugFlags = static_cast<RenderArgs::DebugFlags>(renderDebugFlags | static_cast<int>(RenderArgs::RENDER_DEBUG_HULLS)); } renderArgs->_debugFlags = renderDebugFlags; } // Make sure the WorldBox is in the scene // For the record, this one RenderItem is the first one we created and added to the scene. // We could meoee that code elsewhere but you know... if (!render::Item::isValidID(WorldBoxRenderData::_item)) { auto worldBoxRenderData = std::make_shared<WorldBoxRenderData>(); auto worldBoxRenderPayload = std::make_shared<WorldBoxRenderData::Payload>(worldBoxRenderData); WorldBoxRenderData::_item = _main3DScene->allocateID(); transaction.resetItem(WorldBoxRenderData::_item, worldBoxRenderPayload); _main3DScene->enqueueTransaction(transaction); } { PerformanceTimer perfTimer("EngineRun"); _renderEngine->getRenderContext()->args = renderArgs; _renderEngine->run(); } }
void JoystickScriptingInterface::update() { #ifdef HAVE_SDL2 if (_isInitialized) { PerformanceTimer perfTimer("JoystickScriptingInterface::update"); SDL_GameControllerUpdate(); SDL_Event event; while (SDL_PollEvent(&event)) { if (event.type == SDL_CONTROLLERAXISMOTION) { Joystick* joystick = _openJoysticks[event.caxis.which]; if (joystick) { joystick->handleAxisEvent(event.caxis); } } else if (event.type == SDL_CONTROLLERBUTTONDOWN || event.type == SDL_CONTROLLERBUTTONUP) { Joystick* joystick = _openJoysticks[event.cbutton.which]; if (joystick) { joystick->handleButtonEvent(event.cbutton); } if (event.cbutton.button == SDL_CONTROLLER_BUTTON_BACK) { // this will either start or stop a global back event QEvent::Type backType = (event.type == SDL_CONTROLLERBUTTONDOWN) ? HFBackEvent::startType() : HFBackEvent::endType(); HFBackEvent backEvent(backType); qApp->sendEvent(qApp, &backEvent); } else if (event.cbutton.button == SDL_CONTROLLER_BUTTON_A) { // this will either start or stop a global action event QEvent::Type actionType = (event.type == SDL_CONTROLLERBUTTONDOWN) ? HFActionEvent::startType() : HFActionEvent::endType(); // global action events fire in the center of the screen HFActionEvent actionEvent(actionType, Application::getInstance()->getCamera()->computeViewPickRay(0.5f, 0.5f)); qApp->sendEvent(qApp, &actionEvent); } } else if (event.type == SDL_CONTROLLERDEVICEADDED) { SDL_GameController* controller = SDL_GameControllerOpen(event.cdevice.which); SDL_JoystickID id = getInstanceId(controller); Joystick* joystick = new Joystick(id, SDL_GameControllerName(controller), controller); _openJoysticks[id] = joystick; emit joystickAdded(joystick); } else if (event.type == SDL_CONTROLLERDEVICEREMOVED) { Joystick* joystick = _openJoysticks[event.cdevice.which]; _openJoysticks.remove(event.cdevice.which); emit joystickRemoved(joystick); } } } #endif }
void SDL2Manager::pluginUpdate(float deltaTime, bool jointsCaptured) { #ifdef HAVE_SDL2 if (_isInitialized) { auto userInputMapper = DependencyManager::get<UserInputMapper>(); for (auto joystick : _openJoysticks) { joystick->update(deltaTime, jointsCaptured); } PerformanceTimer perfTimer("SDL2Manager::update"); SDL_GameControllerUpdate(); SDL_Event event; while (SDL_PollEvent(&event)) { if (event.type == SDL_CONTROLLERAXISMOTION) { Joystick* joystick = _openJoysticks[event.caxis.which]; if (joystick) { joystick->handleAxisEvent(event.caxis); } } else if (event.type == SDL_CONTROLLERBUTTONDOWN || event.type == SDL_CONTROLLERBUTTONUP) { Joystick* joystick = _openJoysticks[event.cbutton.which]; if (joystick) { joystick->handleButtonEvent(event.cbutton); } if (event.cbutton.button == SDL_CONTROLLER_BUTTON_BACK) { // this will either start or stop a global back event QEvent::Type backType = (event.type == SDL_CONTROLLERBUTTONDOWN) ? HFBackEvent::startType() : HFBackEvent::endType(); HFBackEvent backEvent(backType); qApp->sendEvent(qApp, &backEvent); } } else if (event.type == SDL_CONTROLLERDEVICEADDED) { SDL_GameController* controller = SDL_GameControllerOpen(event.cdevice.which); SDL_JoystickID id = getInstanceId(controller); if (!_openJoysticks.contains(id)) { Joystick* joystick = new Joystick(id, SDL_GameControllerName(controller), controller); _openJoysticks[id] = joystick; joystick->registerToUserInputMapper(*userInputMapper); joystick->assignDefaultInputMapping(*userInputMapper); emit joystickAdded(joystick); } } else if (event.type == SDL_CONTROLLERDEVICEREMOVED) { Joystick* joystick = _openJoysticks[event.cdevice.which]; _openJoysticks.remove(event.cdevice.which); userInputMapper->removeDevice(joystick->getDeviceID()); emit joystickRemoved(joystick); } } } #endif }
void EntitySimulation::updateEntities() { QMutexLocker lock(&_mutex); quint64 now = usecTimestampNow(); // these methods may accumulate entries in _entitiesToBeDeleted expireMortalEntities(now); callUpdateOnEntitiesThatNeedIt(now); moveSimpleKinematics(now); updateEntitiesInternal(now); PerformanceTimer perfTimer("sortingEntities"); sortEntitiesThatMoved(); }
void RenderableModelEntityItem::loader() { _needsModelReload = true; EntityTreeRenderer* renderer = DependencyManager::get<EntityTreeRenderer>().data(); assert(renderer); if (!_model || _needsModelReload) { PerformanceTimer perfTimer("getModel"); getModel(renderer); } if (_model) { _model->setURL(getParsedModelURL()); _model->setCollisionModelURL(QUrl(getCompoundShapeURL())); } }