//Convenience Constructor QuatCamera::QuatCamera(): yAxis{ 0.0f, 1.0f, 0.0f }, position{ 7.0f, 4.0f, 20.0f }, forward{ 0.0f, 0.0f, -1.0f }, up{ 0.0f, 1.0f, 0.0f }, MOVEMENT_SPEED(0.1f), ROTATION_SPEED(0.0025f), SPIN_SPEED(40.0f), slerping(false) { up = getNormalized(up); forward = getNormalized(forward); }
QuatCamera::QuatCamera(glm::vec3 pos, glm::vec3 up_, glm::vec3 forward_) : yAxis{ 0.0f, 1.0f, 0.0f }, position{ pos }, forward{ forward_ }, up{ up_ }, MOVEMENT_SPEED(0.1f), ROTATION_SPEED(0.0025f), SPIN_SPEED(40.0f), slerping(false) { up = getNormalized(up); forward = getNormalized(forward); }
void Osg3dView::mousePressEvent(QMouseEvent *event) { vDebug("mousePressEvent"); if (event->button() == Qt::LeftButton) { m_savedEventNDCoords = getNormalized(event->x(), event->y()); // always identify the item under the mouse in case // it is a drag object findObjectsUnderMouseEvent(); // if np.at(1) != loadedModel we are dragging/clicking some control // in that case we want to stash the current mouse mode, do the drag // and restore the mouse mode when we are done. // Do the job asked if (m_mouseMode & (MM_PAN|MM_ROTATE|MM_ORBIT|MM_ZOOM) ) m_viewingCore->setPanStart( m_savedEventNDCoords.x(), m_savedEventNDCoords.y()); else if (m_mouseMode & MM_PICK_CENTER) { m_viewingCore->pickCenter(m_savedEventNDCoords.x(), m_savedEventNDCoords.y() ); update(); } else if (m_mouseMode & MM_SELECT) { // In this case we probably want to skip any intersections with // objects other than those under loadedModel; pickAnObjectFromView(); } m_mouseIsPressed = true; } }
void Quaternion::fromMatrix(const Matrix &m) { Real trace = m[0] + m[5] + m[10] + 1.0; Real s = .5; if (!Math::eq(trace, 0)) { s /= Math::Sqrt(trace); w = 0.25 / s; x = (m[6] - m[9]) * s; y = (m[8] - m[2]) * s; z = (m[1] - m[4]) * s; } else { if((m[0] > m[5]) && (m[0] > m[10]) ) { s /= Math::Sqrt( 1.0 + m[0] - m[5] - m[10] ); x = 0.25 / s; y = (m[4] + m[1]) * s; z = (m[8] + m[2]) * s; w = (m[9] - m[6]) * s; } else if(m[5] > m[10]) { s /= Math::Sqrt( 1.0 + m[5] - m[0] - m[10] ); x = (m[4] + m[1]) * s; y = 0.25 / s; z = (m[9] + m[6]) * s; w = (m[8] - m[2]) * s; } else { s /= Math::Sqrt( 1.0 + m[10] - m[0] - m[5] ); x = (m[8] + m[2]) * s; y = (m[9] + m[6]) * s; z = 0.25 / s; w = (m[4] - m[1]) * s; } } normalize(); // The resulting quaternion should be already normalized. ASSERT_EQ(*this, getNormalized()); }
void Shot::onCollision(const Collision & c) { sf::Color clr(255,255,255); if(c.entity != NULL) { // Except entities with the same team or the same type if(c.entity->team == team || c.entity->getType() == getType()) return; if(c.entity->getType() != ENT_MAP) { // Repulsion Vector2f repulsion = getNormalized(speed); // TODO find a way to access delta here, or not have to. // onCollision basically doesn't access to delta, then we have to choose a value... c.entity->accelerate(repulsion * 80.f, 0.03f); // Hurting Message hurt(M_HEA_HURT, this); hurt.health = 15; c.entity->processMessage(hurt); // Bloody color clr.g = 0; clr.b = 0; } } // Hit particles r_level->spawnEntity(new entity::ShockWave(0.1, 0.8, 4, clr), pos); invalidate(); }
void Osg3dView::mouseReleaseEvent(QMouseEvent *event) { vDebug("mouseReleaseEvent"); m_savedEventNDCoords = getNormalized(event->x(), event->y()); if (event->button() == Qt::LeftButton) m_mouseIsPressed = false; }
float Vec2::getAngle(const Vec2& other) const { Vec2 a2 = getNormalized(); Vec2 b2 = other.getNormalized(); float angle = atan2f(a2.cross(b2), a2.dot(b2)); if( fabs(angle) < FLT_EPSILON ) return 0.f; return angle; }
void Quaternion::invert() { // make sure we only try this with normalized quaternions. If the quat is not of unit // length, the method of inverting changes. ASSERT_EQ(*this, getNormalized()); x = -x; y = -y; z = -z; }
float toxi::geom::Vec2D::angleBetween( Vec2D v, bool forceNormalize ) { double theta; if (forceNormalize) { theta = getNormalized().dot(v.getNormalized()); } else { theta = dot(v); } return (float) std::acos(toxi::math::MathUtils::clipNormalized(theta)); }
//Increments the slerp void QuatCamera::updateSlerp(atlas::utils::Time const& t) { slerpProgress += t.deltaTime / SLERP_DURATION; //Slerping Complete if ((slerpProgress >= 1.0f) || equals(getNormalized(target - position), forward)) { slerping = false; slerpProgress = 0.0000000000f; } else { doSlerp(t); } }
void Quaternion::apply(Vector3 &vector) const { // make sure we only try this with normalized quaternions. If the quat is not of unit // length, the method of inverting changes. ASSERT_EQ(*this, getNormalized()); // Tansform the vector into the 4th dimension, apply the rotation, and transform back. Quaternion q = (*this) * Quaternion(0, vector.x, vector.y, vector.z) * Quaternion(w, -x, -y, -z); vector.x = q.x; vector.y = q.y; vector.z = q.z; }
float TExamplesDistance_DTW::operator ()(const TExample &e1, const TExample &e2) const { vector<float> seq1, seq2, der1, der2; getNormalized(e1, seq1); getNormalized(e2, seq2); TdtwMatrix mtrx; switch (dtwDistance) { case DTW_EUCLIDEAN: { initMatrix(seq1, seq2, mtrx); break; } case DTW_DERIVATIVE: { getDerivatives(seq1, der1); getDerivatives(seq2, der2); initMatrix(der1, der2, mtrx); break; } } float dist = calcDistance(mtrx); return dist; }
Quaternion QuaternionFn::getAngleAxis(const Radian& angle, const Vector3& axis) { Quaternion q; const Vector3 a = getNormalized(axis); const float s = MathFn::sin(0.5f * angle); q.xyz = a * s; q.w = MathFn::cos(0.5f * angle); return q; }
void Quaternion::fromAngleAxis(const Radian &angle, const Vector3 &axis) { // This is used to compensate for a non-unit axis. Real oneOverLength = 1.0f / axis.length(); Real sinAngle = Math::Sin(angle * 0.5f); w = Math::Cos(angle * 0.5f); x = (axis.x * sinAngle) * oneOverLength; y = (axis.y * sinAngle) * oneOverLength; z = (axis.z * sinAngle) * oneOverLength; // The resulting quaternion should be already normalized. ASSERT_EQ(*this, getNormalized()); }
void LayerGradientTest::onTouchesMoved(const std::vector<Touch*>& touches, Event *event) { auto s = Director::getInstance()->getWinSize(); auto touch = touches[0]; auto start = touch->getLocation(); auto diff = Vec2(s.width/2,s.height/2) - start; diff = diff.getNormalized(); auto gradient = static_cast<LayerGradient*>( getChildByTag(1) ); gradient->setVector(diff); }
void solvePaddleBallCollision(const Paddle& mPaddle, Ball& mBall) noexcept { if(!isIntersecting(mPaddle, mBall)) return; auto newY(mPaddle.top() - mBall.shape.getRadius() * 2.f); mBall.shape.setPosition(mBall.x(), newY); auto paddleBallDiff(mBall.x() - mPaddle.x()); auto posFactor(paddleBallDiff / mPaddle.width()); auto velFactor(mPaddle.velocity.x * 0.05f); sf::Vector2f collisionVec{posFactor + velFactor, -2.f}; mBall.velocity = getReflected(mBall.velocity, getNormalized(collisionVec)); }
/** * @brief cumulativef computes the cumulative Histogram. * @param bNormalized is a boolean value; if it is true values of * the Histogram will be normalized. * @return It returns the cumulative Histogram as a float pointer. */ float *cumulativef(bool bNormalized) { getNormalized(); bin_c = Array<float>::cumsum(bin_nor, nBin, bin_c); if(bNormalized) { for(int i=0; i<nBin; i++) { bin_c[i] /= bin_c[nBin - 1]; } } return bin_c; }
/** * @brief write saves the Histogram as an Image into a file. * @param name is the filename where to save the Histogram. * @param bNor is a boolean value for normalizing or not the Histogram. */ void write(std::string name, bool bNor) { Image img(1, nBin, 1, 1); if(bNor) { getNormalized(); memcpy(img.data, bin_nor, sizeof(float)*nBin); } else { for(int i = 0; i < nBin; i++) { img.data[i] = float(bin[i]); } } img.Write(name, LT_NONE); }
void OSGWidget::mouseReleaseEvent( QMouseEvent* event ) { m_mouseReleaseJustHappened = true; m_lastMouseEventNDCoords = getNormalized(event->x(), event->y()); m_mouseButtons &= event->buttons(); if (m_mouseModifiers != Qt::NoModifier) { popState(); } m_mouseModifiers = Qt::NoModifier; m_lastMouseEventTime.start(); }
void Quaternion::fromEuler(const Radian &nx, const Radian &ny, const Radian &nz) { Real sx = Math::Sin(nx * .5); Real sy = Math::Sin(ny * .5); Real sz = Math::Sin(nz * .5); Real cx = Math::Cos(nx * .5); Real cy = Math::Cos(ny * .5); Real cz = Math::Cos(nz * .5); w = (cz * cy * cx) + (sz * sy * sx); x = (cz * cy * sx) - (sz * sy * cx); y = (cz * sy * cx) + (sz * cy * sx); z = (sz * cy * cx) - (cz * sy * sx); // The resulting quaternion should be already normalized. ASSERT_EQ(*this, getNormalized()); }
/****************** *Euler Conversion* ******************/ void Quaternion::toEuler(Radian &nx, Radian &ny, Radian &nz) { // make sure we only try this with normalized quaternions ASSERT_EQ(*this, getNormalized()); ny = -Math::Asin(2.0 * ((x * z) - (w * y))); Real cy = Math::Cos(ny); if(Math::eq(cy, 0)) { //Gimbal Lock nx = 0.0; nz = Math::Atan2(((x * y) - (w * z)) * 2.0, (1.0 - (x * x) - (z * z)) * 2.0); } else { Real twoInvCy = 2.0 / cy; nx = -Math::Atan2(((y * z) + (w * x)) * twoInvCy, (0.5 - (x * x) - (y * y)) * twoInvCy); nz = Math::Atan2(((x * y) + (w * z)) * twoInvCy, (0.5 - (y * y) - (z * z)) * twoInvCy); } }
void Quaternion::toAngleAxis(Radian &angle, Real &nx, Real &ny, Real &nz) { // make sure we only try this with normalized quaternions ASSERT_EQ(*this, getNormalized()); angle = Math::Acos(w) * 2.0; Real oneOverLength = Math::Sqrt((x * x) + (y * y) + (z * z)); nx = x * oneOverLength; ny = y * oneOverLength; nz = z * oneOverLength; oneOverLength = 1.0 / Math::Sqrt((nx * nx) + (ny * ny) + (nz * nz)); nx *= oneOverLength; ny *= oneOverLength; nz *= oneOverLength; // The resulting axis should be normalized already. ASSERT_EQ(Vector3(nx, ny, nz), Vector3(nx, ny, nz).getNormalized()); }
void OSGWidget::mousePressEvent( QMouseEvent* event ) { m_animateTimer.stop(); m_mouseReleaseJustHappened = false; m_lastMouseEventNDCoords = getNormalized(event->x(), event->y()); m_mouseButtons |= event->buttons(); m_mouseModifiers = event->modifiers(); // handle overrides if (m_mouseButtons == Qt::LeftButton) { if (m_mouseModifiers == Qt::ShiftModifier) { pushState(); m_viewingCore->setViewingCoreMode(ViewingCore::THIRD_PERSON); setMouseMode(MM_PAN); } else if (m_mouseModifiers == Qt::ControlModifier) { pushState(); m_viewingCore->setViewingCoreMode(ViewingCore::THIRD_PERSON); setMouseMode(MM_ORBIT); } else if ((unsigned)m_mouseModifiers == (unsigned)(Qt::ControlModifier | Qt::ShiftModifier) ) { pushState(); m_viewingCore->setViewingCoreMode(ViewingCore::THIRD_PERSON); setMouseMode(MM_ZOOM); } } else if (m_mouseButtons == Qt::RightButton) { m_viewingCore->pickCenter(m_lastMouseEventNDCoords.x(), m_lastMouseEventNDCoords.y() ); } // Do the job asked if (m_mouseMode & (MM_PAN|MM_ROTATE|MM_ORBIT|MM_ZOOM) ) m_viewingCore->setPanStart( m_lastMouseEventNDCoords.x(), m_lastMouseEventNDCoords.y() ); else if (m_mouseMode & MM_PICK_CENTER) { m_viewingCore->pickCenter(m_lastMouseEventNDCoords.x(), m_lastMouseEventNDCoords.y() ); } m_lastMouseEventTime.start(); }
void Enemy::updateMovement(){ auto target = getTarget(); if (!target) { if (velocity.getLengthSq() != 0.f) return; velocity = Vec2::ZERO; } else { auto delta = target->position - position; velocity = delta.getNormalized() * _ATTR(speed); } MoveNoti noti; noti.id = id; noti.start_x = position.x; noti.start_y = position.y; noti.velocity_x = velocity.x; noti.velocity_y = velocity.y; stage->gameroom->sendPacket(noti); }
void Osg3dView::mouseMoveEvent(QMouseEvent *event) { vDebug("mouseMoveEvent"); osg::Vec2d currentNDC = getNormalized(event->x(), event->y()); osg::Vec2d delta = currentNDC - m_savedEventNDCoords; switch (m_mouseMode) { case MM_ORBIT: m_viewingCore->rotate( m_savedEventNDCoords, delta); break; case MM_PAN: m_viewingCore->pan(delta.x(), delta.y()); break; case MM_ZOOM: { double tempScale = m_viewingCore->getFovyScale(); m_viewingCore->setFovyScale(1.03); if(delta.y() > 0) m_viewingCore->fovyScaleDown(); if(delta.y() < 0) m_viewingCore->fovyScaleUp(); m_viewingCore->setFovyScale(tempScale); break; } case MM_ROTATE: m_viewingCore->rotate( m_savedEventNDCoords, delta ); break; default: break; } m_savedEventNDCoords = currentNDC; update(); }
cocos2d::Vec2 SteeringBehaviors::separation() { Vec2 tmpForce; auto tmpIterator = EntityMgr->getEntityMap()->begin(); for (; tmpIterator != EntityMgr->getEntityMap()->end(); tmpIterator++) { auto tmpCharacter = dynamic_cast<GameCharacter*>(tmpIterator->second); if (tmpCharacter == m_pOwner || !isNeighbor(tmpCharacter)) { continue; } auto tmpToOwner = m_pOwner->getMovingEntity().getPosition() - tmpCharacter->getMovingEntity().getPosition(); // 这个驱动力与该角色到owner的距离成反比(注意这里的距离是减去了两个半径后) auto tmpLen = tmpToOwner.getLength() - (m_pOwner->getMovingEntity().getRadius() + tmpCharacter->getMovingEntity().getRadius()); if (tmpLen <= 0) { tmpLen = 1; } tmpForce += m_separationMagnify * tmpToOwner.getNormalized() / tmpLen; } return tmpForce; }
void Graph::draw(int x, int y) { ofPushMatrix(); ofPushStyle(); ofTranslate(x, y); drawPosition = worldToScreen(ofVec2f(0, 0)); ofFill(); ofSetColor(ofMap(ofGetElapsedTimef() - lastTrigger, 0, .5, 255, 0, true)); if(noData) { ofSetColor(128); } ofRect(0, 0, width, height); ofNoFill(); ofSetColor(255); ofPushStyle(); // if(hoverState) { // ofSetHexColor(0xffee00); // ofSetLineWidth(2); // } ofRect(0, 0, width, height); ofPopStyle(); ofRectangle region(1, height - 1, width - 2, -(height - 2)); ofSetHexColor(0xec008c); if(noData) { ofSetColor(200); } drawBuffer(derivativePolyline, threshold, derivativeBox, region); ofSetColor(255); drawBuffer(bufferPolyline, 0, bufferBox, region); ofSetColor(255); drawString(name, 5, 10); if(!buffer.empty() && !derivative.empty()) { ofPushMatrix(); ofTranslate(width, 0); drawString(ofToString(bufferBox.y, 2) + "<" + (buffer.empty() ? "empty" : ofToString(buffer.back(), 2)) + "<" + ofToString(bufferBox.y + bufferBox.height, 2), 5, 10); drawString(ofToString(derivativeBox.y, 2) + "<" + (derivative.empty() ? "empty" : ofToString(derivative.back(), 2)) + "<" + ofToString(derivativeBox.y + derivativeBox.height, 2), 5, 18); drawString(ofToString(threshold, 2) + ", " + ofToString(buffer.back(), 2) + " (" + ofToString(getNormalized(), 2) + ") " + ofToString(derivative.back(), 2), 5, 26); ofPopMatrix(); } ofPopStyle(); ofPopMatrix(); }
float C3Vector::getAngle(const C3Vector& v) const { // Return value is in radian!! C3Vector a(getNormalized()); C3Vector b(v.getNormalized()); return(CMath::robustAcos(a*b)); }
void Fl_Gto::show() const { TlLogging& log = TlLogging::getInstance(); std::stringstream ss; int angular; ss << "----------------------------------------------------------------------" "--\n"; ss << " numbercgto : " + TlUtils::xtos(this->getNumOfCGTOs()) + "\n"; ss << "----------------------------------------------------------------------" "--\n"; for (int i = 0; i < this->getNumOfCGTOs(); i++) { ss << " --- " << i << " th CGTO --------------------\n"; ss << "Snum [" << this->cgto[i].Snum << "]\n"; ss << "Pnum [" << this->cgto[i].Pnum << "]\n"; ss << "Dnum [" << this->cgto[i].Dnum << "]\n"; ss << "basis [" << cgto[i].basisName << "]\n"; ss << "atom [" << cgto[i].atom << "]\n"; ss << "label [" << cgto[i].label << "]\n"; ss << "shellname [" << cgto[i].shellname << "]\n"; ss << "shell " << cgto[i].shell << " \n"; ss << TlUtils::format(" scale factor = %18.8lf\n", cgto[i].scalefactor); ss << TlUtils::format(" contraction = %18ld\n", cgto[i].contraction()); ss << " <normalizedfactor> "; if (getShell(i) == 's') { angular = 0; } else if (getShell(i) == 'p') { angular = 1; } else if (getShell(i) == 'd') { angular = 2; } else if (getShell(i) == 'f') { angular = 3; } else { ss << " *** Fl_Gto::show() not supported such large shell.\n"; ss << " +++ calculate in case of l=m=n=0, and continue.\n"; angular = 0; } for (int l = 0; l <= angular; l++) { for (int m = 0; m <= angular; m++) { for (int n = 0; n <= angular; n++) { if (l + m + n == angular) { ss << TlUtils::format(" (%1ld,%1ld,%1ld) = %18.8lE ", l, m, n, getNormalizedfactor(i, l, m, n)); } } } } ss << "\n"; ss << " // primitive GTO //\n"; for (int j = 0; j < cgto[i].contraction(); j++) { ss << TlUtils::format(" %18.8lE %18.8lE \n", this->cgto[i].pgto[j].exponent, this->cgto[i].pgto[j].coefficient); ss << " <normalized> "; if (getShell(i) == 's') angular = 0; else if (getShell(i) == 'p') angular = 1; else if (getShell(i) == 'd') angular = 2; else if (getShell(i) == 'f') angular = 3; else { ss << " *** Fl_Gto::show() not supported such large shell.\n"; ss << " +++ calculate in case of l=m=n=0, and continue.\n"; angular = 0; } for (int l = 0; l <= angular; l++) { for (int m = 0; m <= angular; m++) { for (int n = 0; n <= angular; n++) { if (l + m + n == angular) { ss << TlUtils::format(" (%1ld,%1ld,%1ld) = %18.8lE %18.8lE \n", l, m, n, getNormalized(i, j, l, m, n), getCoulombnormalized(i, j, l, m, n)); } } } } ss << "\n"; } } ss << " ---------------------------------------------------------------------" "---\n"; log.info(ss.str()); }
/****************************************************************************** * Render the current scene * uses the global variables from the parser *****************************************************************************/ int ntlWorld::renderScene( void ) { #ifndef ELBEEM_PLUGIN char nrStr[5]; // nr conversion std::ostringstream outfn_conv(""); // converted ppm with other suffix ntlRenderGlobals *glob; // storage for global rendering parameters myTime_t timeStart,totalStart,timeEnd; // measure user running time myTime_t rendStart,rendEnd; // measure user rendering time glob = mpGlob; // deactivate for all with index!=0 if((glob_mpactive)&&(glob_mpindex>0)) return(0); /* check if picture already exists... */ if(!glob->getSingleFrameMode() ) { snprintf(nrStr, 5, "%04d", glob->getAniCount() ); if(glob_mpactive) { outfn_conv << glob->getOutFilename() <<"_"<<glob_mpindex<<"_" << nrStr << ".png"; /// DEBUG! } else { // ORG outfn_conv << glob->getOutFilename() <<"_" << nrStr << ".png"; } //if((mpGlob->getDisplayMode() == DM_RAY)&&(mpGlob->getFrameSkip())) { if(mpGlob->getFrameSkip()) { struct stat statBuf; if(stat(outfn_conv.str().c_str(),&statBuf) == 0) { errorOut("ntlWorld::renderscene Warning: file "<<outfn_conv.str()<<" already exists - skipping frame..."); glob->setAniCount( glob->getAniCount() +1 ); return(2); } } // RAY mode } else { // single frame rendering, overwrite if necessary... outfn_conv << glob->getSingleFrameFilename(); } /* start program */ timeStart = getTime(); /* build scene geometry, calls buildScene(t,false) */ glob->getRenderScene()->prepareScene(mSimulationTime); /* start program */ totalStart = getTime(); /* view parameters are currently not animated */ /* calculate rays through projection plane */ ntlVec3Gfx direction = glob->getLookat() - glob->getEye(); /* calculate width of screen using perpendicular triangle diven by * viewing direction and screen plane */ gfxReal screenWidth = norm(direction)*tan( (glob->getFovy()*0.5/180.0)*M_PI ); /* calculate vector orthogonal to up and viewing direction */ ntlVec3Gfx upVec = glob->getUpVec(); ntlVec3Gfx rightVec( cross(upVec,direction) ); normalize(rightVec); /* calculate screen plane up vector, perpendicular to viewdir and right vec */ upVec = ntlVec3Gfx( cross(rightVec,direction) ); normalize(upVec); /* check if vectors are valid */ if( (equal(upVec,ntlVec3Gfx(0.0))) || (equal(rightVec,ntlVec3Gfx(0.0))) ) { errMsg("ntlWorld::renderScene","Invalid viewpoint vectors! up="<<upVec<<" right="<<rightVec); return(1); } /* length from center to border of screen plane */ rightVec *= (screenWidth*glob->getAspect() * -1.0); upVec *= (screenWidth * -1.0); /* screen traversal variables */ ntlVec3Gfx screenPos; /* current position on virtual screen */ int Xres = glob->getResX(); /* X resolution */ int Yres = glob->getResY(); /* Y resolution */ ntlVec3Gfx rightStep = (rightVec/(Xres/2.0)); /* one step right for a pixel */ ntlVec3Gfx upStep = (upVec/(Yres/2.0)); /* one step up for a pixel */ /* anti alias init */ char showAAPic = 0; int aaDepth = glob->getAADepth(); int aaLength; if(aaDepth>=0) aaLength = (2<<aaDepth); else aaLength = 0; float aaSensRed = 0.1; float aaSensGreen = 0.1; float aaSensBlue = 0.1; int aaArrayX = aaLength*Xres+1; int aaArrayY = ( aaLength+1 ); ntlColor *aaCol = new ntlColor[ aaArrayX*aaArrayY ]; char *aaUse = new char[ aaArrayX*aaArrayY ]; /* picture storage */ int picX = Xres; int picY = Yres; if(showAAPic) { picX = Xres *aaLength+1; picY = Yres *aaLength+1; } ntlColor *finalPic = new ntlColor[picX * picY]; /* reset picture vars */ for(int j=0;j<aaArrayY;j++) { for(int i=0;i<aaArrayX;i++) { aaCol[j*aaArrayX+i] = ntlColor(0.0, 0.0, 0.0); aaUse[j*aaArrayX+i] = 0; } } for(int j=0;j<picY;j++) { for(int i=0;i<picX;i++) { finalPic[j*picX+i] = ntlColor(0.0, 0.0, 0.0); } } /* loop over all y lines in screen, from bottom to top because * ppm format wants 0,0 top left */ rendStart = getTime(); glob->setCounterShades(0); glob->setCounterSceneInter(0); for (int scanline=Yres ; scanline > 0 ; --scanline) { debugOutInter( "ntlWorld::renderScene: Line "<<scanline<< " ("<< ((Yres-scanline)*100/Yres) <<"%) ", 2, 2000 ); screenPos = glob->getLookat() + upVec*((2.0*scanline-Yres)/Yres) - rightVec; /* loop over all pixels in line */ for (int sx=0 ; sx < Xres ; ++sx) { if((sx==glob->getDebugPixelX())&&(scanline==(Yres-glob->getDebugPixelY()) )) { // DEBUG!!! glob->setDebugOut(10); } else glob->setDebugOut(0); /* compute ray from eye through current pixel into scene... */ ntlColor col; if(aaDepth<0) { ntlVec3Gfx dir(screenPos - glob->getEye()); ntlRay the_ray(glob->getEye(), getNormalized(dir), 0, 1.0, glob ); /* ...and trace it */ col = the_ray.shade(); } else { /* anti alias */ int ai,aj; /* position in grid */ int aOrg = sx*aaLength; /* grid offset x */ int currStep = aaLength; /* step size */ char colDiff = 1; /* do colors still differ too much? */ ntlColor minCol,maxCol; /* minimum and maximum Color Values */ minCol = ntlColor(1.0,1.0,1.0); maxCol = ntlColor(0.0,0.0,0.0); while((colDiff) && (currStep>0)) { colDiff = 0; for(aj = 0;aj<=aaLength;aj+= currStep) { for(ai = 0;ai<=aaLength;ai+= currStep) { /* shade pixel if not done */ if(aaUse[aj*aaArrayX +ai +aOrg] == 0) { aaUse[aj*aaArrayX +ai +aOrg] = 1; ntlVec3Gfx aaPos( screenPos + (rightStep * (ai- aaLength/2)/(gfxReal)aaLength ) + (upStep * (aj- aaLength/2)/(gfxReal)aaLength ) ); ntlVec3Gfx dir(aaPos - glob->getEye()); ntlRay the_ray(glob->getEye(), getNormalized(dir), 0, 1.0, glob ); /* ...and trace it */ ntlColor newCol= the_ray.shade(); aaCol[aj*aaArrayX +ai +aOrg]= newCol; } /* not used? */ } } /* check color differences */ for(aj = 0;aj<aaLength;aj+= currStep) { for(ai = 0;ai<aaLength;ai+= currStep) { char thisColDiff = 0; if( (fabs(aaCol[aj*aaArrayX +ai +aOrg][0] - aaCol[(aj+0)*aaArrayX +(ai+currStep) +aOrg][0])> aaSensRed ) || (fabs(aaCol[aj*aaArrayX +ai +aOrg][1] - aaCol[(aj+0)*aaArrayX +(ai+currStep) +aOrg][1])> aaSensGreen ) || (fabs(aaCol[aj*aaArrayX +ai +aOrg][2] - aaCol[(aj+0)*aaArrayX +(ai+currStep) +aOrg][2])> aaSensBlue ) ) { thisColDiff = 1; } else if( (fabs(aaCol[aj*aaArrayX +ai +aOrg][0] - aaCol[(aj+currStep)*aaArrayX +(ai+0) +aOrg][0])> aaSensRed ) || (fabs(aaCol[aj*aaArrayX +ai +aOrg][1] - aaCol[(aj+currStep)*aaArrayX +(ai+0) +aOrg][1])> aaSensGreen ) || (fabs(aaCol[aj*aaArrayX +ai +aOrg][2] - aaCol[(aj+currStep)*aaArrayX +(ai+0) +aOrg][2])> aaSensBlue ) ) { thisColDiff = 1; } else if( (fabs(aaCol[aj*aaArrayX +ai +aOrg][0] - aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg][0])> aaSensRed ) || (fabs(aaCol[aj*aaArrayX +ai +aOrg][1] - aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg][1])> aaSensGreen ) || (fabs(aaCol[aj*aaArrayX +ai +aOrg][2] - aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg][2])> aaSensBlue ) ) { thisColDiff = 1; } //colDiff =1; if(thisColDiff) { /* set diff flag */ colDiff = thisColDiff; for(int bj=aj;bj<=aj+currStep;bj++) { for(int bi=ai;bi<=ai+currStep;bi++) { if(aaUse[bj*aaArrayX +bi +aOrg]==2) { //if(showAAPic) aaUse[bj*aaArrayX +bi +aOrg] = 0; } } } } else { /* set all values */ ntlColor avgCol = ( aaCol[(aj+0 )*aaArrayX +(ai+0 ) +aOrg] + aaCol[(aj+0 )*aaArrayX +(ai+currStep) +aOrg] + aaCol[(aj+currStep)*aaArrayX +(ai+0 ) +aOrg] + aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg] ) *0.25; for(int bj=aj;bj<=aj+currStep;bj++) { for(int bi=ai;bi<=ai+currStep;bi++) { if(aaUse[bj*aaArrayX +bi +aOrg]==0) { aaCol[bj*aaArrayX +bi +aOrg] = avgCol; aaUse[bj*aaArrayX +bi +aOrg] = 2; } } } } /* smaller values set */ } } /* half step size */ currStep /= 2; } /* repeat until diff not too big */ /* get average color */ gfxReal colNum = 0.0; col = ntlColor(0.0, 0.0, 0.0); for(aj = 0;aj<=aaLength;aj++) { for(ai = 0;ai<=aaLength;ai++) { col += aaCol[aj*aaArrayX +ai +aOrg]; colNum += 1.0; } } col /= colNum; } /* mark pixels with debugging */ if( glob->getDebugOut() > 0) col = ntlColor(0,1,0); /* store pixel */ if(!showAAPic) { finalPic[(scanline-1)*picX+sx] = col; } screenPos += rightStep; } /* foreach x */ /* init aa array */ if(showAAPic) { for(int j=0;j<=aaArrayY-1;j++) { for(int i=0;i<=aaArrayX-1;i++) { if(aaUse[j*aaArrayX +i]==1) finalPic[((scanline-1)*aaLength +j)*picX+i][0] = 1.0; } } } for(int i=0;i<aaArrayX;i++) { aaCol[(aaArrayY-1)*aaArrayX+i] = aaCol[0*aaArrayX+i]; aaUse[(aaArrayY-1)*aaArrayX+i] = aaUse[0*aaArrayX+i]; } for(int j=0;j<aaArrayY-1;j++) { for(int i=0;i<aaArrayX;i++) { aaCol[j*aaArrayX+i] = ntlColor(0.0, 0.0, 0.0); aaUse[j*aaArrayX+i] = 0; } } } /* foreach y */ rendEnd = getTime(); /* write png file */ { int w = picX; int h = picY; unsigned rowbytes = w*4; unsigned char *screenbuf, **rows; screenbuf = (unsigned char*)malloc( h*rowbytes ); rows = (unsigned char**)malloc( h*sizeof(unsigned char*) ); unsigned char *filler = screenbuf; // cutoff color values 0..1 for(int j=0;j<h;j++) { for(int i=0;i<w;i++) { ntlColor col = finalPic[j*w+i]; for (unsigned int cc=0; cc<3; cc++) { if(col[cc] <= 0.0) col[cc] = 0.0; if(col[cc] >= 1.0) col[cc] = 1.0; } *filler = (unsigned char)( col[0]*255.0 ); filler++; *filler = (unsigned char)( col[1]*255.0 ); filler++; *filler = (unsigned char)( col[2]*255.0 ); filler++; *filler = (unsigned char)( 255.0 ); filler++; // alpha channel } } for(int i = 0; i < h; i++) rows[i] = &screenbuf[ (h - i - 1)*rowbytes ]; writePng(outfn_conv.str().c_str(), rows, w, h); } // next frame glob->setAniCount( glob->getAniCount() +1 ); // done timeEnd = getTime(); char resout[1024]; snprintf(resout,1024, "NTL Done %s, frame %d/%d (took %s scene, %s raytracing, %s total, %d shades, %d i.s.'s)!\n", outfn_conv.str().c_str(), (glob->getAniCount()), (glob->getAniFrames()+1), getTimeString(totalStart-timeStart).c_str(), getTimeString(rendEnd-rendStart).c_str(), getTimeString(timeEnd-timeStart).c_str(), glob->getCounterShades(), glob->getCounterSceneInter() ); debMsgStd("ntlWorld::renderScene",DM_MSG, resout, 1 ); /* clean stuff up */ delete [] aaCol; delete [] aaUse; delete [] finalPic; glob->getRenderScene()->cleanupScene(); if(mpGlob->getSingleFrameMode() ) { debMsgStd("ntlWorld::renderScene",DM_NOTIFY, "Single frame mode done...", 1 ); return 1; } #endif // ELBEEM_PLUGIN return 0; }