/****************************************************************************** * Determines the display radius of a single particle. ******************************************************************************/ FloatType ParticleDisplay::particleRadius(size_t particleIndex, ParticlePropertyObject* radiusProperty, ParticleTypeProperty* typeProperty) { OVITO_ASSERT(radiusProperty == nullptr || radiusProperty->type() == ParticleProperty::RadiusProperty); OVITO_ASSERT(typeProperty == nullptr || typeProperty->type() == ParticleProperty::ParticleTypeProperty); if(radiusProperty) { // Take particle radius directly from the radius property. OVITO_ASSERT(particleIndex < radiusProperty->size()); return radiusProperty->getFloat(particleIndex); } else if(typeProperty) { // Assign radius based on particle types. OVITO_ASSERT(particleIndex < typeProperty->size()); ParticleType* ptype = typeProperty->particleType(typeProperty->getInt(particleIndex)); if(ptype && ptype->radius() > 0) return ptype->radius(); } return defaultParticleRadius(); }
/****************************************************************************** * Determines the display color of a single particle. ******************************************************************************/ ColorA ParticleDisplay::particleColor(size_t particleIndex, ParticlePropertyObject* colorProperty, ParticleTypeProperty* typeProperty, ParticlePropertyObject* selectionProperty, ParticlePropertyObject* transparencyProperty) { OVITO_ASSERT(colorProperty == nullptr || colorProperty->type() == ParticleProperty::ColorProperty); OVITO_ASSERT(typeProperty == nullptr || typeProperty->type() == ParticleProperty::ParticleTypeProperty); OVITO_ASSERT(selectionProperty == nullptr || selectionProperty->type() == ParticleProperty::SelectionProperty); OVITO_ASSERT(transparencyProperty == nullptr || transparencyProperty->type() == ParticleProperty::TransparencyProperty); // Check if particle is selected. if(selectionProperty) { OVITO_ASSERT(particleIndex < selectionProperty->size()); if(selectionProperty->getInt(particleIndex)) return selectionParticleColor(); } ColorA c = defaultParticleColor(); if(colorProperty) { // Take particle color directly from the color property. OVITO_ASSERT(particleIndex < colorProperty->size()); c = colorProperty->getColor(particleIndex); } else if(typeProperty) { // Return color based on particle types. OVITO_ASSERT(particleIndex < typeProperty->size()); ParticleType* ptype = typeProperty->particleType(typeProperty->getInt(particleIndex)); if(ptype) c = ptype->color(); } // Apply alpha component. if(transparencyProperty) { OVITO_ASSERT(particleIndex < transparencyProperty->size()); c.a() = FloatType(1) - transparencyProperty->getFloat(particleIndex); } return c; }
bool ParticleSystem::UpdateSystem( float frametime ) { // the entity emitting this system cl_entity_t *source = UTIL_GetClientEntityWithServerIndex( m_iEntIndex ); if(!source) { // gEngfuncs.Con_Printf("ent not found\n" ); return false; } // Don't update if the system is outside the player's PVS. if (source->curstate.msg_time < gEngfuncs.GetClientTime()) { //remove particles enable = 0; } else enable = (source->curstate.renderfx == kRenderFxAurora); //check for contents to remove if(m_iKillCondition == gEngfuncs.PM_PointContents(source->curstate.origin, NULL)) { enable = 0; } if (m_pMainParticle == NULL) { if (enable) { ParticleType *pType = m_pMainType; if (pType) { m_pMainParticle = pType->CreateParticle(this);//m_pMainParticle); if (m_pMainParticle) { m_pMainParticle->m_iEntIndex = m_iEntIndex; m_pMainParticle->age_death = -1; // never die } } } } else if (!enable) { m_pMainParticle->age_death = 0; // die now m_pMainParticle = NULL; } particle* pParticle = m_pActiveParticle; particle* pLast = NULL; while( pParticle ) { if( UpdateParticle( pParticle, frametime ) ) { pLast = pParticle; pParticle = pParticle->nextpart; } else // deactivate it { if (pLast) { pLast->nextpart = pParticle->nextpart; pParticle->nextpart = m_pFreeParticle; m_pFreeParticle = pParticle; pParticle = pLast->nextpart; } else // deactivate the first particle in the list { m_pActiveParticle = pParticle->nextpart; pParticle->nextpart = m_pFreeParticle; m_pFreeParticle = pParticle; pParticle = m_pActiveParticle; } } } return true; }
bool ParticleSystem::UpdateSystem( float frametime ) { // the entity emitting this system edict_t *source = GetEntityByIndex( m_iEntIndex ); if( !source ) return false; // Don't update if the system is outside the player's PVS. enable = (source->v.renderfx == kRenderFxAurora); // check for contents to remove if( POINT_CONTENTS( source->v.origin ) == m_iKillCondition ) { enable = 0; } if( m_pMainParticle == NULL ) { if ( enable ) { ParticleType *pType = m_pMainType; if ( pType ) { m_pMainParticle = pType->CreateParticle( this ); if ( m_pMainParticle ) { m_pMainParticle->m_iEntIndex = m_iEntIndex; m_pMainParticle->age_death = -1; // never die } } } } else if ( !enable ) { m_pMainParticle->age_death = 0; // die now m_pMainParticle = NULL; } particle* pParticle = m_pActiveParticle; particle* pLast = NULL; while( pParticle ) { if ( UpdateParticle( pParticle, frametime )) { pLast = pParticle; pParticle = pParticle->nextpart; } else // deactivate it { if ( pLast ) { pLast->nextpart = pParticle->nextpart; pParticle->nextpart = m_pFreeParticle; m_pFreeParticle = pParticle; pParticle = pLast->nextpart; } else // deactivate the first particle in the list { m_pActiveParticle = pParticle->nextpart; pParticle->nextpart = m_pFreeParticle; m_pFreeParticle = pParticle; pParticle = m_pActiveParticle; } } } return true; }
/****************************************************************************** * Updates the display of atom properties. ******************************************************************************/ void ParticleInformationApplet::updateInformationDisplay() { DataSet* dataset = _mainWindow->datasetContainer().currentSet(); if(!dataset) return; QString infoText; QTextStream stream(&infoText, QIODevice::WriteOnly); for(auto& pickedParticle : _inputMode->_pickedParticles) { OVITO_ASSERT(pickedParticle.objNode); const PipelineFlowState& flowState = pickedParticle.objNode->evalPipeline(dataset->animationSettings()->time()); // If selection is based on particle ID, update the stored particle index in case order has changed. if(pickedParticle.particleId >= 0) { for(DataObject* dataObj : flowState.objects()) { ParticlePropertyObject* property = dynamic_object_cast<ParticlePropertyObject>(dataObj); if(property && property->type() == ParticleProperty::IdentifierProperty) { const int* begin = property->constDataInt(); const int* end = begin + property->size(); const int* iter = std::find(begin, end, pickedParticle.particleId); if(iter != end) pickedParticle.particleIndex = (iter - begin); } } } stream << QStringLiteral("<b>") << tr("Particle index") << QStringLiteral(" ") << (pickedParticle.particleIndex + 1) << QStringLiteral(":</b>"); stream << QStringLiteral("<table border=\"0\">"); for(DataObject* dataObj : flowState.objects()) { ParticlePropertyObject* property = dynamic_object_cast<ParticlePropertyObject>(dataObj); if(!property || property->size() <= pickedParticle.particleIndex) continue; // Update saved particle position in case it has changed. if(property->type() == ParticleProperty::PositionProperty) pickedParticle.localPos = property->getPoint3(pickedParticle.particleIndex); if(property->dataType() != qMetaTypeId<int>() && property->dataType() != qMetaTypeId<FloatType>()) continue; for(size_t component = 0; component < property->componentCount(); component++) { QString propertyName = property->name(); if(property->componentNames().empty() == false) { propertyName.append("."); propertyName.append(property->componentNames()[component]); } QString valueString; if(property->dataType() == qMetaTypeId<int>()) { valueString = QString::number(property->getIntComponent(pickedParticle.particleIndex, component)); ParticleTypeProperty* typeProperty = dynamic_object_cast<ParticleTypeProperty>(property); if(typeProperty && typeProperty->particleTypes().empty() == false) { ParticleType* ptype = typeProperty->particleType(property->getIntComponent(pickedParticle.particleIndex, component)); if(ptype) { valueString.append(" (" + ptype->name() + ")"); } } } else if(property->dataType() == qMetaTypeId<FloatType>()) valueString = QString::number(property->getFloatComponent(pickedParticle.particleIndex, component)); stream << QStringLiteral("<tr><td>") << propertyName << QStringLiteral(":</td><td>") << valueString << QStringLiteral("</td></tr>"); } } stream << QStringLiteral("</table><hr>"); } if(_inputMode->_pickedParticles.empty()) infoText = tr("No particles selected."); else if(_inputMode->_pickedParticles.size() >= 2) { stream << QStringLiteral("<b>") << tr("Distances:") << QStringLiteral("</b>"); stream << QStringLiteral("<table border=\"0\">"); for(size_t i = 0; i < _inputMode->_pickedParticles.size(); i++) { const auto& p1 = _inputMode->_pickedParticles[i]; for(size_t j = i + 1; j < _inputMode->_pickedParticles.size(); j++) { const auto& p2 = _inputMode->_pickedParticles[j]; stream << QStringLiteral("<tr><td>(") << (p1.particleIndex+1) << QStringLiteral(",") << (p2.particleIndex+1) << QStringLiteral("):</td><td>") << (p1.localPos - p2.localPos).length() << QStringLiteral("</td></tr>"); } } stream << QStringLiteral("</table><hr>"); } if(_inputMode->_pickedParticles.size() >= 3) { stream << QStringLiteral("<b>") << tr("Angles:") << QStringLiteral("</b>"); stream << QStringLiteral("<table border=\"0\">"); for(size_t i = 0; i < _inputMode->_pickedParticles.size(); i++) { const auto& p1 = _inputMode->_pickedParticles[i]; for(size_t j = 0; j < _inputMode->_pickedParticles.size(); j++) { if(j == i) continue; const auto& p2 = _inputMode->_pickedParticles[j]; for(size_t k = j + 1; k < _inputMode->_pickedParticles.size(); k++) { if(k == i) continue; const auto& p3 = _inputMode->_pickedParticles[k]; Vector3 v1 = p2.localPos - p1.localPos; Vector3 v2 = p3.localPos - p1.localPos; v1.normalizeSafely(); v2.normalizeSafely(); FloatType angle = acos(v1.dot(v2)); stream << QStringLiteral("<tr><td>(") << (p2.particleIndex+1) << QStringLiteral(" - ") << (p1.particleIndex+1) << QStringLiteral(" - ") << (p3.particleIndex+1) << QStringLiteral("):</td><td>") << (angle * 180.0f / FLOATTYPE_PI) << QStringLiteral("</td></tr>"); } } } stream << QStringLiteral("</table><hr>"); } _infoDisplay->setText(infoText); }