Text über Objekt ausserhalb des Viewports anzeigen
Text über Objekt ausserhalb des Viewports anzeigen
Hallo PBler,
ich möchte in meinem Projekt einen Text überhalb eines (3D-)Objekts darstellen. Das klappt auch super, solange das Objekt innerhalb des Viewports ist, da ich mir die Koordinaten des Objekts mittels CameraProjectionX/Y hole und dann dort den Text hinzeichne. Jetzt hätte ich gerne, daß wenn das Objekt den Viewport z.B. nach rechts verlässt, der Text am rechten Bildschirmrand weiterhin angezeigt wird, was mit den CameraProjection-Befehlen nicht mehr funktioniert, da diese dann -1 zurückgeben.
Die Sache ist einfach, wenn das Objekt den Viewport verlässt, da ich ja dann einfach die letzte Position an welcher das Objekt im Viewport war speichern kann und weiterhin dort den Text anzeigen. Wenn jedoch ein Objekt nie im Viewport war und es erscheint sagen wir mal links von der Kamera/dem Viewport und kommt dann ins Bild hat sich das mit dem Koordinaten speichern erledigt.
Hat von euch einer eine gute Idee parat wie ich sowas umsetzen kann?
Gruß
MAC
ich möchte in meinem Projekt einen Text überhalb eines (3D-)Objekts darstellen. Das klappt auch super, solange das Objekt innerhalb des Viewports ist, da ich mir die Koordinaten des Objekts mittels CameraProjectionX/Y hole und dann dort den Text hinzeichne. Jetzt hätte ich gerne, daß wenn das Objekt den Viewport z.B. nach rechts verlässt, der Text am rechten Bildschirmrand weiterhin angezeigt wird, was mit den CameraProjection-Befehlen nicht mehr funktioniert, da diese dann -1 zurückgeben.
Die Sache ist einfach, wenn das Objekt den Viewport verlässt, da ich ja dann einfach die letzte Position an welcher das Objekt im Viewport war speichern kann und weiterhin dort den Text anzeigen. Wenn jedoch ein Objekt nie im Viewport war und es erscheint sagen wir mal links von der Kamera/dem Viewport und kommt dann ins Bild hat sich das mit dem Koordinaten speichern erledigt.
Hat von euch einer eine gute Idee parat wie ich sowas umsetzen kann?
Gruß
MAC
Windows XP 32-bit SP3, Windows 7 64-bit, PB 4.60, PB 5.11, PB 5.20
- Chimorin
- Beiträge: 451
- Registriert: 30.01.2013 16:11
- Computerausstattung: MSI GTX 660 OC mit TwinFrozr III
6Gb DDR 3 RAM
AMD Phenom II X4 B55 @ 3,6GHz
Windows 7 Home Premium 64-bit
Re: Text über Objekt ausserhalb des Viewports anzeigen
Gut, so könnte das funktionieren:
1. Du erstellst eine Textur.
2. Du malst mit DrawText() deinen Text darauf.
3. Aus Textur wird Material gemacht.
4. Mit dem Material erstellst du eine Billboardgruppe an der Stelle bei deinem Objekt, nur halt drüber.
5. Du fügst ein Billboard mit den relativen Kooordinaten 0/0/0 hinzu.
6. fertig.
P.S. Die Billboardgruppe und die Textur würde ich am Anfang des Programms erstellen, das Material der Billboardgruppe kann auch im Nachhinein geändert werden.
1. Du erstellst eine Textur.
2. Du malst mit DrawText() deinen Text darauf.
3. Aus Textur wird Material gemacht.
4. Mit dem Material erstellst du eine Billboardgruppe an der Stelle bei deinem Objekt, nur halt drüber.
5. Du fügst ein Billboard mit den relativen Kooordinaten 0/0/0 hinzu.
6. fertig.
P.S. Die Billboardgruppe und die Textur würde ich am Anfang des Programms erstellen, das Material der Billboardgruppe kann auch im Nachhinein geändert werden.
Re: Text über Objekt ausserhalb des Viewports anzeigen
Danke, aber das ist nicht mein Problem. Den Text habe ich schon auf dem Bildschirm, es geht mir darum, daß der Text nicht mit dem Objekt über den Bildschirmrand hinaus verschwinden soll, sondern daß er dann sichtbar am Bildschirmrand verharren soll, selbst wenn das Objekt schon raus ist. Also quasi so: Objekt ist im Bild -> Text wird über dem Objekt dargestellt (funktioniert schon); Kamera dreht nach links bis das Objekt auf der rechten Seite den Viewport verlässt -> Text soll am rechten Bildschirmrand stehen bleiben, so das man erkennen kann, das rechts ausserhalb des Bildschirm noch ein Objekt ist.
Ich brauche also im Grunde genommen eine Funktion die mir sagt: ein Objekt ist links/rechts/oben/unten vom Viewport. In anderen 3D-Engines haben die Projection-Funktionen immer Koordinaten zurückgegeben die halt größer/kleiner waren als die Koordinaten im Screen und so konnte man dann abfragen (PseudoCode):
PB liefert hier allerdings keine Koodinaten ausserhalb des Screen-Bereichs zurück, sondern -1 wenn das Objekt nicht im Screen ist, was diese Vorgehensweise unmöglich macht.
Ich brauche also im Grunde genommen eine Funktion die mir sagt: ein Objekt ist links/rechts/oben/unten vom Viewport. In anderen 3D-Engines haben die Projection-Funktionen immer Koordinaten zurückgegeben die halt größer/kleiner waren als die Koordinaten im Screen und so konnte man dann abfragen (PseudoCode):
Code: Alles auswählen
If ProjectionX>ScreenWidth
TextX=ScreenWidth-TextFeldBreite
EndIf
If ProjectionX<0
TextX=0
EndIf
Windows XP 32-bit SP3, Windows 7 64-bit, PB 4.60, PB 5.11, PB 5.20
- Makke
- Beiträge: 156
- Registriert: 24.08.2011 18:00
- Computerausstattung: AMD Ryzen 7 5700X - AMD Radeon RX 6800 XT - 32 GB DDR4 SDRAM
- Wohnort: Ruhrpott
- Kontaktdaten:
Re: Text über Objekt ausserhalb des Viewports anzeigen
Hi,
den Text erstellst Du ja im 3D Raum wenn ich das richtig verstanden habe, Du müsstest noch ein paar Infos mehr geben, z.B.:
- bedienst Du tatsächlich alle drei Achsen (Beispiel: Luftkampfspiel) oder nur zwei Achsen (Beispie: 3D Shooter) ?
- sollen immer alle Objecte außerhalb des Viewports "am Bildrand" kleben oder nur ein bestimmtes (Beispiel: Flugzeug hat einen Gegner im Target, der verfolgt werden soll)
- weiterhin ist noch wichtig welchen FieldOfView Wert (CameraFOV()) Du benutzt
Ich meine sowas schon im OGRE Forum gelesen zu haben, das das (nur) über eine Projektions-Matrix zu lösen ist. Das schöne an OGRE ist, das viele Berechnungen zu Matricen und Quaternions mitgeliefert werden, in PB musst Du Dir leider alles selber zusammenschreiben.
den Text erstellst Du ja im 3D Raum wenn ich das richtig verstanden habe, Du müsstest noch ein paar Infos mehr geben, z.B.:
- bedienst Du tatsächlich alle drei Achsen (Beispiel: Luftkampfspiel) oder nur zwei Achsen (Beispie: 3D Shooter) ?
- sollen immer alle Objecte außerhalb des Viewports "am Bildrand" kleben oder nur ein bestimmtes (Beispiel: Flugzeug hat einen Gegner im Target, der verfolgt werden soll)
- weiterhin ist noch wichtig welchen FieldOfView Wert (CameraFOV()) Du benutzt
Ich meine sowas schon im OGRE Forum gelesen zu haben, das das (nur) über eine Projektions-Matrix zu lösen ist. Das schöne an OGRE ist, das viele Berechnungen zu Matricen und Quaternions mitgeliefert werden, in PB musst Du Dir leider alles selber zusammenschreiben.
---
Windows 11 (64 bit)
Windows 11 (64 bit)
Re: Text über Objekt ausserhalb des Viewports anzeigen
Da ich sowas bereits geschrieben habe, hier mal meine Variante:
Es ermittelt die CameraProjection, und wenn diese -1 ergibt, rechnet er mit Matrizen.
ExamineCameraProjection() muss dabei die Camera, die Koordinaten und die Bildschirmgröße bekommen.
Außerdem kann ein Padding angegeben werden, jenachdem, wie viel Abstand zum Bildschirmrand sein soll.
Sry, für den CodeStil, aber ich hab das eben aus meinem Projekt rausgerissen.
Es ermittelt die CameraProjection, und wenn diese -1 ergibt, rechnet er mit Matrizen.
ExamineCameraProjection() muss dabei die Camera, die Koordinaten und die Bildschirmgröße bekommen.
Außerdem kann ein Padding angegeben werden, jenachdem, wie viel Abstand zum Bildschirmrand sein soll.
Sry, für den CodeStil, aber ich hab das eben aus meinem Projekt rausgerissen.
Code: Alles auswählen
;- Vector3D und Matrix3D
Structure Vector3
X.f
Y.f
Z.f
EndStructure
Structure Matrix3
A11.f : A12.f : A13.f
A21.f : A22.f : A23.f
A31.f : A32.f : A33.f
EndStructure
Procedure.i V3_Set(*Use.Vector3, X.f, Y.f, Z.f)
*Use\X = X
*Use\Y = Y
*Use\Z = Z
ProcedureReturn *Use
EndProcedure
Procedure.f V3_Length(*Source.Vector3)
ProcedureReturn Sqr(*Source\X * *Source\X + *Source\Y * *Source\Y + *Source\Z * *Source\Z)
EndProcedure
Procedure.i V3_Multiply(*Use.Vector3, Value.f)
*Use\X * Value
*Use\Y * Value
*Use\Z * Value
ProcedureReturn *Use
EndProcedure
Procedure.i V3_Subtraction(*Use.Vector3, *Source1.Vector3, *Source2.Vector3)
*Use\X = *Source1\X - *Source2\X
*Use\Y = *Source1\Y - *Source2\Y
*Use\Z = *Source1\Z - *Source2\Z
ProcedureReturn *Use
EndProcedure
Procedure.i V3_Normalize(*Use.Vector3)
Protected Length.f = V3_Length(*Use)
If Length
*Use\X / Length
*Use\Y / Length
*Use\Z / Length
EndIf
ProcedureReturn *Use
EndProcedure
Procedure.i V3_SetLength(*Use.Vector3, Length.f)
V3_Normalize(*Use)
V3_Multiply(*Use, Length)
ProcedureReturn *Use
EndProcedure
Procedure.i V3_Rotate(*Use.Vector3, *Source.Matrix3)
Protected Buffer.Vector3
CopyMemory(*Use, @Buffer, SizeOf(Vector3))
*Use\X = Buffer\X**Source\A11 + Buffer\Y**Source\A12 + Buffer\Z**Source\A13
*Use\Y = Buffer\X**Source\A21 + Buffer\Y**Source\A22 + Buffer\Z**Source\A23
*Use\Z = Buffer\X**Source\A31 + Buffer\Y**Source\A32 + Buffer\Z**Source\A33
ProcedureReturn *Use
EndProcedure
Procedure M3_Inverse(*Use.Matrix3, *Source.Matrix3)
Protected Factor.f
With *Source
Factor.f = 1 / (\A11*\A22*\A33-\A13*\A22*\A31+\A12*\A23*\A31+\A13*\A21*\A32-\A11*\A23*\A32-\A12*\A21*\A33)
*Use\A11 = (\A22*\A33-\A23*\A32) * Factor
*Use\A12 = (\A13*\A32-\A12*\A33) * Factor
*Use\A13 = (\A12*\A23-\A13*\A22) * Factor
*Use\A21 = (\A23*\A31-\A21*\A33) * Factor
*Use\A22 = (\A11*\A33-\A13*\A31) * Factor
*Use\A23 = (\A13*\A21-\A11*\A23) * Factor
*Use\A31 = (\A21*\A32-\A22*\A31) * Factor
*Use\A32 = (\A12*\A31-\A11*\A32) * Factor
*Use\A33 = (\A11*\A22-\A12*\A21) * Factor
EndWith
EndProcedure
Procedure M3_Orientation(*Use.Matrix3, X.f, Y.f, Z.f, W.f)
With *Use
\A11 = W*W+X*X-Y*Y-Z*Z
\A12 = 2*X*Y-2*W*Z
\A13 = 2*X*Z+2*W*Y
\A21 = 2*X*Y+2*W*Z
\A22 = W*W-X*X+Y*Y-Z*Z
\A23 = 2*Y*Z-2*W*X
\A31 = 2*X*Z-2*W*Y
\A32 = 2*Y*Z+2*W*X
\A33 = W*W-X*X-Y*Y+Z*Z
EndWith
EndProcedure
;- Camera Projection
Structure CameraProjection
X.f
Y.f
Distance.f
Direction.f
EndStructure
Global CameraProjection.CameraProjection
Procedure ExamineCameraProjection(Camera.i, X.f, Y.f, Z.f, Width.i, Height.i, Padding.f=0.0)
Protected ProjectionX.f = CameraProjectionX(Camera, X, Y, Z)
Protected ProjectionY.f = CameraProjectionY(Camera, X, Y, Z)
Protected Direction.Vector3, CameraDirection.Vector3
Protected Projection.Vector3, Length.f, Inverse.Matrix3, Orientation.Matrix3
V3_Set(Direction, X-CameraX(Camera), Y-CameraY(Camera), Z-CameraZ(Camera))
CameraProjection\Distance = V3_Length(Direction)
If ProjectionX = -1 Or ProjectionY = -1
V3_Normalize(Direction)
V3_Set(CameraDirection, CameraDirectionX(Camera), CameraDirectionY(Camera), CameraDirectionZ(Camera))
V3_Subtraction(Projection, CameraDirection, Direction)
FetchOrientation(CameraID(Camera))
M3_Orientation(Orientation, GetX(), GetY(), GetZ(), GetW())
M3_Inverse(Inverse, Orientation)
V3_Rotate(Projection, Inverse)
Projection\Z = 0
Projection\X = -Projection\X
Length = Sqr(Width*Width/4+Height*Height/4) - Sqr(Padding*Padding*2)
V3_SetLength(Projection, Length)
If Projection\X < -(Width/2-Padding)
CameraProjection\X = Padding
CameraProjection\Y = Projection\Y * Abs((Width/2-Padding)/Projection\X) + Height/2
ElseIf Projection\X > Width/2-Padding
CameraProjection\X = Width-Padding
CameraProjection\Y = Projection\Y * Abs((Width/2-Padding)/Projection\X) + Height/2
ElseIf Projection\Y < -(Height/2-Padding)
CameraProjection\X = Projection\X * Abs((Height/2-Padding)/Projection\Y) + Width/2
CameraProjection\Y = Padding
ElseIf Projection\Y > Height/2-Padding
CameraProjection\X = Projection\X * Abs((Height/2-Padding)/Projection\Y) + Width/2
CameraProjection\Y = Height-Padding
Else
CameraProjection\X = Projection\X + Width/2
CameraProjection\Y = Projection\Y + Height/2
EndIf
Else
CameraProjection\X = ProjectionX
CameraProjection\Y = ProjectionY
EndIf
EndProcedure
;- Demo
InitEngine3D()
InitSprite()
UsePNGImageDecoder()
InitMouse()
Enumeration
#Window
#Camera
#Sprite
#Light
#Entity
EndEnumeration
OpenWindow(#Window, 0, 0, 800, 600, "ScreenTitle", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(#Window), 0, 0, WindowWidth(#Window), WindowHeight(#Window), 0, 0, 0)
CatchSprite(#Sprite, ?cross, #PB_Sprite_AlphaBlending)
CreateCamera(#Camera, 0, 0, 100, 100)
MoveCamera(#Camera, 0, 0, 4)
CameraLookAt(#Camera, 0, 0, 0)
CreateLight(#Light, $FFFFFF, 5, 0, 5)
CreateEntity(#Entity, MeshID(CreateCube(#PB_Any, 1)), #PB_Material_None, 1, 0, 0)
Repeat
Repeat
Select WindowEvent()
Case #PB_Event_CloseWindow
End
Case #PB_Event_None
Break
EndSelect
ForEver
RenderWorld()
ExamineMouse()
RotateCamera(#Camera, -MouseDeltaY()/10, -MouseDeltaX()/10, 0, #PB_Relative)
ExamineCameraProjection(#Camera, EntityX(#Entity), EntityY(#Entity), EntityZ(#Entity), 800, 600, 20)
DisplayTransparentSprite(#Sprite, CameraProjection\X-16, CameraProjection\Y-16)
FlipBuffers()
ForEver
DataSection
cross:
Data.q $0A1A0A0D474E5089,$524448490D000000,$2000000020000000,$7A7A730000000608,$58457419000000F4
Data.q $72617774666F5374,$2065626F64410065,$6165526567616D49,$00003C65C9717964,$DA7854414449BB03
Data.q $3E145114486B57AC,$607CAFADADBAAE3B,$2432528F96AE618A,$C922C2148928CD4B,$A20A230485032908
Data.q $814487E920CBF91F,$05945191FC0F4245,$928888A4A9A26519,$956CB528B335DDCF,$EE3BDDAEE1F75D5D
Data.q $70BD59DDEF663EC8,$7DDF7DF39CCEE776,$674F9BF80067B9CC,$379E0D7C360AEA4E,$6B0B674D20D8708F
Data.q $EB506ACE11E110EB,$6BE1AC09B99F95FB,$1B1DD9A9C708440F,$E20B59BE3FE61D86,$8E0847C22013DF0C
Data.q $866784C72754FF08,$3B8584AB5F274C04,$E0C1572F9BA8BC95,$5D45F7EB6CC82AED,$05C4470420DC8123
Data.q $C49BDABA0EB95D25,$B54D50C06FCB49A1,$87EFA830E11E112B,$88BC62204C98AE6F,$055C562416E0F4B6
Data.q $867E392C1CB0E44C,$F0FCDACB9838687D,$89DD00478B21040C,$91751EFEA1812F17,$6E5DFEF8602B8B7D
Data.q $5D43EEC41E415826,$08316430923AC885,$1FCF4C1CB4A13DA8,$5D48C1974FBC8152,$A3679106342D7B2D
Data.q $6D0A6E223FB204EE,$A7C6E60A5F3CEC45,$FBFBFEC2D18D4054,$FA307382AF5F5430,$2BC084DB9C8ECEA4
Data.q $23601AEF2C04B8A2,$9D8FF5A3045F931A,$9C762257435ED7C8,$DCF63EB57E680629,$4F9C979EACF63093
Data.q $373E6022C288B380,$2F630798396DC479,$2224E012BB925C1A,$44127D771029C4FE,$125FAF1404719CBE
Data.q $002F1C459C0249C9,$B37B4DC8B776DEEF,$989B8E4A91B6F141,$B31C26AE06B46380,$6D6BE4356E224D99
Data.q $70CB5819B4E448BF,$D04FA464818F4771,$7BC3F280F613E812,$7F1E4C025E41D9DA,$426D1E43E3241738
Data.q $22899A5A28126C7D,$0FE9021CE791C444,$281C745D42DEBAE5,$05D5F1108A5D5ADB,$F02CACB899B2C1E9
Data.q $B118B44490DC9A9B,$04EC22BC1D1D940D,$FEC83F633C817570,$1FFB2D1AD581514D,$8044B76AFAA32FEC
Data.q $3C89C608938BEBAA,$678ED066E7FC1D3D,$59E9C9850C0DA688,$6C62631FCD35F0D6,$06969E476C5CA3C7
Data.q $6EBF20E4E8F38B81,$42E07A7AA81912F3,$13B1696162A158EF,$1871896BD58D89A0,$244553837F21FB1B
Data.q $953A9EB320854D4F,$ACA00606A82F8C73,$5AE18DD1AC3F914F,$1494F2564E245906,$50125E18E818B208
Data.q $222AE621CBB3F7F5,$B222DA8D13532F30,$8C02AC66B7441F25,$2577CBB591A1EB38,$6BCB544942B33043
Data.q $FAA2757007BB1115,$E21AE5D9936A083A,$319360DC81C7D867,$1115AC717708B027,$910838F8F2445538
Data.q $52A0756ACF04ED49,$1C241D9E5DC8F928,$C1A10EDD8F24456A,$8D5079EABF83EC81,$078E38BB8391A37F
Data.q $D03BC0F4F8E8B714,$6F80416374FBE8F4,$147A4B7404936489,$5AB74E1DB92EE134,$71C5B59CC24072D3
Data.q $C596428823C474E7,$3F50F34BFA26547D,$0C70CD3E42B4171A,$22BAFC7289C0758E,$18DDBFE7D6914455
Data.q $56D91C2C8E056F39,$C7E445484679A39B,$104CC6EA71D272A5,$53B45600300BFE71,$000000AF4D4CDE60
Data.q $6042AE444E454900,$0000000000000082
EndDataSection
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Re: Text über Objekt ausserhalb des Viewports anzeigen
Hi, im konkreten Fall geht es darum Untertitel von Charakteren in einem Spiel anzuzeigen, wenn diese sprechen. Die Untertitel sollen dann über dem Charakter angezeigt werden (was sie zu Übertiteln macht
). Und wenn jetzt ein Charakter am Bildschrimrand herausmarschiert, soll der Untertitel weiterhin zu sehen sein wenn er dabei weiterplaudert, so daß der Spieler sehen kann: "Aha, rechts im Off steht einer und redet!". Ich habe mir jetzt überlegt ich versuche es mal so:
Ich schaue mal ob das so klappt wie ich mir das vorstelle.
[EDIT] Danke, Stargate. Deinen Code schaue ich mir mal an, scheint ja genau das zu sein was ich brauche!

Code: Alles auswählen
Kamera-Projektions-Koodinaten abfragen
-> wenn die Werte plausibel sind (Objekt ist sichtbar), den Text normal anzeigen
-> wenn die Werte -1 ergeben könnte ich hingehen und mir die aktuellen Kamerawinkel merken, dann ein CameraLookAt auf das Objekt machen und die Winkeldifferenz benutzen um zu erkennen ob das Objekt z.B. links oder rechts vom Kamera-Viewport ist (je nachdem ob die Winkel größer oder kleiner werden), danach die Kamera auf die Ursprungsausrichtung zurücksetzen
[EDIT] Danke, Stargate. Deinen Code schaue ich mir mal an, scheint ja genau das zu sein was ich brauche!
Windows XP 32-bit SP3, Windows 7 64-bit, PB 4.60, PB 5.11, PB 5.20
- Makke
- Beiträge: 156
- Registriert: 24.08.2011 18:00
- Computerausstattung: AMD Ryzen 7 5700X - AMD Radeon RX 6800 XT - 32 GB DDR4 SDRAM
- Wohnort: Ruhrpott
- Kontaktdaten:
Re: Text über Objekt ausserhalb des Viewports anzeigen
@Stargate: Hut ab ! Sehr schick.
---
Windows 11 (64 bit)
Windows 11 (64 bit)
Re: Text über Objekt ausserhalb des Viewports anzeigen
Da schließe ich mich an, der Code ist perfekt, danke!
Windows XP 32-bit SP3, Windows 7 64-bit, PB 4.60, PB 5.11, PB 5.20