real time wall mirror
Blitz3D Forums/Blitz3D Programming/real time wall mirror
| ||
| I searched for a real time wall mirror, but I only found terrible pseudo code, which was not working correct. Now I started to build a "wall mirror class" project, which will enable everybody a free to position, free rotation mirror, which is able to mirror all scenes, including free moving camera aspects. this is a first code, which is correct as long as the mirror in standing vertical on the floor. (all textures and object in this image are code based and help only to understand the method. in nice rooms the mirror shows nice mirror image) this is the code:
; Definitionin of the mirror
Global Mirror
Global MirrorCamera
Global MirrorTexture
Global MirrorPlan
; this part constructs only a simple virtual room for the demo
Graphics3D 1024,768,32,2
AntiAlias 1
; Licht
AmbientLight 111,111,111
Licht= CreateLight(1)
MoveEntity licht, -5,10,10
RotateEntity licht, 45,45,0
LightColor Licht, 255,222,222
Licht2= CreateLight(1)
MoveEntity licht2, 5,10,10
RotateEntity licht2, 45,-45,0
LightColor Licht2, 222,222,252
licht3=CreateLight(3)
LightRange licht3,1090
RotateEntity licht3,270,270,0
MoveEntity licht3,-2,-2,-4
;Camera
Global Camera=CreateCamera()
kommode=CreatePivot()
SeedRnd MilliSecs()
MaterialBreite#=0.02
MoveEntity kommode, 0,0,0
PositionEntity Camera, -2,1,-5
RotateEntity Camera, 0,0,0
CameraViewport Camera,20,20,620,620
; Der Raum
Raum=CreateCube()
FlipMesh raum
EntityColor Raum,115,82,42
MoveEntity raum, 1,2.82,-4.47
ScaleEntity raum,6,4,5
; Die Kommode
Dim Wand(99)
Dim Fuss(99)
Dim Schub(99)
TexName$="holz.png"
Holz=LoadTexture(TexName)
If holz=0 Then
Holz=CreateTexture(256,256,0)
SetBuffer TextureBuffer(holz)
Color 102,61,4
Rect 0,0,256,256
Color 112,71,24
For i=0 To 1000
Oval Rand(0,255),Rand(0,255),2,50
Next
SetBuffer BackBuffer()
EndIf
RotateTexture Holz, 90
ScaleTexture Holz,1,0.3
; linke wand
Wand(0)=CreateCube (Kommode)
ScaleEntity wand(0),MaterialBreite,1,0.5
MoveEntity wand(0), -1.5,0,0
EntityColor Wand(0),211,211,211
EntityTexture Wand(0),Holz
; rechte wand
Wand(1)=CreateCube (Kommode)
ScaleEntity wand(1),MaterialBreite,1,0.5
MoveEntity wand(1), 1.5,0,0
EntityColor Wand(1),191,191,191
EntityTexture Wand(1),Holz
; oben
Wand(2)=CreateCube (Kommode)
ScaleEntity wand(2),1.6,2*MaterialBreite,0.55
MoveEntity wand(2), 0,1,-0.05
EntityTexture Wand(2),Holz
; unten
Wand(3)=CreateCube (Kommode)
ScaleEntity wand(3),1.55,MaterialBreite,0.51
MoveEntity wand(3), 0,-1,0
;EntityColor Wand(3),Rand(100,255),Rand(100,255),Rand(100,255)
EntityColor Wand(3),111,111,111
EntityTexture Wand(3),Holz
; hinten
Wand(4)=CreateCube (Kommode)
ScaleEntity wand(4),1.50,0.97,MaterialBreite
MoveEntity wand(4), 0,0,0.5
;EntityColor Wand(3),Rand(100,255),Rand(100,255),Rand(100,255)
EntityColor Wand(4),11,11,11
;EntityTexture Wand(3),Holz
; fuss
fuss(0)=CreateSphere (8,Kommode)
ScaleEntity fuss(0),0.1,0.1,0.1
MoveEntity fuss(0), -1.4,-1.1,-0.4
EntityColor fuss(0),48,33,24
Fuss(1)=CopyEntity(Fuss(0),Kommode)
MoveEntity fuss(1), +2.8,0,0
Fuss(2)=CopyEntity(Fuss(0),Kommode)
MoveEntity fuss(2), 0,0,0.8
Fuss(3)=CopyEntity(Fuss(0),Kommode)
MoveEntity fuss(3), +2.8,0,0.8
; Schublade
;holz=LoadTexture(TexName)
ScaleTexture holz,1,0.4
RotateTexture holz, 90
Schub(0)=CreatePivot(Kommode)
MoveEntity Schub(0),-0.76,0.625,-0.55
;
SchubZier=CreateCube(Schub(0))
ScaleEntity SchubZier,0.75,0.3,MaterialBreite
MoveEntity SchubZier, 0,0,0
EntityTexture SchubZier,holz
;EntityColor SchubZier,Rand(100,255),Rand(100,255),Rand(100,255)
;
SchubKnopf=CreateCylinder(16,True,Schub(0))
ScaleEntity SchubKnopf, 0.1,0.03,0.02
MoveEntity SchubKnopf,0,0,-0.1
TurnEntity SchubKnopf,90,0,0
EntityColor SchubKnopf,155,155,155
EntityColor SchubKnopf,48,33,24
EntityShininess SchubKnopf,1
;
SchubWangeL=CreateCube(Schub(0))
ScaleEntity SchubWangeL,MaterialBreite,0.25,0.5
MoveEntity SchubWangeL, -0.65,0,0.5
EntityColor SchubWangeL,211,211,211
EntityTexture SchubWangeL,holz
;
;HideEntity SchubWangel
SchubWangeR=CopyEntity (Schubwangel,Schub(0))
MoveEntity SchubWangeR, 1.3,0,0
EntityColor SchubWangeR,169,169,188
;
SchubBoden=CreateCube(Schub(0))
ScaleEntity SchubBoden,0.65,MaterialBreite,0.5
MoveEntity SchubBoden, 0,-0.25,0.5
EntityColor SchubBoden,151,151,151
EntityTexture SchubBoden,holz
;
SchubRueck=CreateCube(Schub(0))
ScaleEntity SchubRueck,0.65,0.25,MaterialBreite
MoveEntity SchubRueck, 0,0,1
EntityColor SchubRueck,111,111,91
EntityTexture SchubRueck,holz
For I=1 To 6
;EntityColor SchubZier,Rand(100,255),Rand(100,255),Rand(100,255)
Schub(i)=CopyEntity (Schub(0),Kommode)
Next
MoveEntity Schub(1),1.52,0,0
MoveEntity Schub(2),0,-0.63,0
MoveEntity Schub(3),1.52,-0.63,0
MoveEntity Schub(4),0,-1.26,0
MoveEntity Schub(5),1.52,-1.26,0
;Kommode2=CopyEntity(Kommode)
;MoveEntity kommode2,4,0,-2
; restliches Mobiliar
Wuerfel=CreateCube()
ScaleEntity wuerfel,0.5,1,0.5
MoveEntity wuerfel, 0,-1,-4
EntityColor wuerfel, 0,0,55
Lampe=CreateSphere(8)
;ScaleEntity Lampe, 0.5,0.5,0.5
MoveEntity Lampe, 0,4,-2
EntityColor lampe,55,213,222
Saeule=CreateCylinder(8,0)
ScaleEntity Saeule,0.5,5,0.5
EntityColor Saeule, 111,111,111
MoveEntity Saeule, -4,2,0
EntityShininess Saeule,1
Teppich=CreateCube()
ScaleEntity Teppich, 8,0.001,8
MoveEntity teppich, 3,-1.15,-6
EntityColor teppich, 55,0,0
r=1
X=100
Dim Regal(9)
Regal(0)=CreateCube()
ScaleEntity regal(0) ,0.5,0.05,2
EntityColor Regal(0), 111,211,111
MoveEntity Regal(0),6.6,0,-4
EntityShininess Regal(0),1
For i= 1 To 4
Regal(i)=CopyEntity(Regal(0))
MoveEntity regal(i),0,i*0.5,0
Next
; Spiegel Init !!!!!!!!!!!!!!!!
InitMirror
; Main Loop
Repeat
PointEntity camera, wand(2)
ScaleEntity Kommode, 1,1,1
RenderMirror Camera, MirrorCamera
UpdateWorld
RenderWorld
Color 202,161,114
Text 700,400,"W A L L M I R R O R D E M O "
Text 700,460,"<E> and <R> to rotate Mirror"
Text 700,490,"<+> and <-> to up/down camera"
Text 700,520,"<curosr keys> to move camera"
Text 700,580,"<ESC> to Quit"
Text 100,680,"(C) M I D I M A S T E R M U S I C E D U C A T I O N S O F T W A R E www.midimaster.de "
Flip
; Schublade auf/zu
If (x>100) And (r=1) Then
r=-1.0
Else If (x<0) Then
r=1
EndIf
x=x+r
MoveEntity schub(3),0,0,r*0.007
;DebugLog x + " " + r
;Steuerung
a%=GetKey()
If a>0 Then
DebugLog "Key: " + a
; EndIf
If a=31 Then
MoveEntity camera,0.3,0,0
EndIf
If a=30 Then
MoveEntity camera,-0.3,0,0
EndIf
If a=28 Then
MoveEntity camera,0,0,0.3
EndIf
If a=29 Then
MoveEntity camera,0,0,-0.3
EndIf
If a=45 Then
MoveEntity camera,0,-0.3,0
EndIf
If a=43 Then
MoveEntity camera,0,0.3,0
EndIf
If a=114 Then
TurnEntity camera,0,3,0
EndIf
If a=108 Then
TurnEntity camera,0,-3,0
EndIf
If a=101 Then
TurnEntity mirror,0,-3,0
EndIf
If a=114 Then
TurnEntity mirror,0,3,0
EndIf
If a=27 Then
End
EndIf
EndIf
Forever
; Spiegel-Funktionen
Function InitMirror()
mirror = CreatePivot()
MirrorCamera = CreateCamera()
; ScaleEntity MirrorCamera, 0.02,0.02,0.02
CameraViewport MirrorCamera,700,100,256,256
PositionEntity mirror, 3,1,-1
RotateEntity mirror,0,90,0
; the glas plane:
MirrorPlan=CreateCube(mirror)
ScaleEntity mirrorPlan,1,1,0.0003
MirrorTexture = CreateTexture(256,256,256)
ScaleTexture MirrorTexture,1,1
EntityFX mirrorPlan,9
EntityTexture mirrorPlan,MirrorTexture
; only for the nice frame:
SpiegelRahmen=CreateCube(mirror)
ScaleEntity Spiegelrahmen,1.05,0.05,0.05
MoveEntity SpiegelRahmen,0,1,0
EntityColor SpiegelRahmen, 65,25,0
SpiegelRahmen2=CopyEntity(SpiegelRahmen,mirror)
MoveEntity SpiegelRahmen2,0,-2,0
SpiegelRahmen3=CreateCube(mirror)
ScaleEntity Spiegelrahmen3,0.05,2.0,0.05
MoveEntity SpiegelRahmen3,1,-0.5,0
EntityColor SpiegelRahmen3, 65,25,0
SpiegelRahmen4=CopyEntity(SpiegelRahmen3,mirror)
MoveEntity SpiegelRahmen4,-2,0,0
End Function
Function RenderMirror(Camera,MirrorCamera)
;switch camera
CameraProjMode Camera,0
CameraProjMode MirrorCamera,1
; mirror camera to the mirror
PositionEntity MirrorCamera, EntityX(Mirror),EntityY(Mirror),EntityZ(Mirror)
CameraZoom MirrorCamera,1.5
HideEntity Mirror
; find out the angle between Original-camera und mirror
; save old values
Winkel_Y=EntityYaw(Camera)
Winkel_X=EntityPitch(Camera)
PointEntity Camera,MirrorCamera
; D I E F O R M E L :
RotateEntity MirrorCamera, 360-2*EntityPitch(Mirror)+EntityPitch(Camera),180+2*EntityYaw(Mirror)-EntityYaw(Camera),0
; photo from this to the MirrorPlan
UpdateWorld
RenderWorld
; side inversion
For i=1 To 256
CopyRect 700+i,100,1,256,256-i,0,BackBuffer(),TextureBuffer(MirrorTexture)
Next
; adjust original camera back
ShowEntity Mirror
RotateEntity Camera,Winkel_X,winkel_Y,0
CameraProjMode Camera,1
CameraProjMode MirrorCamera,0
End Function
done: - free positioning in rooms changes mirror image correct - turning of the mirror changes mirror image correct - free camera position and orientation changes mirror image correct - depending on this 3 factores, the mirror images folows the camera optical correct to do: - rolling of the mirror on his z-axis not implemented - "reverse zoom effect" when approaching mirror not implemented - no class at the moment |
| ||
| but I only found terrible pseudo code, which was not working correct Pseudocode generally doesn't work at all. That's why its called pseudocode. |
| ||
| Yes.... ...but i was not marked as pseudo code. The code was offered as a "how to code a wall mirror". This old code was terrible and should be replaced. But don't let us talk about the old stuff! Did you test the new mirror? I am not sure, that it is worth for the code archive... |
| ||
| Are you refering to this? http://www.blitzbasic.com/codearcs/codearcs.php?code=1524 |
| ||
| No, that a nice example...and it works! But he has the same problems like me. A rotation at the z-axis produces errors. When you rotate the mirror like a steering wheel, the world inside should stand still. I added this to his code to test it:
...
While Not KeyDown(1)
...
Text 10,50, mirror_distance#
;new added:
TurnEntity mirror_object,0,0,0.3
;
Flip
Wend
....
|
| ||
| Provided the mirror is flat, however you will still see effects of the CAMERA zoom dependant on where the mirror is located with respect to the camera. |
| ||
| whats the reason to not using simple cubemapping? |
| ||
| is it possible in cubemapping to render the mirror view correct to position and orientation of the camera with light situation? i am not sure... I thought with cubemapping you always render the same direction of the mirror-camera and use it all the time. when moving the original camera beside such a mirror. the image inside the mirror looks like a photo of the room, or? this is what a algorithm has to do: With a view in a mirror the direction of the "mirror camera" depents on the master camera angles to the mirror and interacts with the camera movement. Can you show me a sample of a elemtar cubemapping code to test it? I would be happy if a solution with cubemapping works better then my code. |
| ||
| search the code archives...it has been done a dozens times. reflection is the main purpose of cube mapping. there're also samples in the manuals: http://blitzbasic.com/b3ddocs/command.php?name=SetCubeFace&ref=3d_cat |
| ||
| ok, I saw this sample, but I cannot test it, because in my Blitz3D there aren't these media objects. I remember i have seen them in an older version of Blitz3D.... I will test it, but I cannot believe that these fixed camera angles (90°,... etc) will interact with a moving main camera... And the algorithm need 6x renderworld, which costs a lot of time. Can somebody test for me, what happens if the teacup is standing still and the camera moves. Does the mirror image change? move? sizes? |
| ||
| I'm sure at least the demo version lets you play with the samples. |
| ||
| According to a poster on this entry in the archives, that code is faster than cube mapping. http://www.blitzbasic.com/codearcs/codearcs.php?code=1524 |
| ||
| I will test it, but I cannot believe that these fixed camera angles (90°,... etc) will interact with a moving main camera... of course it does. if you look at the following line: Position camera where the entity is - this is where we will be rendering views from for cubemap PositionEntity camera,EntityX#(entity),EntityY#(entity),EntityZ#(entity) u will see, that the render camera which is used to render the cubemap is positioned at the mirror position, which basically means the cubemap will show, what the mirror "sees". the cubemap texture shader will take care of the correct view matrix... please stop moaning, and start trying. it works and has been done infinite times. this will be my last words on this topic. thank you and good luck. |
| ||
| to OJay: I don't want to moan. Sorry, but my english is not very good and sometimes I may use the wrong words, so it seems to sound agressiv. But this is not my intention. I want to discuss about mirror coding. I try to find these media objects to test the demo, then try to enter this cubemapping mirror into my demo and compare, what happens. What makes me wonder in your code above, is the aspect, that the mirror cam is positioned at the mirror, ok! But it has to turn depenting on the master cameras view. Example Picture: Object "B"
Object ooo
"A"
oooo
oooo
oooo
mirror
/
/
/
[]
camera
( is there a possibility to upload picture to blitzbasic forum?) With cubemapping you will see the big object "A" in the mirror in a real mirror you will see only object "B" |
| ||
I have to say, I also tried a mirror (on a wall) using cubemapping, and I found it relative fiddleworkish. I remember I had it partially working, but it wasn't exact science and most disturbing was the fact, that the mirror didn't have the same resolution as the rest of the world. It works kind of for water:![]() Other methods are: a seperate Render from the right angle and position, then texture the mirror with this render somehow - still the resolution problem. When you watch Blitz's interal CreateMirror then you realize: it looks best when the geometry is simply dublicated and flipped - at the cost of additional geometry. Blitz's CreateMirror only works when there is nothing below it, because it "mirrors in both directions". This makes it hard to use and probably rather useless. Now, what you could do is: clone the parts that may become visible in the mirror an flip them along the mirrors axis. Then do an additional render only with these new parts, then put this render onto the main render, using some kind of mask process, so only the surface of the mirror will be painted by the additional render. Probably your flipped new parts should contain a big black wall around the mirror, this would allow to DrawImage the mirror Render onto the main render. This would also mean you have to duplicate the player mesh when he's within the view range of the mirror (or eg. inside a helper box) - not a big deal IMHO. If the flipped geometry is created dynamicly, or if you add it to the map, it doesn't make much diffrence, although the 2nd way may be easier. But this kind of mirror probably isn't very useful in anything other than typical indoor enviroments, eg. bathroom with mirror... |
| ||
| I'd go for the render from bounce angle from the camera. Your resolution will be a tid rubbish, but you can choose a smaller texture size the further away you get from the mirror. |
| ||
| For the resolution, a mirror's CameraZoom (FOV) is (unless the mirror is concave/convex) is only dependant on the distance. However the VIEWER's cameraZoom can affect the the mirror too, especially if the mirror object lies on the edges of the viewerer-camera's render. The only applicable 'solution' to the effect of the viewer's camerazoom is to Limit the camera-Zoom of the mirror's render AND to ensure the Viewer's camera zoom is a constistent and ~90 degree FOV * The Mirror-Render-Camera also needs to be rotated an equivalent amount to the angles of incidence (difference between the mirror object angles and the viewer camera's angles) across the dimensions of the Mirror Object, and CameraZoom widened or shortened to match the distance of the viewer from the mirror object. Although at extreme camera-zoom / FOV angles the render can appear distorted, these distortions should remain at the boundaries of the mirror object and OUTSIDE the viewer camera's render of the mirror object when the viewer-camera is close enough to the mirror so that edges of the mirror object are not seen. For example, stand close to a mirror from the side, and what you can see is only a very thin slice of reflection, however the reflection would be of the farside of the room away from you. Standing face on, you would see yourself and what's behind you. The previously reflected far sides of the room to the left and right (and of course, whatever is BEHIND the mirror) would now be beyond the mirror's reflection. |
| ||
| Here's something I did -- yikes! -- 7 years ago: http://www.sendspace.com/file/393319 It's far from perfect (problems at extreme angles, such as Malice mentions), but something else to play with. (Apologies for using SendSpace, as I can't access my FTP at present.) |
| ||
| Hi! You can use FastExt library for mirrors (with single additional RenderWorld for reflection map). The algorithm is completely identical to the water system. |
