void Matrix4f::setRow( int i, const Vector4f& v ) { m_elements[ i ] = v.x(); m_elements[ i + 4 ] = v.y(); m_elements[ i + 8 ] = v.z(); m_elements[ i + 12 ] = v.w(); }
void Matrix4f::setCol( int j, const Vector4f& v ) { int colStart = 4 * j; m_elements[ colStart ] = v.x(); m_elements[ colStart + 1 ] = v.y(); m_elements[ colStart + 2 ] = v.z(); m_elements[ colStart + 3 ] = v.w(); }
// static QRgb QImageUtils::vector4fToQRgba( const Vector4f& v ) { int r = ColorUtils::floatToInt( v.x() ); int g = ColorUtils::floatToInt( v.y() ); int b = ColorUtils::floatToInt( v.z() ); int a = ColorUtils::floatToInt( v.w() ); return qRgba( r, g, b, a ); }
void Float4Widget::setValue(Vector4f v) { comboSlider1->blockSignals(true); comboSlider2->blockSignals(true); comboSlider3->blockSignals(true); comboSlider4->blockSignals(true); comboSlider1->setValue(v.x()); comboSlider2->setValue(v.y()); comboSlider3->setValue(v.z()); comboSlider3->setValue(v.w()); comboSlider1->blockSignals(false); comboSlider2->blockSignals(false); comboSlider3->blockSignals(false); comboSlider4->blockSignals(false); }
// for a given state, evaluate f(X,t) vector<Vector3f> PendulumSystem::evalF(vector<Vector3f> state) { vector<Vector3f> f; f.push_back(Vector3f(0,0,0)); f.push_back(Vector3f(0,0,0)); // YOUR CODE HERE for (unsigned i=2; i < state.size(); i+=2) { Vector3f position = state[i]; Vector3f velocity = state[i+1]; Vector3f force = Vector3f(); float mass = 1; float g = -.25; Vector3f gravity = Vector3f(0,mass*g,0); force += gravity; float drag = .1; Vector3f viscousDrag = -drag * velocity; force += viscousDrag; for (unsigned j=0; j < m_vSprings.size(); j++) { Vector4f spring = m_vSprings[j]; float springConstant = spring.z(); float restLength = spring.w(); if (spring.x() == i/2) { Vector3f dist = position - state[spring.y()*2]; force += -springConstant*(dist.abs() - restLength)*(dist.normalized()); } else if (spring.y() == i/2) { Vector3f dist = position - state[spring.x()*2]; force += -springConstant*(dist.abs() - restLength)*(dist.normalized()); } } f.push_back(velocity); f.push_back(force/mass); } return f; }
void Renderer::updateNearFar( const Vector4f& boundingSphere ) { const Matrix4f& view = getViewMatrix(); Matrix4f viewInv; compute_inverse( view, viewInv ); const Vector3f& zero = viewInv * Vector3f::ZERO; Vector3f front = viewInv * Vector3f( 0.0f, 0.0f, -1.0f ); front -= zero; front.normalize(); front *= boundingSphere.w(); const Vector3f& translation = getModelMatrix().get_translation(); const Vector3f& center = translation - boundingSphere.get_sub_vector< 3 >(); const Vector3f& nearPoint = view * ( center - front ); const Vector3f& farPoint = view * ( center + front ); if( _impl->useOrtho( )) { LBASSERTINFO( fabs( farPoint.z() - nearPoint.z() ) > std::numeric_limits< float >::epsilon(), nearPoint << " == " << farPoint ); setNearFar( -nearPoint.z(), -farPoint.z() ); } else { // estimate minimal value of near plane based on frustum size const eq::Frustumf& frustum = _impl->getFrustum(); const float width = fabs( frustum.right() - frustum.left() ); const float height = fabs( frustum.top() - frustum.bottom() ); const float size = LB_MIN( width, height ); const float minNear = frustum.near_plane() / size * .001f; const float zNear = LB_MAX( minNear, -nearPoint.z() ); const float zFar = LB_MAX( zNear * 2.f, -farPoint.z() ); setNearFar( zNear, zFar ); } }
Vector4f operator - ( const Vector4f& v ) { return Vector4f( -v.x(), -v.y(), -v.z(), -v.w() ); }
Vector4f operator / ( const Vector4f& v0, const Vector4f& v1 ) { return Vector4f( v0.x() / v1.x(), v0.y() / v1.y(), v0.z() / v1.z(), v0.w() / v1.w() ); }
// static float Vector4f::dot( const Vector4f& v0, const Vector4f& v1 ) { return v0.x() * v1.x() + v0.y() * v1.y() + v0.z() * v1.z() + v0.w() * v1.w(); }
void ParticleEmitter::generateParticles(double simulationTime, std::vector<Particle>& particleBuffer, ParticleRenderer* renderer) const { if (simulationTime > m_endTime + m_particleLifetime) { // No particles left return; } if (simulationTime < m_startTime) { // No particles emitted yet return; } // t is the time elapsed since the start time double t = simulationTime - m_startTime; // Particles are always emitted at a constant rate double spawnInterval = 1.0 / m_spawnRate; // Location within the particle stream; more than maxint particles // may be emitted over the lifetime of the particle system, so we // have to wrap. double streamLocation = std::fmod(t * m_spawnRate, (double) (0x80000000u)); // Compute the particle index; this will be used to initialize the // random number generator, so that the particle always has the // same properties. int particleIndex = (int) (streamLocation); // Age of the first particle double age = (streamLocation - particleIndex) * spawnInterval; float invLifetime = (float) (1.0 / m_particleLifetime); double maxAge = min((double) m_particleLifetime, t); if (simulationTime > m_endTime) { int skipParticles = (int) ((simulationTime - m_endTime) * m_spawnRate); particleIndex -= skipParticles; age += skipParticles * spawnInterval; } particleBuffer.clear(); // Scale factor used in color interpolation; subtract // a small value to avoid having to do an extra range // check for particles right at the end of their lifetimes. float colorKeyScale = float(m_colorCount) - 1.00001f; while (age < maxAge) { float w0 = (float) age * invLifetime; float w1 = 1.0f - w0; // Initialize the pseudorandom number generator with a value // that's based on the current particle index. This ensures that // the same initial state is always generated for the particle. // We can't just use the unmodified particle index, as this produces // obvious correlations between particles when initial properties // are generated with a simple linear congruential number generator. PseudorandomGenerator gen((v_uint64(particleIndex) * 1103515245) ^ 0xaaaaaaaaaaaaaaaaULL); // Compute the initial state Vector3f p0; Vector3f v0; m_generator->generateParticle(gen, p0, v0); if (m_velocityVariation > 0.0f) { v0 += randomPointInUnitSphere(gen) * m_velocityVariation; } // Compute the state of the particle at the current time Particle particle; // Compute the particle size particle.size = w0 * m_endSize + w1 * m_startSize; // Calculate the color of the particle. This can be done very // inexpensively in a shader. if (m_colorCount < 2) { particle.color = m_colorKeys[0].start<3>(); particle.opacity = m_colorKeys[0].w(); } else { float s = w0 * colorKeyScale; int colorIndex = (unsigned int) s; float t = s - colorIndex; Vector4f interpolatedColor = (1 - t) * m_colorKeys[colorIndex] + t * m_colorKeys[colorIndex + 1]; particle.color = interpolatedColor.start<3>(); particle.opacity = interpolatedColor.w(); } // Calculate particle position as p0 + v0*t + (1/2)at^2 particle.velocity = v0 + static_cast<float>(age) * m_force; particle.position = p0 + static_cast<float>(age) * (v0 + (static_cast<float>(age) * 0.5f) * m_force); // Rotation (if enabled) // TODO // Flush the particle buffer if it's full if (particleBuffer.size() == particleBuffer.capacity()) { renderer->renderParticles(particleBuffer); particleBuffer.clear(); } // Add the particle to the buffer particleBuffer.push_back(particle); // Older particles were emitted earlier, and therefore have a // lower index. particleIndex--; age += spawnInterval; } // Render any particles remaining in the buffer if (!particleBuffer.empty()) { renderer->renderParticles(particleBuffer); particleBuffer.clear(); } }
/** Draw a piecewise cubic curve with transformation and frustum clipping. Only * the part of the curve between startTime and endTime will be drawn. Additionally, * the curve is drawn with a fade effect. The curve is at full opacity at fadeStartTime * and completely transparent at fadeEndTime. fadeStartTime may be greater than * fadeEndTime--this just means that the fade direction will be reversed. * * @param modelview an affine transformation that will be applied to the curve * @param nearZ z coordinate of the near plane * @param farZ z coordinate of the far plane * @param viewFrustumPlaneNormals array of four normals (top, bottom, left, and right frustum planes) * @param subdivisionThreshold * @param startTime the beginning of the time interval * @param endTime the end of the time interval * @param fadeStartTime points on the curve before this time are drawn with full opacity * @param fadeEndTime points on the curve after this time are not drawn */ void CurvePlot::renderFaded(const Eigen::Affine3d& modelview, double nearZ, double farZ, const Eigen::Vector3d viewFrustumPlaneNormals[], double subdivisionThreshold, double startTime, double endTime, const Vector4f& color, double fadeStartTime, double fadeEndTime) const { // Flag to indicate whether we need to issue a glBegin() bool restartCurve = true; if (m_samples.empty() || endTime <= m_samples.front().t || startTime >= m_samples.back().t) return; // Linear search for the first sample unsigned int startSample = 0; while (startSample < m_samples.size() - 1 && startTime > m_samples[startSample].t) startSample++; // Start at the first sample with time <= startTime if (startSample > 0) startSample--; double fadeDuration = fadeEndTime - fadeStartTime; double fadeRate = 1.0 / fadeDuration; const Vector3d& p0_ = m_samples[startSample].position; const Vector3d& v0_ = m_samples[startSample].velocity; Vector4d p0 = modelview * Vector4d(p0_.x(), p0_.y(), p0_.z(), 1.0); Vector4d v0 = modelview * Vector4d(v0_.x(), v0_.y(), v0_.z(), 0.0); double opacity0 = (m_samples[startSample].t - fadeStartTime) * fadeRate; opacity0 = max(0.0, min(1.0, opacity0)); HighPrec_Frustum viewFrustum(nearZ, farZ, viewFrustumPlaneNormals); HighPrec_RenderContext rc(vbuf, viewFrustum, subdivisionThreshold); vbuf.createVertexBuffer(); vbuf.setup(); bool firstSegment = true; bool lastSegment = false; for (unsigned int i = startSample + 1; i < m_samples.size() && !lastSegment; i++) { // Transform the points into camera space. const Vector3d& p1_ = m_samples[i].position; const Vector3d& v1_ = m_samples[i].velocity; Vector4d p1 = modelview * Vector4d(p1_.x(), p1_.y(), p1_.z(), 1.0); Vector4d v1 = modelview * Vector4d(v1_.x(), v1_.y(), v1_.z(), 0.0); double opacity1 = (m_samples[i].t - fadeStartTime) * fadeRate; opacity1 = max(0.0, min(1.0, opacity1)); if (endTime <= m_samples[i].t) { lastSegment = true; } // O(t) is an approximating function for this segment of // the orbit, with 0 <= t <= 1 // C is the viewer position // d(t) = |O(t) - C|, the distance from viewer to the // orbit segment. double curveBoundingRadius = m_samples[i].boundingRadius; // Estimate the minimum possible distance from the // curve to the z=0 plane. If the curve is far enough // away to be approximated as a straight line, we'll just // render it. Otherwise, it should be a performance win // to do a sphere-frustum cull test before subdividing and // rendering segment. double minDistance = abs(p0.z()) - curveBoundingRadius; // Render close segments as splines with adaptive subdivision. The // subdivisions eliminates kinks between line segments and also // prevents clipping precision problems that occur when a // very long line is rendered with a relatively small view // volume. if (curveBoundingRadius >= subdivisionThreshold * minDistance || lastSegment || firstSegment) { // Skip rendering this section if it lies outside the view // frustum. if (viewFrustum.cullSphere(p0, curveBoundingRadius)) { if (!restartCurve) { vbuf.end(); restartCurve = true; } } else { double dt = m_samples[i].t - m_samples[i - 1].t; double t0 = 0.0; double t1 = 1.0; if (firstSegment) { t0 = (startTime - m_samples[i - 1].t) / dt; t0 = std::max(0.0, std::min(1.0, t0)); firstSegment = false; } if (lastSegment) { t1 = (endTime - m_samples[i - 1].t) / dt; } Matrix4d coeff = cubicHermiteCoefficients(p0, p1, v0 * dt, v1 * dt); restartCurve = rc.renderCubicFaded(restartCurve, coeff, t0, t1, color, (fadeStartTime - m_samples[i - 1].t) / dt, fadeRate * dt, curveBoundingRadius, 1); } } else { // Apparent size of curve is small enough that we can approximate // it as a line. // Simple cull test--just check the far plane. This is required because // apparent clipping precision limitations can cause a GPU to draw lines // that lie completely beyond the far plane. if (p0.z() + curveBoundingRadius < farZ) { if (!restartCurve) { vbuf.end(); restartCurve = true; } } else { if (restartCurve) { vbuf.begin(); vbuf.vertex(p0, Vector4f(color.x(), color.y(), color.z(), color.w() * float(opacity0))); restartCurve = false; } vbuf.vertex(p1, Vector4f(color.x(), color.y(), color.z(), color.w() * float(opacity1))); } } p0 = p1; v0 = v1; opacity0 = opacity1; } if (!restartCurve) { vbuf.end(); } vbuf.flush(); vbuf.finish(); }
/// Initialize a uniform parameter with a 4D vector void setUniform(const std::string &name, const Vector4f &v, bool warn = true) { glUniform4f(uniform(name, warn), v.x(), v.y(), v.z(), v.w()); }
float Vector4f::dot(const Vector4f& other) const { return this->x() * other.x() + this->y() * other.y() + this->z() * other.z() + this->w() * other.w(); }
//------------------------------------------------------------------------------ bool MaterialLoader::loadFromVariant(const sn::Variant & doc, sn::Material & mat) const { const AssetMetadata & meta = mat.getAssetMetadata(); // Shader ShaderProgram * shader = getAssetBySerializedLocation<ShaderProgram>(doc["shader"].getString(), meta.project, true); if (shader) mat.setShader(shader); // Depth bool depthTest = false; sn::unserialize(doc["depthTest"], depthTest); mat.setDepthTest(depthTest); // Blending BlendMode blendMode; sn::unserialize(doc["blend"], blendMode); mat.setBlendMode(blendMode); // Params const Variant::Dictionary params = doc["params"].getDictionary(); if (!params.empty()) { for (auto it = params.begin(); it != params.end(); ++it) { auto & v = it->second; // {"@type":"texture|rendertexture", "value":"foobar"} if (v.isDictionary()) { auto a = it->second.getDictionary(); auto typeTag = a["@type"]; auto valueTag = a["value"]; if (typeTag.isString() && valueTag.isString()) { std::string stype = typeTag.getString(); std::string loc = valueTag.getString(); if (stype == "texture") { Texture * tex = getAssetBySerializedLocation<Texture>(loc, meta.project, true); if (tex) mat.setTexture(it->first, tex); else SN_ERROR("Texture not found: " << loc); } else if (stype == "rendertexture") { RenderTexture * rt = getAssetBySerializedLocation<RenderTexture>(loc, meta.project, true); if (rt) mat.setRenderTexture(it->first, rt); else SN_ERROR("RenderTexture not found: " << loc); } else SN_ERROR("Unknown specified type: " << stype); } } else if (v.isArray()) { auto & a = it->second.getArray(); if (a.size() == 2) { Vector2f p; sn::unserialize(v, p); mat.setParam(it->first, p.x(), p.y()); } else if (a.size() == 3) { Vector3f p; sn::unserialize(v, p); mat.setParam(it->first, p.x(), p.y(), p.z()); } else if (a.size() == 4) { Vector4f p; sn::unserialize(v, p); mat.setParam(it->first, p.x(), p.y(), p.z(), p.w()); } // ... } else if (v.isFloat()) { mat.setParam(it->first, static_cast<f32>(v.getFloat())); } // TODO Handle other param types } } return mat.getShader() != nullptr; }
Vector4f operator * ( const Vector4f& v, float f ) { return Vector4f( f * v.x(), f * v.y(), f * v.z(), f * v.w() ); }
bool operator == ( const Vector4f& v0, const Vector4f& v1 ) { return( v0.x() == v1.x() && v0.y() == v1.y() && v0.z() == v1.z() && v0.w() == v1.w() ); }
// Return the GL restart status: true if the last segment of the // curve was culled and we need to start a new primitive sequence // with glBegin(). bool renderCubicFaded(bool restartCurve, const Matrix4d& coeff, double t0, double t1, const Vector4f& color, double fadeStart, double fadeRate, double curveBoundingRadius, int depth) const { const double dt = (t1 - t0) * InvSubdivisionFactor; double segmentBoundingRadius = curveBoundingRadius * InvSubdivisionFactor; #if DEBUG_ADAPTIVE_SPLINE { int c = depth % 10; glColor4f(SplineColors[c][0], SplineColors[c][1], SplineColors[c][2], 1.0f); ++SegmentCounts[depth]; } #endif Vector4d lastP = coeff * Vector4d(1.0, t0, t0 * t0, t0 * t0 * t0); double lastOpacity = (t0 - fadeStart) * fadeRate; lastOpacity = max(0.0, min(1.0, lastOpacity)); // clamp for (unsigned int i = 1; i <= SubdivisionFactor; i++) { double t = t0 + dt * i; Vector4d p = coeff * Vector4d(1.0, t, t * t, t * t * t); double opacity = (t - fadeStart) * fadeRate; opacity = max(0.0, min(1.0, opacity)); // clamp double minDistance = max(-m_viewFrustum.nearZ(), abs(p.z()) - segmentBoundingRadius); if (segmentBoundingRadius >= m_subdivisionThreshold * minDistance) { if (m_viewFrustum.cullSphere(p, segmentBoundingRadius)) { if (!restartCurve) { m_vbuf.end(); restartCurve = true; } } else { restartCurve = renderCubicFaded(restartCurve, coeff, t - dt, t, color, fadeStart, fadeRate, segmentBoundingRadius, depth + 1); } } else { #if DEBUG_ADAPTIVE_SPLINE { int c = depth % 10; glColor4f(SplineColors[c][0], SplineColors[c][1], SplineColors[c][2], i % 2 ? 0.25f : 1.0f); } #endif if (restartCurve) { m_vbuf.begin(); m_vbuf.vertex(lastP, Vector4f(color.x(), color.y(), color.z(), color.w() * float(lastOpacity))); restartCurve = false; } m_vbuf.vertex(p, Vector4f(color.x(), color.y(), color.z(), color.w() * float(opacity))); } lastP = p; lastOpacity = opacity; } return restartCurve; }