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. |