예제 #1
0
Float2<T> Float2<T>::slerp(const Float2 &end, T percent) const
{
	T theta = static_cast<T>(std::acos(this->dot(end) / (this->length() * end.length())));
	T sinThetaRecip = static_cast<T>(1.0 / std::sin(theta));
	T beginScale = static_cast<T>(std::sin((1.0 - percent) * theta) * sinThetaRecip);
	T endScale = std::sin(percent * theta) * sinThetaRecip;
	return this->scaledBy(beginScale) + end.scaledBy(endScale);
}
예제 #2
0
void HotCubeCube::start()
{
	BaseGameCube::start();

	Float2 panning;
	panning.set(0, 0);
	buffer->bg1.setMask(BG1Mask::filled(vec(4,7), vec(8,2)));
	buffer->bg1.text(vec(4,7), BlackFont, "          ");
	buffer->bg1.setPanning(panning);
}
예제 #3
0
파일: cube.cpp 프로젝트: honnet/SifteoGame
// compute velocity & position (cube included) and draw dot (exploded or not)
void Cube::animate(Cube* cubes, const float dts) {
    static const float deadzone = 2.0f;
    static const float accelScale = 0.6f;
    static const float damping = 0.995f;

    if (lifeCounter <= 0)
        return;

    for (uint8_t d=0; d<dot_n; d++) {
        // if dot neither hidden nor exploded, animate it:
        if (not (vid.sprites[d].isHidden() || dots[d].exp)) {
            Float2 accel = id.accel().xy();
            if (accel.len2() > deadzone * deadzone)
                dots[d].vel += accel * accelScale;
            dots[d].vel *= damping;
            Float2 step = dots[d].vel * dts;
            Float2 candidate = dots[d].pos + step;

            // Does this dot want to leave the cube ?
            Side mySide = (candidate.y < minPos.y) ? TOP    : //  0
                          (candidate.x < minPos.x) ? LEFT   : //  1
                          (candidate.y > maxPos.y) ? BOTTOM : //  2
                          (candidate.x > maxPos.x) ? RIGHT  : //  3
                          NO_SIDE; // -1
            bool stayHere = true;   // default
            CubeID hisID;           // neighbor CubeID
            Side hisSide = NO_SIDE; // his side number that touches mySide

            if (mySide != NO_SIDE) {          // avoids cubeAt(NO_SIDE) error
                Neighborhood myNbh(id);
                hisID = myNbh.cubeAt(mySide);
                if (hisID.isDefined()) {      // ...same with sideOf(NO_SIDE)
                    Neighborhood hisNbh(hisID);
                    hisSide = hisNbh.sideOf(id);
                    stayHere = cubes[hisID].isFull();
                }
            }
            if (stayHere) {                         // will this dot stay?
                if (mySide==TOP || mySide==BOTTOM)  // bounce vertically?
                    dots[d].vel.y = -dots[d].vel.y;
                if (mySide==LEFT || mySide==RIGHT)  // ...horizontally?
                    dots[d].vel.x = -dots[d].vel.x;

                dots[d].pos += dots[d].vel * dts;   // finish calculation
                vid.sprites[d].setImage(DotIMG);    // draw the dot
                vid.sprites[d].move(dots[d].pos);
            } else {                                // move to neighbor
                dots[d].pos += step;                // finish calculation
                moveDot(d, cubes[hisID], mySide, hisSide);
            }
        }
    }
    collisionCheck();
    displayDamages();
}
예제 #4
0
Int2 Questioner::doPanning(Int2 targetPan, int timetaken)
{
	if(timetaken > TIME_TO_SCROLL)
	{
		myGameDrawer->doPanning(myCube, targetPan);
		return targetPan;
	}

	float panningPropTimeLeft = (TIME_TO_SCROLL - timetaken) / (float) TIME_TO_SCROLL;
	
	Float2 diffPan = vec((float) 0, panningPropTimeLeft * PIXEL_SCROLL);
	Float2 newPan = targetPan + diffPan;

	myGameDrawer->doPanning(myCube, newPan.round());

	return newPan.round();
}
예제 #5
0
void AppSetup::onResizeWindow(const Int2& newSize)
{
	m_inf.windowSize = newSize;

	Float2 newSizeF = Float2((float)newSize.width(), (float)newSize.height());
	Float2 virtualSizeF = Float2((float)m_inf.virtualSize.width(), (float)m_inf.virtualSize.height());

	if (m_inf.automaticFitToWindowSize && (newSize.width() != m_inf.virtualSize.width() || newSize.height() != m_inf.virtualSize.height()))
	{
		Float2 ppp(-1.f,-1.f);
		Int2 virtualPos(-1,-1);

		float ratioW = (float)newSize.width() / (float)m_inf.virtualSize.width();
		float ratioH = (float)newSize.height() / (float)m_inf.virtualSize.height();
		if (m_inf.virtualSizeAllowRatioDeformation)
		{
			ppp = Float2(ratioW,ratioH);
			virtualPos = Int2(0,0);
		}
		else if (newSizeF.width()/newSizeF.height() > virtualSizeF.width() / virtualSizeF.height())
		{
			ppp = Float2(ratioH,ratioH);
			virtualPos = Int2((int)((newSizeF.width()-virtualSizeF.width()*ratioH)/2.f), 0);
		}
		else
		{
			ppp = Float2(ratioW,ratioW);
			virtualPos = Int2(0, (int)((newSizeF.height()-virtualSizeF.height()*ratioW)/2.f));
		}
		
		this->setPixelPerPointLowLevel(ppp, virtualPos);
	}
	else
	{
		this->setPixelPerPointLowLevel(Float2(1.f,1.f), Int2(0,0));
#if defined(USES_WINDOWS_OPENGL) || defined(USES_LINUX)
		m_openGL->setRealWindowSize(newSize);
		m_openGL->set2DMode();
#else
		// do nothing here
#endif
	}

	m_isUsingVirtualSize = (this->getPixelPerPoint() != Float2(1.f, 1.f) || this->getVirtualTopLeftCornerInWindow() != Int2(0, 0));
}
예제 #6
0
파일: main.cpp 프로젝트: meh2481/Siftrinth
static void onTouch(void* ctxt, unsigned cube)
{
	if(g_iCurMode & MODE_GAMEOVER && boards[cube].hasMarble())	//Tap on the "game over" cube to restart
	{
		//Play sound effect for clearing board (also board reset-- why not?)
		channels[BOARD_SFX_CHANNEL]->play(sBoardClear);
		for(int i = 0; i < NUM_CUBES; i++)
		{
			boards[i].getVid()->bg1.eraseMask();	//Wipe "game over" screen
			boards[i].initTilemap();	//Load a new tilemap into each
			boards[i].takeMarble();
		}
		//Add marble to first cube
		Float2 fVel;
		fVel.set(0,0);
		Float2 fPos = LCD_center;
		fPos.x += TILE_WIDTH/2.0;
		fPos.y += TILE_HEIGHT/2.0;
		boards[0].addMarble(fPos, fVel);
		
		//Other starting tasks
		for(int i = 0; i < NUM_COLORS; i++)
			g_bColorsUsed[i] = false;
		g_iScore = -1;
		g_iCurMode = BOARD_NOTHING;
		for(int i = 0; i < NUM_CUBES; i++)
			g_starsCollected[i] = 0;
		g_iBoardReset = -1;
	}
	if(g_iCurMode & BOARD_WAITPORTAL && boards[cube].hasMarble())	//Tap on the flashy arrow cube to ignore portal
	{
		boards[cube].spitBack();	//Spit marble back out
		//Play sound effect for exiting a portal
		channels[PORTAL_CHANNEL]->play(sPortalExit);
		g_iCurMode = BOARD_NOTHING;
		for(int iCube = 0; iCube < NUM_CUBES; iCube++)
		{
			//Hide any flashy arrows
			boards[iCube].hideArrows();
			boards[iCube].resetFlashTimer();
		}
	}
}
예제 #7
0
파일: main.cpp 프로젝트: amgregoi/Sifteo
RGB565 calculateMandelbrot(UInt2 pixel)
{
    /*
     * Calculate one pixel of a Mandelbrot fractal,
     * using continuous shading based on a renormalizing technique.
     *
     * Reference: http://linas.org/art-gallery/escape/escape.html
     */

    const float radius2 = 400.f;
    const unsigned maxIters = 12;
    const float scale = 0.022f;
    const Int2 center = LCD_center + vec(25, 0);

    // We use Float2 vectors to store complex numbers
    Float2 z = vec(0, 0);
    Float2 c = (pixel - center) * scale;
    unsigned iters = 0;
    float modulus2;

    // Traditional Mandelbrot iteration
    do {
        z = z.cmul(z) + c;
        modulus2 = z.len2();
    } while (++iters <= maxIters && modulus2 <= radius2);

    // A couple extra iterations
    z = z.cmul(z) + c;
    z = z.cmul(z) + c;
    iters += 2;

    // Continuous shading, taking into account the iteration number as well
    // as how far outside the escape radius we are.
    float mu = (iters - log(log(z.len())) / M_LN2) / maxIters;

    if (mu < 1.0f) {
        // Exterior of fractal
        return calculateColorPalette(mu);
    } else {
        // Interior (didn't escape within our limit, or NaN)
        return RGB565::fromRGB(0x000000);
    }
}
예제 #8
0
	void drawTextLayout(ID2D1DeviceContext* context, const Float2& zoomRatio, ID2D1SolidColorBrush* solidBrush, IDWriteTextLayout* textLayout, const Int2& position, const Float2& scale)
	{
		D2D1_MATRIX_3X2_F transformTmp;
		context->GetTransform(&transformTmp);
		context->SetTransform(D2D1::Matrix3x2F::Translation(zoomRatio.x() + (float)position.x() / scale.x(), zoomRatio.y() + (float)position.y() / scale.y()));// * s_ppp.x() * s_ppp.y(
		// TODO scale with s_ppp

		context->DrawTextLayout(D2D1::Point2F(0.0f, 0.0f), textLayout, solidBrush);

		context->SetTransform(transformTmp);
	}
예제 #9
0
파일: cube.cpp 프로젝트: honnet/SifteoGame
// check distance between dots and mark them as exploded if too close
void Cube::collisionCheck() {
    for (uint8_t i=0; i<dot_n; i++)
        if (not vid.sprites[i].isHidden() && !dots[i].exp)
            for (uint8_t j=i+1; j<dot_n; j++)
                if (not vid.sprites[j].isHidden() && !dots[i].exp)  {
                    Float2 dif = dots[i].pos - dots[j].pos;
                    // are the dots too close ?
                    if (dif.len2() < SPR_size.len2()/4) {
                        dots[i].pos -= dif/2; // bring dots closer
                        dots[j].pos += dif/2; // to each other
                        dots[i].exp = exploDuration;
                        dots[j].exp = exploDuration;
#if ACCURATE == 1
                        // use a binary map to check if we hit or miss Conan:
                        dots[i].bnd = isHit(dots[i].pos);
                        dots[j].bnd = isHit(dots[j].pos);
#else
                        // ...or use a FlatAssetImage but it's less accurate:
                        Float2 o = SPR_size/2; // offset to sprite center
                        uint16_t linPosI = uint16_t( (dots[i].pos.x+o.x)/8 ) +
                                           uint16_t( (dots[i].pos.y+o.y)/8 ) *
                                           ConanIMG.tileWidth() ;
                        uint16_t linPosJ = uint16_t( (dots[j].pos.x+o.x)/8 ) +
                                           uint16_t( (dots[j].pos.y+o.y)/8 ) *
                                           ConanIMG.tileWidth() ;
                        // D'oh! need band aid ?
                        dots[i].bnd = (ConanIMG.tile(linPosI) != whiteTile);
                        dots[j].bnd = (ConanIMG.tile(linPosJ) != whiteTile &&
                                       linPosJ  != linPosI);
#endif
                        // D'oh! need band aid ?
                        if (dots[i].bnd)
                            lifeCounter -= 5;
                        if (dots[j].bnd)
                            lifeCounter -= 5;
                    }
                }

    if (lifeCounter <= 0)
        win();
}
예제 #10
0
	void drawLine(ID2D1DeviceContext* context, const Float2& zoomRatio, const Int2& pos1, const Int2& pos2, const Color& color, float thickness)
	{
		D2D1::ColorF colorDx(color.r() / 256.f, color.g() / 256.f, color.b() / 256.f, color.a() / 256.f);
		//D2D1::ColorF colorDx = D2D1::ColorF::MidnightBlue;
		ID2D1SolidColorBrush* solidBrush;
		DX::ThrowIfFailed(context->CreateSolidColorBrush(colorDx, &solidBrush));

		D2D1_POINT_2F pt1;
		pt1.x = zoomRatio.x() + (float)pos1.x();
		pt1.y = zoomRatio.y() + (float)pos1.y();
		D2D1_POINT_2F pt2;
		pt2.x = zoomRatio.x() + (float)pos2.x();
		pt2.y = zoomRatio.y() + (float)pos2.y();
		context->SetTransform(D2D1::Matrix3x2F::Identity());
		//s_context->SetDpi(DirectXDraw::getDefaultDpi().x(), DirectXDraw::getDefaultDpi().y());

		context->DrawLine(pt1, pt2, solidBrush, thickness);

		solidBrush->Release();
		//delete solidBrush;
	}
예제 #11
0
	void writeScore(int i)
	{
		int maskWidth = 2;
		
		cubeVideo[cube].bg1.setMask(BG1Mask::filled(vec(0,12), vec(maskWidth * 2, 4)));
		text.set(-64 + maskWidth * 6, 52);
		
		String<3> bTest;
		bTest << Fixed(i, maskWidth, true);
		
		textTarget = text;
		writeText(bTest.c_str());
	}
예제 #12
0
	void drawRoundedRectangle(ID2D1DeviceContext* context, const Float2& zoomRatio, const Int2& posLeftTop, const Int2& posRightBottom, const Color& color, float round, float borderSize, bool fill)
	{
		D2D1::ColorF colorDx(color.r() / 256.f, color.g() / 256.f, color.b() / 256.f, color.a() / 256.f);
		ID2D1SolidColorBrush* solidBrush;
		DX::ThrowIfFailed(context->CreateSolidColorBrush(colorDx, &solidBrush));

		D2D1_ROUNDED_RECT rrect;
		rrect.radiusX = round;
		rrect.radiusY = round;
		rrect.rect.left = zoomRatio.x() + (float)posLeftTop.x();
		rrect.rect.top = zoomRatio.y() + (float)posLeftTop.y();
		rrect.rect.right = zoomRatio.x() + (float)posRightBottom.x();
		rrect.rect.bottom = zoomRatio.y() + (float)posRightBottom.y();
		context->SetTransform(D2D1::Matrix3x2F::Identity());

		if (fill) context->FillRoundedRectangle(rrect, solidBrush);
		//if (borderSize > 0.f) 
		context->DrawRoundedRectangle(rrect, solidBrush, borderSize);

		solidBrush->Release();
		//delete solidBrush;
	}
예제 #13
0
	void update(TimeDelta timeStep)
	{
		//LOG("Update");
		if (whichGame == 0)
		{
			cubeVideo[cube].bg0.image(vec(0,0), BackgroundXTwo);
		}
		else if (whichGame == 1)
		{
			cubeVideo[cube].bg0.image(vec(0,0), BackgroundYTwo);
		}
		
		writeScore(shakeScore);

		Int2 accel = cubeVideo[cube].physicalAccel().xy();
		float delta;
		
		if (whichGame == 0)
		{
			delta = accel.x - lastAccel.x;
		}
		else if (whichGame == 1)
		{
			delta = accel.y - lastAccel.y;
		}
        
		delta = Sifteo::abs(delta);
		
		shakeCounter += delta;
		
		if (shakeCounter > 1000)
		{
			shakeCounter -= 1000;
			shakeScore++;
		}
				
		lastAccel = accel;
        
        cubeVideo[cube].bg1.setPanning(text.round());
	}
예제 #14
0
	void drawBitmap(
		ID2D1DeviceContext* context, const Float2& zoomRatio, const Float2& m_defaultDpi, 
		ID2D1Bitmap* bitmap, const Float2& position, const Float2& scale, float opacity, D2D1_RECT_F* rectSource, D2D1_RECT_F* rectDest, float angleDegree, const Int2& rotationCenterPos, 
		bool horizontalMirror, bool verticalMirror)
	{
		D2D1_MATRIX_3X2_F transformTmp;
		context->GetTransform(&transformTmp);

		D2D1::Matrix3x2F matTranslation = D2D1::Matrix3x2F::Translation(zoomRatio.x() + position.x(), zoomRatio.y() + position.y());//  / scale.x() / scale.y()
		
		if (angleDegree != 0.f || horizontalMirror || verticalMirror)
		{
			D2D1::Matrix3x2F matMirroring = D2D1::Matrix3x2F::Scale(horizontalMirror ? -1.f : 1.f, verticalMirror ? -1.f : 1.f);
			D2D1_POINT_2F imageRotationCenterPos = D2D1::Point2F((float)rotationCenterPos.x(), (float)rotationCenterPos.y());
			D2D1::Matrix3x2F matRotation = D2D1::Matrix3x2F::Rotation(angleDegree, imageRotationCenterPos);
			context->SetTransform(matMirroring * matRotation * matTranslation);
		}
		else
		{
			context->SetTransform(matTranslation);// * s_ppp.x() * s_ppp.y()
		}

		//Assert(scale.x() > 0.f && scale.y() > 0.f);
		
		// note about bitmaps: https://msdn.microsoft.com/en-us/library/windows/desktop/dd371150%28v=vs.85%29.aspx
		Float2 dpiBitmap;
		bitmap->GetDpi(&dpiBitmap.data[0], &dpiBitmap.data[1]);

		Float2 scaleToApply = dpiBitmap / m_defaultDpi * scale;//s_ppp * dpiBitmap / dpiContext * scale;

		D2D1_RECT_F rectDestFinal;
		if (rectDest == 0)
		{
			D2D1_SIZE_F sz = bitmap->GetSize();
			rectDestFinal.left = 0.f;
			rectDestFinal.top = 0.f;
			rectDestFinal.right = sz.width * scaleToApply.x();
			rectDestFinal.bottom = sz.height *scaleToApply.y();

			context->DrawBitmap(bitmap, &rectDestFinal, opacity, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, rectSource);
		}
		else
		{
			rectDestFinal = *rectDest;
			rectDestFinal.left *= scaleToApply.x();
			rectDestFinal.top *= scaleToApply.y();
			rectDestFinal.right *= scaleToApply.x();
			rectDestFinal.bottom *= scaleToApply.y();

			Float2 srcScaleToApply = dpiBitmap / m_defaultDpi;

			D2D1_RECT_F rectSourceFinal;
			rectSourceFinal = *rectSource;
			rectSourceFinal.left /= srcScaleToApply.x();
			rectSourceFinal.top /= srcScaleToApply.y();
			rectSourceFinal.right /= srcScaleToApply.x();
			rectSourceFinal.bottom /= srcScaleToApply.y();

			context->DrawBitmap(bitmap, &rectDestFinal, opacity, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, &rectSourceFinal);
		}

		context->SetTransform(transformTmp);//D2D1::Matrix3x2F::Translation(0.f, 0.f));
		//s_context->Flush();
	}
예제 #15
0
Int2 AppSetup::getSizeOrtho2DWindow() const
{
	Float2 ppp = this->getPixelPerPoint();
	return Int2((int)((float)m_inf.windowSize.x() / ppp.x()), (int)((float)m_inf.windowSize.y() / ppp.y()));
}
예제 #16
0
파일: main.cpp 프로젝트: meh2481/Siftrinth
void main()
{
	//Create our audio channels
	AudioChannel a1(0);
	AudioChannel a2(1);
	AudioChannel a3(2);
	AudioChannel a4(3);
	AudioChannel a5(4);
	AudioChannel a6(5);
	channels[0] = &a1;
	channels[1] = &a2;
	channels[2] = &a3;
	channels[3] = &a4;
	channels[4] = &a5;
	channels[5] = &a6;
	r.seed();
	
	channels[BALL_ROLL_CHANNEL]->play(sRollLoop, REPEAT);	//Start playing rolling marble noise
	channels[BALL_ROLL_CHANNEL]->setVolume(0);
	for(int i = 0; i < NUM_CUBES; i++)
		g_starsCollected[i] = 0;
	for(int i = 0; i < NUM_COLORS; i++)
		g_bColorsUsed[i] = false;
	g_iBoardReset = -1;
	g_iScore = -1;
    TimeStep ts;
	float fTapPromptDelay = 0.0;
	int iBoardDied;

	//Initialize our boards
	for(int i = 0; i < NUM_CUBES; i++)
		boards[i].init(i);
	Events::neighborAdd.set(onNeighborAdd);	//Function for when two cubes touch each other
	Events::cubeTouch.set(onTouch);			//Function for when a cube is tapped
	
	//Add the marble to one of them
	Float2 fVel;
	fVel.set(0,0);
	Float2 fPos = LCD_center;
	fPos.x += TILE_WIDTH/2.0;
	fPos.y += TILE_HEIGHT/2.0;
	boards[0].addMarble(fPos, fVel);
	
	TextDraw td;
	bool bFirstSound = true;
	
	//Main loop
    while (1) 
	{
        ts.next();
		for(int i = 0; i < NUM_CUBES; i++)
		{
			int iMode;
			switch(g_iCurMode)
			{
				case BOARD_NOTHING:
					iMode = boards[i].update(float(ts.delta()));
					//Update our rolling sound to the right volume
					if(boards[i].hasMarble())
					{
						float fVol = boards[i].getMarbleVelocity() * 0.9;
						if(fVol > MAX_VOLUME)
							fVol = MAX_VOLUME;
						channels[BALL_ROLL_CHANNEL]->setVolume(fVol);
					}
					if(iMode & BOARD_GOTPOINT)
					{
						iMode ^= BOARD_GOTPOINT;
						g_iScore++;
						if(++g_starsCollected[i] == NUM_STARS_CUBE)
							g_iBoardReset = i;
						//Play sound for getting a star, but not right on reset
						if(bFirstSound)
							bFirstSound = false;
						else
							channels[BALL_SFX_CHANNEL]->play(sGetStar);
					}
					if(iMode & BOARD_DIED)
					{
						//Show game over screen
						iMode ^= BOARD_DIED;
						iMode |= MODE_GAMEOVER;
						td.draw(boards[i].getVid(), "Game over", 6);
						String<64> s;
						s << "Score: " << g_iScore;
						td.draw(boards[i].getVid(), s.c_str(), 8);
						fTapPromptDelay = 0.0;
						iBoardDied = i;
						bFirstSound = true;
						channels[BALL_ROLL_CHANNEL]->setVolume(0);
						channels[BALL_SFX_CHANNEL]->play(sDie);
					}
					if(iMode & BOARD_LEFT)
					{
						iMode ^= BOARD_LEFT;
						if(g_iBoardReset == i)
						{
							boards[i].reset(g_bColorsUsed);
							g_starsCollected[i] = 0;
							g_iBoardReset = -1;
							g_iScore += 3;	//Three points for clearing board
							//Play sound effect for clearing board
							channels[BOARD_SFX_CHANNEL]->play(sBoardClear);
						}
						//Play pass-through-portal sound
						else if(!channels[PORTAL_CHANNEL]->isPlaying())
							channels[PORTAL_CHANNEL]->play(sThroughPortal);
					}
					if(iMode & BOARD_WAITPORTAL)
					{
						//Play sound effect for entering a portal
						channels[PORTAL_CHANNEL]->play(sPortalEnter);
						channels[BALL_ROLL_CHANNEL]->setVolume(0);
					}
					g_iCurMode = iMode;
					break;
				case BOARD_WAITPORTAL:
					boards[i].waitPortal(float(ts.delta()));
					channels[BALL_ROLL_CHANNEL]->setVolume(0);
					break;
				case MODE_GAMEOVER:
					fTapPromptDelay += float(ts.delta()) / 3.0;
					if(fTapPromptDelay >= TAP_PROMPT_DELAY && fTapPromptDelay < 100.0)
					{
						fTapPromptDelay = 100;
						td.draw(boards[iBoardDied].getVid(), "Tap to restart", 14);
					}
					channels[BALL_ROLL_CHANNEL]->setVolume(0);
			}
		}
		
        System::paint();
    }
}
예제 #17
0
void Renderer::fitViewNearFarToObjects(Float2& near_far,
                                       const Float4x4& view, const float near_min, const float far_max,
                                       const bool inc_light_vols) const {
    near_far.set(near_min, far_max);
    return;

    // Note, the fitting is NOT tight.   Firstly, we're using the geometry's
    // axis aligned bounding box, which is not tight (after the model
    // transform) then we're assuming the size of the box is maximum after
    // rotation into the camera space (which is also not tight).

    // Recall: OpenGL convention is to look down the negative Z axis,
    //         therefore, more negative values are actually further away.
    near_far[0] = -std::numeric_limits<float>::infinity();  // znear
    near_far[1] = std::numeric_limits<float>::infinity();  // zfar

    float min_z, max_z;

    gm_->renderStackReset();
    while (!gm_->renderStackEmpty()) {
        GeometryInstance* cur_geometry = gm_->renderStackPop();
        AABBox* aabbox = cur_geometry->aabbox();
        if (aabbox) {
            aabbox->calcMinMaxZBoundInViewSpace(min_z, max_z, view);
            if (max_z < near_far[1]) {
                near_far[1] = max_z;
            }
            if (min_z > near_far[0]) {
                near_far[0] = min_z;
            }
        }
    }

    // Also fit to light geometry:
    if (inc_light_vols) {
        Float3 pos_source;
        Float3 dir;
        float rad;
        Float3 center_view;
        LightPoint* light_point;
        LightSpot* light_spot;
        for (uint32_t i = 0; i < lighting_->lights().size(); i++) {
            switch (lighting_->lights()[i]->type()) {
            case LIGHT_POINT:
                light_point = (LightPoint*)(lighting_->lights()[i]);
                // Calculate model view projection matrix
                Float3::affineTransformPos(center_view, view,
                                           light_point->pos_world());
                rad = light_point->outside_rad();
                if ((center_view[2] - rad) < near_far[1]) {
                    near_far[1] = center_view[2] - rad;
                }
                if ((center_view[2] + rad) > near_far[0]) {
                    near_far[0] = center_view[2] + rad;
                }
                break;
            case LIGHT_SPOT_VSM:
            case LIGHT_SPOT:
                light_spot = (LightSpot*)(lighting_->lights()[i]);
                // Check the source point
                Float3::affineTransformPos(pos_source, view,
                                           light_spot->pos_world());
                if (pos_source[2] < near_far[1]) {
                    near_far[1] = pos_source[2];
                }
                if (pos_source[2] > near_far[0]) {
                    near_far[0] = pos_source[2];
                }
                // Now check the cone end
                Float3::affineTransformPos(center_view, view,
                                           light_spot->cone_center_world());
                rad = light_spot->cone_outside_radius();
                if ((center_view[2] - rad) < near_far[1]) {
                    near_far[1] = center_view[2] - rad;
                }
                if ((center_view[2] + rad) > near_far[0]) {
                    near_far[0] = center_view[2] + rad;
                }
                break;
            default:
                break;
            }
        }
    }

    near_far[0] += LOOSE_EPSILON;
    near_far[1] -= LOOSE_EPSILON;

    // now clamp the near and far to the user defined values
    if (near_far[0] > near_min) {
        near_far[0] = near_min;
    }
    if (near_far[1] < far_max) {
        near_far[1] = far_max;
    }
    if (near_far[1] > near_far[0]) {
        near_far[1] = near_far[0] - 0.1f;
    }
}