camera AB blend

Blitz3D Forums/Blitz3D Programming/camera AB blend

i wanna do a cutscene in realtime like metal gear solid type... n i have many cameras setup inside my scene... how do i switch my camera just like that to make it more scenic view just like watching a pre-rendered video... and also how do i blend 2 camera view in between switching camera A to B view (view A gradually fade 100%-0% and the same time view B fade 0%-100%)

Hi Akat,

i wrote some functions which may help you setting up a cutscene. But it does not provide you with such a blend function.

Link:
http://www.blitzcoder.com/cgi-bin/showcase/showcase_showentry.pl?id=kstadler03242004174523&comments=no

To do a fade I would assume you need 3 cameras, two of them are you original and destination scenes and the third is used to display the fade. What you would do is render your normal original and destination scenes and grab the renders to place on sprites in front of camera 3. To actually fade just fade one sprite out and one sprite in (EntityAlpha should do it).

Hope that helps.

You should only need two, really - one for the first clip, then the second for the second clip, which renders to a textured quad in front of the first camera. After the dissolve, switch cameras seamlessly and get rid of the first... (I think!)

Here I whipped this up.
Hope it helps.

I'll try adding a wipe effect to it later.

;Camera Fade Demo

SeedRnd MilliSecs()
Graphics3D 800,600,32

; Our 2 cameras.
; For the effect to work, they need to be in different areas...duh!
; I have kept them together for this demo and point them in
; Different directions.
cam1=CreateCamera()
cam2=CreateCamera(cam1)

;Projector is the face we will use to see camera 1
projector=CreateCube(cam2)
ScaleEntity projector,1,1,0.01
MoveEntity projector,-0.001,-0.249,1.01

MoveEntity cam1,0,15,-5
CameraRange cam2,0.1,1000

lit=CreateLight(2)
MoveEntity lit,0,100,-300

;Just a random ground texture
ground=CreatePlane()
groundtex=CreateTexture(256,256)
SetBuffer TextureBuffer(groundtex)
ScaleTexture groundtex,50,50
For sq=1 To 100
	Color Rand(255),Rand(255),Rand(255)
	Rect Rand(256),Rand(256),Rand(256),Rand(256),True
Next
EntityTexture ground,groundtex

;And some stuff to look at
cube=CreateCube()
sphere=CreateSphere()

enttex=CreateTexture(128,128)
ClsColor 250,100,50
SetBuffer TextureBuffer(enttex)
Cls
Color 50,100,250
Oval 0,0,128,128,1
Color 50,250,100
Oval 44,44,40,40,1
EntityTexture cube,enttex
EntityTexture sphere,enttex

cubeflat=CopyEntity(cube)

ScaleEntity cube,3,3,3
MoveEntity cube,15,10,0
MoveEntity sphere,-15,10,0
MoveEntity cubeflat,-15,6,0
ScaleEntity cubeflat,5,2,5

;Camera 1 will look at the cube
;Camera 2 at the sphere
PointEntity cam1,cube
PointEntity cam2,sphere

;This creates the projection texture
proj=CreateTexture(1024,1024)
ScaleTexture proj,1024.0/GraphicsWidth(),1024.0/GraphicsWidth()
EntityTexture projector,proj

;The projector alpha level
projalpha#=1.0
	
SetBuffer BackBuffer()

While Not KeyHit(1)
	;Do some random rotation stuff
	pit#=pit#+(Rnd(2)-1)/10
	yaw#=yaw#+(Rnd(2)-1)/10
	roll#=roll#+(Rnd(2)-1)/10
	
	TurnEntity cube,pit,yaw,roll
	TurnEntity sphere,pit,yaw,roll
	TurnEntity cubeflat,0,-.2,0
	
	;If we need to see Cam 1 then Turn on Camera 1 and hide the projector is case it is in view
	If projalpha>0 Then
		CameraProjMode cam2,0
		CameraProjMode cam1,1
		HideEntity projector
		RenderWorld
	End If	
	
	;If we need to see Camera 2 then Turn on Camera 2 
	If projalpha<1 Then
	
		;If camera 1 is in there as well then 
		;Copy camera 1 To the projector And show the projector
		If projalpha >0 Then
			CopyRect 0,0,800,600,0,0,BackBuffer(),TextureBuffer(proj)
			;This controls the fade
			EntityAlpha projector,projalpha
			ShowEntity projector
		End If
		
		CameraProjMode cam2,1
		CameraProjMode cam1,0
		RenderWorld
		
	End If
	
If KeyDown(205) And projalpha<1.0 Then projalpha=projalpha+0.01
If KeyDown(203) And projalpha>0.0 Then projalpha = projalpha-0.01

Text 10,10,"Cursor Left and Right to Fade - Alpha level = "+projalpha

Flip 1
Wend
End


here you go... not fast.

edit: Now very fast..... store the temp texture in vram with flag 256. this can be done because the program is using a straight copyrect

Graphics3D 800,600,0,0
AmbientLight 200,200,200
SetBuffer BackBuffer()

;--------------------
camera1 = CreateCamera()
HideEntity camera1
tex1 = CreateTexture(GraphicsWidth(),GraphicsHeight(),256)

camera2 = CreateCamera()
TurnEntity camera2,0,180,0
HideEntity camera2
tex2 = CreateTexture(GraphicsWidth(),GraphicsHeight(),256)

fadecam = CreateCamera()
PositionEntity fadecam,3000,0,0
HideEntity fadecam

;--------------------
cone = CreateCone()
MoveEntity cone,0,0,5
EntityColor cone,255,0,0

cube = CreateCube()
MoveEntity cube,-1,0,-5
EntityColor cube,0,255,0

fadesprite1 = CreateSprite()
fadesprite2 = CreateSprite()
PositionEntity fadesprite1,3000,0,1
PositionEntity fadesprite2,3000,0,1
EntityTexture fadesprite1,tex1 : EntityFX fadesprite1,1
EntityTexture fadesprite2,tex2 : EntityFX fadesprite2,1

;--------------------
i#=0
d#=.01
While Not KeyHit(1)
	TurnEntity cone,2,1,2
	TurnEntity cube,2,2,1

	i=i+d
	If i>1 Then d=-d:i=1
	If i<0 Then d=-d:i=0
	EntityAlpha fadesprite1,0+i
	EntityAlpha fadesprite2,1-i

	RenderCamera camera1,tex1
	RenderCamera camera2,tex2
	RenderCamera fadecam
	
	Flip ;False ;uncomment false to not wait for vwait
Wend
End

Function RenderCamera(camera%,texture=False)
	ShowEntity camera
	RenderWorld
	HideEntity camera
	If texture
		CopyRect 0,0,GraphicsWidth(),GraphicsHeight(),0,0,BackBuffer(),TextureBuffer(texture)
	EndIf
End Function


Phil beat me to it... but the vram flag works with his example too.

Hmm, Here I made a couple of minor changes.
VRAM for starters, thanks dmaz, I forgot about that one.
And also forgot to make the projector fullbright in case there is no light shining on it.

Just use this code now

;Camera Fade Demo

SeedRnd MilliSecs()
Graphics3D 800,600,32

; Our 2 cameras.
; For the effect to work, they need to be in different areas...duh!
; I have kept them together for this demo and point them in
; Different directions.
cam1=CreateCamera()
cam2=CreateCamera(cam1)

;Projector is the face we will use to see camera 1
projector=CreateCube(cam2)
ScaleEntity projector,1,1,0.01
MoveEntity projector,-0.001,-0.249,1.01

MoveEntity cam1,0,15,-5
CameraRange cam2,0.1,1000

lit=CreateLight(2)
MoveEntity lit,0,100,-300

;Just a random ground texture
ground=CreatePlane()
groundtex=CreateTexture(256,256)
SetBuffer TextureBuffer(groundtex)
ScaleTexture groundtex,50,50
For sq=1 To 100
	Color Rand(255),Rand(255),Rand(255)
	Rect Rand(256),Rand(256),Rand(256),Rand(256),True
Next
EntityTexture ground,groundtex

;And some stuff to look at
cube=CreateCube()
sphere=CreateSphere()

enttex=CreateTexture(128,128)
ClsColor 250,100,50
SetBuffer TextureBuffer(enttex)
Cls
Color 50,100,250
Oval 0,0,128,128,1
Color 50,250,100
Oval 44,44,40,40,1
EntityTexture cube,enttex
EntityTexture sphere,enttex

cubeflat=CopyEntity(cube)

ScaleEntity cube,3,3,3
MoveEntity cube,15,10,0
MoveEntity sphere,-15,10,0
MoveEntity cubeflat,-15,6,0
ScaleEntity cubeflat,5,2,5

;Camera 1 will look at the cube
;Camera 2 at the sphere
PointEntity cam1,cube
PointEntity cam2,sphere

;This creates the projection texture
proj=CreateTexture(1024,1024,1+256)
ScaleTexture proj,1024.0/GraphicsWidth(),1024.0/GraphicsWidth()
EntityTexture projector,proj
EntityFX projector,1

;The projector alpha level
projalpha#=1.0
	
SetBuffer BackBuffer()

While Not KeyHit(1)
	;Do some random rotation stuff
	pit#=pit#+(Rnd(2)-1)/10
	yaw#=yaw#+(Rnd(2)-1)/10
	roll#=roll#+(Rnd(2)-1)/10
	
	TurnEntity cube,pit,yaw,roll
	TurnEntity sphere,pit,yaw,roll
	TurnEntity cubeflat,0,-.2,0
	
	;If we need to see Cam 1 then Turn on Camera 1 and hide the projector is case it is in view
	If projalpha>0 Then
		CameraProjMode cam2,0
		CameraProjMode cam1,1
		HideEntity projector
		RenderWorld
	End If	
	
	;If we need to see Camera 2 then Turn on Camera 2 
	If projalpha<1 Then
	
		;If camera 1 is in there as well then 
		;Copy camera 1 To the projector And show the projector
		If projalpha >0 Then
			CopyRect 0,0,800,600,0,0,BackBuffer(),TextureBuffer(proj)
			;This controls the fade
			EntityAlpha projector,projalpha
			ShowEntity projector
		End If
		
		CameraProjMode cam2,1
		CameraProjMode cam1,0
		RenderWorld
		
	End If
	
If KeyDown(205) And projalpha<1.0 Then projalpha=projalpha+0.01
If KeyDown(203) And projalpha>0.0 Then projalpha = projalpha-0.01

Text 10,10,"Cursor Left and Right to Fade - Alpha level = "+projalpha

Flip 1
Wend
End



Yeah, I almost forgot about that too... Now all we need is a nice generic function that can be called with 2 camera's or something. so a game loop would be something like

blah

if fade
RenderFade cam1,alpha1,cam2,alpha2
else
RenderWorld
endif
flip

Phil, up for that ;)

well mine works a bit different.
if there is no fading it will only render the needed camera anyway.

But I can make it into a function for sure.
Give me 10 mins.

[edit]
Make that a few hours.
Got busy here all of a sudden :-)
[/edit]

OK here are my routines.

First is the Include file. Save this as "FaderInclude.bb"
Here are the functions:

FadeSetup (LockCameras,[FadeSpeed],[InitialCamera])

This routine will make 2 global cameras called Fade_Cam1 and Fade_Cam2

LockCameras when True will make Fade_Cam1 the parent entity to Fade_Cam2

FadeSpeed sets the speed of the fade.
This is stored in the global variable Fade_Speed
Default value is 10. Accepts any number>0

InitialCamera sets the first camera we will see in the scene.
Defaults to Fade_Cam1
Acceptable values are 1 and 2


RenderFade (DestinationCamera,[tween])

This routine will render your scene exactly like Blitz3D except that it will
fade to the destination camera every call. Should work with tweening as well.
Once the destination camera is reached the routine will only render this camera.

DestinationCamera is the camera we want to see. This can be changed anytime during
a fade.
Acceptable Values are 1 and 2

tween is the tween value passed to the standard RenderWorld.
This defaults To 1 like Blitz.

;Fader Include File

; FadeSetup (LockCameras,[FadeSpeed],[InitialCamera])
;
; This routine will make 2 global cameras called Fade_Cam1 and Fade_Cam2
;
; LockCameras when True will make Fade_Cam1 the parent entity to Fade_Cam2
;
; FadeSpeed sets the speed of the fade.
; This is stored in the global variable Fade_Speed
; Default value is 10. Accepts any number>0
;
; InitialCamera sets the first camera we will see in the scene.
; Defaults to Fade_Cam1
; Acceptable values are 1 and 2


; RenderFade (DestinationCamera,[tween])
; 
; This routine will render your scene exactly like Blitz3D except that it will
; fade to the destination camera every call. Should work with tweening as well.
; Once the destination camera is reached the routine will only render this camera.
;
; DestinationCamera is the camera we want to see. This can be changed anytime during
; a fade.
; Acceptable Values are 1 and 2
;
; tween is the tween value passed to the standard RenderWorld.
; This defaults To 1 like Blitz.

Global Fade_Cam1
Global Fade_Cam2
Global Fade_proj
Global Fade_projalpha#
Global Fade_Speed
Global Fade_Projector

Function FadeSetup(lock,speed=10,destcam=1)
	Fade_Speed=speed
	Fade_Cam1=CreateCamera()
	Fade_Cam2=CreateCamera()
	
	If lock Then EntityParent Fade_Cam2,Fade_Cam1
	
	Fade_Projector=CreateCube(Fade_Cam2)
	ScaleEntity Fade_Projector,1,1,0.01
	MoveEntity Fade_Projector,-0.001,-0.249,1.01
	CameraRange Fade_Cam2,0.1,1000
	
	Fade_proj=CreateTexture(1024,1024,1+256)
	ScaleTexture Fade_proj,1024.0/GraphicsWidth(),1024.0/GraphicsWidth()
	EntityTexture Fade_Projector,Fade_proj
	EntityFX Fade_Projector,1
	
	If destcam=2 Then HideEntity Fade_Projector Else Fade_projalpha#=1.0
	
End Function
	
Function RenderFade(destcam,tween#=1)
	If destcam<1 Or destcam>2 Then destcam=1
	If destcam=2 And Fade_projalpha>0 Then Fade_projalpha=Fade_projalpha-(Fade_Speed/1000.0)
	If destcam=1 And Fade_projalpha<1 Then Fade_projalpha=Fade_projalpha+(Fade_Speed/1000.0)
	
	HideEntity Fade_Projector

	If Fade_projalpha>0 Then
		CameraProjMode Fade_Cam2,0
		CameraProjMode Fade_Cam1,1
		RenderWorld tween
	End If	

	If Fade_projalpha<1 Then
	
		If Fade_projalpha >0 Then
			CopyRect 0,0,800,600,0,0,BackBuffer(),TextureBuffer(Fade_proj)
			EntityAlpha Fade_Projector,Fade_projalpha
			ShowEntity Fade_Projector
		End If
		
		CameraProjMode Fade_Cam2,1
		CameraProjMode Fade_Cam1,0
		RenderWorld
		
	End If
End Function



And here is my previous example now using the new functions.

;Camera Fade Demo

Include "FaderInclude.bb"

SeedRnd MilliSecs()
Graphics3D 800,600,32

dest=1
FadeSetup(True,10,dest)

MoveEntity Fade_Cam1,0,15,-5

lit=CreateLight(2)
MoveEntity lit,0,100,-300

;Just a random ground texture
ground=CreatePlane()
groundtex=CreateTexture(256,256)
SetBuffer TextureBuffer(groundtex)
ScaleTexture groundtex,50,50
For sq=1 To 100
	Color Rand(255),Rand(255),Rand(255)
	Rect Rand(256),Rand(256),Rand(256),Rand(256),True
Next
EntityTexture ground,groundtex

;And some stuff to look at
cube=CreateCube()
sphere=CreateSphere()

enttex=CreateTexture(128,128)
ClsColor 250,100,50
SetBuffer TextureBuffer(enttex)
Cls
Color 50,100,250
Oval 0,0,128,128,1
Color 50,250,100
Oval 44,44,40,40,1
EntityTexture cube,enttex
EntityTexture sphere,enttex
SetBuffer BackBuffer()

cubeflat=CopyEntity(cube)

ScaleEntity cube,3,3,3
MoveEntity cube,15,10,0
MoveEntity sphere,-15,10,0
MoveEntity cubeflat,-15,6,0
ScaleEntity cubeflat,5,2,5

;Camera 1 will look at the cube
;Camera 2 at the sphere
PointEntity Fade_Cam1,cube
PointEntity Fade_Cam2,sphere
	

While Not KeyHit(1)
	;Do some random rotation stuff
	pit#=pit#+(Rnd(2)-1)/10
	yaw#=yaw#+(Rnd(2)-1)/10
	roll#=roll#+(Rnd(2)-1)/10
	
	TurnEntity cube,pit,yaw,roll
	TurnEntity sphere,pit,yaw,roll
	TurnEntity cubeflat,0,-.2,0

If KeyDown(59) Then dest=1
If KeyDown(60) Then dest=2

RenderFade(dest)

Text 10,10,"F1 = Camera 1"
Text 10,20,"F2 = Camera 2"
Text 10,30,"Destination Camera = "+dest

Flip True
Wend
End



Great, but I don't like giving over the camera setup. Shouldn't FadeSetup just set up the projector? How about the user define the fade camera's as any camera and then just pass those? So your RenderFade would except 2 real cameras and just fade between them base on which was first. Also FadeSetup doesn't do anything with Fade_Speed, that should also be a param to RenderFade.

like
cam1=createcamera()
cam2=createcamera()
cam3=createcamera()
FadeSetup()
RenderFade(cam1,cam3,speed)  ; RenderFade(from_camera,to_camera,speed,[tween])

then later back again
RenderFade(cam3,cam1,speed)

don't want to step on your toes ;) but wouldn't that be more cleaner? also having speed in RenderFade allows the programmer to pass a nice sin wave in for speed so you can get a nice speedup and slowdown to the effect... much more versatile.

Well you can do whatever you like with it now :-)

Personally I am quite happy with it.
I did it in the routine mainly because the projector needs to be attached to camera 2.
What diff does it make if the user makes the cameras or the routine? The user still has access to both cameras.

I wanted to keep RenderFade as simple as possible hence why i put fade_speed in the setup.

If you want to vary the speed of the fade just modify the Fade_Speed variable. It is a global.

Right I understand, I hope this doesn't come off wrong. Just that when building shared routines/libraries is good practice to distance yourself from the programmer’s main code. it should be all rolled up into a little black box.

The shared functions shouldn't make any requirements on the programmers main code if possible. The programmer should be able to do everything(mostly) through exported functions and not have to rely on changing the guts. Now I understand that Blitz3D holds us back a little here because of it dependencies on globals but the practice is sound and just makes for cleaner routines and programs.

So the reason that the user makes the cameras instead of the routine is because it's the user's program and you never know what they will be doing with cameras or how they will be configuring them. For instance, your routine does not work for the original question in which Akat stated that there were many cameras defined and he wanted to fade between any two.

Those were/are just some suggestions, I didn't/don't mean any offense. :)

No offense taken..at all !!

Sorry if my comments came across rude. That wasn't my intention.

I was just saying why I did it the way I did.
I agree with you on alot of points.

So when I have added extra features to it(wipes, dissolves etc), I will repost my new version. OK :-)

hey great, no worries. :)

wo... the thread become battle a bit - great cooperation guys (no battle actually)... i could use it - and by the way, inside metal gear solid snake eater: this girl said that in future there will be realtime movie which is u can control it like switch the camera angle and multiple ending path... i give a hint, im working on it now, at least im one of the first who doing it in future... now the storyboard are done and all of the scenes... only left the programming part which i can put ur guys codes there... thanx a lot! u got the credit by now...