Code: Select all
Global Titulo$="tip general"
If ExamineDesktops()=0:End:EndIf
Global bitplanes.a=DesktopDepth(0),RX=DesktopWidth(0)*2/3,RY=DesktopHeight(0)*2/3
InitEngine3D(#PB_Engine3D_NoLog,#PB_Compiler_Home+"Compilers\Engine3d.dll")
#ventana=1
;AntialiasingMode(#PB_AntialiasingMode_x4)
If InitMouse()=0 Or InitSprite()=0 Or InitKeyboard()=0:MessageRequester("Error","Can't open DirectX",0):End:EndIf
OpenWindow(#ventana,0,0,RX,RY,Titulo$,#PB_Window_BorderLess|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(#ventana),0,0,RX,RY,1,0,0,#PB_Screen_WaitSynchronization)
Add3DArchive(#PB_Compiler_Home+"examples\3D\Data\Packs\desert.zip",#PB_3DArchive_Zip)
Add3DArchive(#PB_Compiler_Home+"examples\3D\Data\GUI",#PB_3DArchive_FileSystem)
Enumeration Ventanas3D
#TextoInfoObjeto
EndEnumeration
Enumeration Luces
#Luz
EndEnumeration
Enumeration Camaras
#Camara
EndEnumeration
Enumeration Materiales
#materialtuberia
EndEnumeration
Enumeration Mallas
#MallaPSpline
#mallatuberia
EndEnumeration
Enumeration Nodos
#pivotcamara
#pivottuberia
EndEnumeration
Enumeration Entidades
#PSpline0
#PSpline1
#PSpline2
#PSpline3
#PSpline4
#PSpline5
#PSpline6
#PSpline7
#PSpline8
#PSpline9
#tuberia=60
EndEnumeration
Enumeration Splines
#splinetuberia
EndEnumeration
CreateLight(#luz,$EEEEEE,4,4,2,#PB_Light_Point):SetLightColor(#luz,#PB_Light_DiffuseColor,$EEEEEE):MoveLight(#luz,4,4,2,#PB_Absolute)
CreateCamera(#camara,0,0,100,100):CreateNode(#pivotcamara,0,0,0):AttachNodeObject(#pivotcamara,CameraID(#camara)):CameraRange(#camara,0.1,1E4):CameraBackColor(#camara,$181911)
SkyBox("desert07.jpg"); o bien SkyBox("stevecube.jpg") , etc.
Structure D3DXVECTOR3
x.f
y.f
z.f
EndStructure
Structure Vector3D Extends D3DXVECTOR3
m.f;<-length(modulo)
EndStructure
Global nverticestuberia.a=200,nverticescirctuberia.a=20,npuntosbeziertuberia.a=9,grosortuberia.f=0.6,NewList puntosbeziertuberia.D3DXVECTOR3(); <- para tuberia 3D
For i.a=0 To npuntosbeziertuberia
AddElement(puntosbeziertuberia())
puntosbeziertuberia()\x=2*Cos(i/(npuntosbeziertuberia+1.0)*2*#PI)
puntosbeziertuberia()\y=2*Sin(i/(npuntosbeziertuberia+1.0)*2*#PI)
puntosbeziertuberia()\z=i/(npuntosbeziertuberia+6.0)
Next
Global.Vector3D DELTA,THETA; para puntero ratón en su uso 2D
Global.D3DXVECTOR3 pick,pickv,pos; <- para usar puntero del ratón para referir elementos 3D
Global EntidadSeleccionada.i
Procedure.b MouseButtonEdgeDetection(boton.b,estado.b)
Static mb.b:Protected i.b=1<<boton
If estado;<- if current key status is PUSHED
If mb&i=0:mb|i:ProcedureReturn 1:EndIf;<- if previous key status was NOT PUSHED, then assign previous state to current one, and EXIT.
ElseIf mb&i;<- else (if previous key status was PUSHED and current key status is NOT PUSHED):
mb!i:ProcedureReturn -1;<- set previous key status to NOT PUSHED.
EndIf
ProcedureReturn 0
EndProcedure
Procedure.b KeyEdgeDetection(tecla.a,estado.b)
Static pka.a
If estado;<-if current key status is PUSHED
If pka=0:pka=tecla:ProcedureReturn 1:EndIf;<-if previous key status was NOT PUSHED, then assign previous state to current one, and EXIT.
ElseIf pka=tecla;<-else (if previous key status was PUSHED and current key status is NOT PUSHED):
pka=0:ProcedureReturn -1;<-set previous key status to NOT PUSHED.
EndIf
ProcedureReturn 0
EndProcedure
Macro ProductoEscalar(a,b,ax=x,ay=y,az=z,bx=x,by=y,bz=z)
(a#\ax#*b#\bx#+a#\ay#*b#\by#+a#\az#*b#\bz#)
EndMacro
Macro getmodulo(v,vx=x,vy=y,vz=z)
(Sqr#ProductoEscalar(v#,v#,vx#,vy#,vz#,vx#,vy#,vz#))
EndMacro
Macro ProductoVectorial(in1,in2,out,in1x=x,in1y=y,in1z=z,in2x=x,in2y=y,in2z=z,outx=x,outy=y,outz=z); <- Calculates the vectorial product of two 3D vectors. Just modify this procedure to get the vectorial product for 4D, 5D, 6D or any dimension you need.
out#\outx#=in1#\in1y#*in2#\in2z#-in1#\in1z#*in2#\in2y#
out#\outy#=in1#\in1z#*in2#\in2x#-in1#\in1x#*in2#\in2z#
out#\outz#=in1#\in1x#*in2#\in2y#-in1#\in1y#*in2#\in2x#
EndMacro
Macro ProyeccionVectorial(A,B,P,Ax=x,Ay=y,Az=z,Bx=x,By=y,Bz=z,Px=x,Py=y,Pz=z)
P#\Pz#=ProductoEscalar(A#,B#,Ax#,Ay#,Az#,Bx#,By#,Bz#)/ProductoEscalar(B#,B#,Bx#,By#,Bz#,Bx#,By#,Bz#)
P#\Px#=P#\Pz#*B#\Bx#
P#\Py#=P#\Pz#*B#\By#
P#\Pz#*B#\Bz#
EndMacro
Macro ProyeccionVectorialOrtogonal(A,B,P,Ax=x,Ay=y,Az=z,Bx=x,By=y,Bz=z,Px=x,Py=y,Pz=z)
ProyeccionVectorial(A#,B#,P#,Ax#,Ay#,Az#,Bx#,By#,Bz#,Px#,Py#,Pz#)
P#\Px#=A#\Ax#-P#\Px#
P#\Py#=A#\Ay#-P#\Py#
P#\Pz#=A#\Az#-P#\Pz#
EndMacro
Procedure.b Rotar_Vector3D_por_adicion_Angular(*fi.Vector3D,*R0.Vector3D)
;Esta funcion halla un vector resultado de una rotacion en el espacio de otro vector inicial.
;Esta funcion admite entonces, como parametros de entrada, 2 vectores:
; - 'Vector radio' ( *R0-> ) que se desea rotar. Este vector tiene direccion no colineal con el eje de rotación.
; - 'Vector angulo' ( *fi-> 'velocidad angular'-> * 'tiempo'), es el angulo en el que se rota el 'Vector radio' dado.
; Su modulo indica el numero de radianes a rotar, su direccion indica el angulo en el espacio en el que se rota (eje de rotación)
; su sentido indica el sentido de la rotacion
;NOTA: la funcion extrae el vector velocidad rectilinea y el nuevo vector radio.
; se devuelve nuevo radio en el mismo parametro de entrada ( *R0-> )
; El resultado es:
; Proyección de *R0-> sobre *fi-> MÁS proyección ortogonal de *R0-> sobre *fi-> por el Cos(|fi->|) MÁS módulo de la proyección ortogonal de *R0-> sobre *fi-> por el Sen(|fi->|) por u^,
; siendo u-> = *fi-> X *R0-> .
Protected Rt.Vector3D,u.Vector3D,P0.Vector3D
*fi\m=ProductoEscalar(*fi,*fi)
If *fi\m
u\m=ProductoEscalar(*R0,*fi)/*fi\m; <- aqui lo uso como variable comodin
*fi\m=Sqr(*fi\m)
;Rt-> = Proyeccion de *R0-> sobre *fi->:
Rt\x=u\m**fi\x
Rt\y=u\m**fi\y
Rt\z=u\m**fi\z
;P0-> = proyeccion ortogonal de *R0-> sobre *fi->:
P0\x=*R0\x-Rt\x
P0\y=*R0\y-Rt\y
P0\z=*R0\z-Rt\z
P0\m=getmodulo(P0)
If P0\m<1E-5; <= no hay giro ya que *R0-> y *fi-> son colineales:
ProcedureReturn -1
EndIf
;Calcular el producto vectorial: u-> = *fi-> X *R0-> (o por P0-> daría igual)
u\x=*fi\y**R0\z-*fi\z**R0\y
u\y=*fi\z**R0\x-*fi\x**R0\z
u\z=*fi\x**R0\y-*fi\y**R0\x
;ahora obtener *R0-> = (Proyeccion de *R0-> sobre *fi->)-> + (cos(|*fi->|)·P0-> + |P0->|/|u->|·sin(|*fi->|)·u->)->:
*R0\x=Rt\x
*R0\y=Rt\y
*R0\z=Rt\z
Rt\x=Cos(*fi\m):Rt\y=Sin(*fi\m)
u\m=getmodulo(u)
P0\m*Rt\y/u\m
*R0\x+Rt\x*P0\x+P0\m*u\x
*R0\y+Rt\x*P0\y+P0\m*u\y
*R0\z+Rt\x*P0\z+P0\m*u\z
ProcedureReturn 1
EndIf
ProcedureReturn 0
EndProcedure
Macro AnimarGiroenPropioEjeXYZ(rot,tipoobjeto,objeto,grados,veloc=5)
seno2.d=Pow(Sin(Animaciondiferencial.d),2)
; seno2.d=1-Abs(Cos(Animaciondiferencial.d)); con este va pero el paso no es de #PI/(grados#*2/veloc#). Interesante estudiar esto matemáticamente.
Animaciondiferencial.d+#PI/(grados#*2/veloc#)
If Abs(Animaciondiferencial.d)>=#PI:Animaciondiferencial.d=0:AnimacionPivotCamara.b=0
Else:rot#(tipoobjeto#ID(objeto#),Sign(grados#)*veloc#*seno2.d,#PB_Local|#PB_Relative)
EndIf
EndMacro
Macro OrbitarObjeto1SobreObjeto0(tecla=LeftControl,tipo1=Camera,objeto1=#Camara,tipo0=Node,objeto0=#Pivotcamara); <- el 'objeto1' orbita sobre el 'objeto0', y este debe ser nodo de 'objeto1'
If AnimacionPivotCamara.b
Select TipodeGiro.b
Case 1; pitch 90 grados
AnimarGiroenPropioEjeXYZ(Pitch,tipo0#,objeto0#,Gradosdegiro.d)
Case 2; pitch -90 grados
AnimarGiroenPropioEjeXYZ(Pitch,tipo0#,objeto0#,Gradosdegiro.d)
Case 3; yaw 90 grados
AnimarGiroenPropioEjeXYZ(Yaw,tipo0#,objeto0#,Gradosdegiro.d)
Case 4; yaw -90 grados
AnimarGiroenPropioEjeXYZ(Yaw,tipo0#,objeto0#,Gradosdegiro.d)
Case 5; roll 90 grados
AnimarGiroenPropioEjeXYZ(Roll,tipo0#,objeto0#,Gradosdegiro.d)
Case 6; roll -90 grados
AnimarGiroenPropioEjeXYZ(Roll,tipo0#,objeto0#,Gradosdegiro.d)
EndSelect
Else
If KeyboardPushed(#PB_Key_Pad0)
Rotate#tipo0#(objeto0#,0,0,0,#PB_Absolute)
Move#tipo1#(objeto1#,0,0,9,#PB_Absolute)
EndIf
estadotecla.b=KeyboardPushed(#PB_Key_#tecla#):estadoteclaf.b=KeyEdgeDetection(#PB_Key_#tecla#,estadotecla.b)
If estadoteclaf.b>0; <- inicia control camara
pasocam.f=0.01:pasocamincr.f=0.001
ShowGUI(180,0,#camara,1):CursorX0.f=CursorX.f:CursorY0.f=CursorY.f
ElseIf estadoteclaf.b<0; <- termina control camara
ShowGUI(180,1,#camara,1)
ElseIf estadotecla.b; <- mover el punto de vista
MouseLocate(CursorX0.f,CursorY0.f)
;para desplazar la camara hacia delante, atras, arriba, abajo, izq o der
If DELTA\m
If mmb.b
Move#tipo1#(objeto1#,DELTA\x/40,-DELTA\y/40,0,#PB_Local)
Else
Rotate#tipo0#(objeto0#,-DELTA\y/10,-DELTA\x/10,0,#PB_Relative)
If DELTA\z
Move#tipo1#(objeto1#,0,0,-DELTA\z,#PB_Local)
EndIf
EndIf
ElseIf KeyboardPushed(#PB_Key_Add)
Move#tipo1#(objeto1#,0,0,-pasocam,#PB_Local)
pasocam+pasocamincr
ElseIf KeyboardPushed(#PB_Key_Subtract)
Move#tipo1#(objeto1#,0,0,pasocam,#PB_Local)
pasocam+pasocamincr
EndIf
ElseIf KeyboardPushed(#PB_Key_Pad8)
If KeyboardPushed(#PB_Key_Pad5)
Gradosdegiro.d=-90
AnimacionPivotCamara.b=1:TipodeGiro.b=1
Else
Pitch(tipo0#ID(objeto0#),-0.5,#PB_Local|#PB_Relative)
EndIf
ElseIf KeyboardPushed(#PB_Key_Pad2)
If KeyboardPushed(#PB_Key_Pad5)
Gradosdegiro.d=90
AnimacionPivotCamara.b=1:TipodeGiro.b=2
Else
Pitch(tipo0#ID(objeto0#),0.5,#PB_Local|#PB_Relative)
EndIf
ElseIf KeyboardPushed(#PB_Key_Pad4)
If KeyboardPushed(#PB_Key_Pad5)
Gradosdegiro.d=-90
AnimacionPivotCamara.b=1:TipodeGiro.b=3
Else
Yaw(tipo0#ID(objeto0#),-0.5,#PB_Local|#PB_Relative)
EndIf
ElseIf KeyboardPushed(#PB_Key_Pad6)
If KeyboardPushed(#PB_Key_Pad5)
Gradosdegiro.d=90
AnimacionPivotCamara.b=1:TipodeGiro.b=4
Else
Yaw(tipo0#ID(objeto0#),0.5,#PB_Local|#PB_Relative)
EndIf
ElseIf KeyboardPushed(#PB_Key_Pad7)
If KeyboardPushed(#PB_Key_Pad5)
Gradosdegiro.d=-90
AnimacionPivotCamara.b=1:TipodeGiro.b=5
Else
Roll(tipo0#ID(objeto0#),-0.5,#PB_Local|#PB_Relative)
EndIf
ElseIf KeyboardPushed(#PB_Key_Pad9)
If KeyboardPushed(#PB_Key_Pad5)
Gradosdegiro.d=90
AnimacionPivotCamara.b=1:TipodeGiro.b=6
Else
Roll(tipo0#ID(objeto0#),0.5,#PB_Local|#PB_Relative)
EndIf
EndIf
EndIf
EndMacro
Macro desplazardesdepuntodevista(entidad)
ConvertLocalToWorldPosition(CameraID(#camara),THETA\x,-THETA\y,THETA\z)
THETA\x=GetX():THETA\y=GetY():THETA\z=GetZ():THETA\m=getmodulo(THETA)
MoveEntity(entidad#,THETA\x,THETA\y,THETA\z,#PB_World|#PB_Relative)
EndMacro
Procedure TuberiaBezier(actualizar.b=1,color.l=$43D4E2)
Protected sp1.Vector3D,sp0.Vector3D,sp.Vector3D,vector0.Vector3D,vector.Vector3D,compas.Vector3D,radio.Vector3D,i.a,j.a,texcoordu.f,texcoordv.f,ncara.u=0,Dim primercirculo.D3DXVECTOR3(nverticescirctuberia)
If actualizar
ForEach puntosbeziertuberia()
UpdateSplinePoint(#splinetuberia,ListIndex(puntosbeziertuberia()),puntosbeziertuberia()\x,puntosbeziertuberia()\y,puntosbeziertuberia()\z)
Next
If IsEntity(#tuberia):FreeEntity(#tuberia):EndIf; o bien si la malla va con 'node' en lugar de con 'entity': ;UpdateMesh(#mallatuberia,0)
Else
CreateSpline(#splinetuberia)
CreateSphere(#MallaPSpline,0.05)
ForEach puntosbeziertuberia()
AddSplinePoint(#splinetuberia,puntosbeziertuberia()\x,puntosbeziertuberia()\y,puntosbeziertuberia()\z)
CreateEntity(#PSpline0+ListIndex(puntosbeziertuberia()),MeshID(#MallaPSpline),#PB_Material_None,puntosbeziertuberia()\x,puntosbeziertuberia()\y,puntosbeziertuberia()\z)
Next
CreateMaterial(#materialtuberia,0,color):DisableMaterialLighting(#materialtuberia,1)
;Activar las 2 lineas que siguen si la malla va con 'node' en lugar de con 'entity':
; CreateMesh(#mallatuberia,#PB_Mesh_TriangleList,#PB_Mesh_Static):SetMeshMaterial(#mallatuberia,MaterialID(#materialtuberia))
; CreateNode(#pivottuberia):AttachNodeObject(#pivottuberia,MeshID(#mallatuberia))
EndIf
CreateMesh(#mallatuberia,#PB_Mesh_TriangleList,#PB_Mesh_Static):SetMeshMaterial(#mallatuberia,MaterialID(#materialtuberia)); <- quitar si la malla va con 'node' en lugar de con 'entity'
ComputeSpline(#splinetuberia,0.0):sp\x=SplineX(#splinetuberia):sp\y=SplineY(#splinetuberia):sp\z=SplineZ(#splinetuberia); <- tiempo 0
sp0=sp; <- inicio nulo
FillMemory(@vector,SizeOf(Vector3D)); <- inicio nulo
For i=0 To nverticestuberia; <- recorrer toda la linea spline; desde tiempo=0 hasta tiempo=1 en la spline
sp1=sp0
sp0=sp
ComputeSpline(#splinetuberia,(i+1.0)/(nverticestuberia+1.0))
sp\x=SplineX(#splinetuberia):sp\y=SplineY(#splinetuberia):sp\z=SplineZ(#splinetuberia)
vector0=vector
vector\x=sp\x-sp0\x:vector\y=sp\y-sp0\y:vector\z=sp\z-sp0\z:vector\m=getmodulo(vector); <- vector sentido del tiempo spline
vector\x*2*#PI/vector\m/nverticescirctuberia:vector\y*2*#PI/vector\m/nverticescirctuberia:vector\z*2*#PI/vector\m/nverticescirctuberia; <- vector sentido del tiempo spline modulado
If i
ProyeccionVectorialOrtogonal(radio,vector,compas):compas\m=getmodulo(compas)
ProyeccionVectorialOrtogonal(vector0,vector,radio):radio\m=getmodulo(radio)
If radio\m<compas\m*12:radio=compas:EndIf
radio\x*grosortuberia/2/radio\m:radio\y*grosortuberia/2/radio\m:radio\z*grosortuberia/2/radio\m
Else
compas\x=0:compas\y=grosortuberia/2:compas\z=0:compas\m=compas\y
ProyeccionVectorialOrtogonal(compas,vector,radio):radio\m=getmodulo(radio)
If radio\m<1E-2
Swap compas\y,compas\z
ProyeccionVectorialOrtogonal(compas,vector,radio):radio\m=getmodulo(radio)
EndIf
radio\x*compas\m/radio\m:radio\y*compas\m/radio\m:radio\z*compas\m/radio\m
EndIf
For j=0 To nverticescirctuberia
If i=0
primercirculo(j)\x=sp0\x+radio\x:primercirculo(j)\y=sp0\y+radio\y:primercirculo(j)\z=sp0\z+radio\z
EndIf
Rotar_Vector3D_por_adicion_Angular(@vector,@radio)
MeshVertex(sp0\x+radio\x,sp0\y+radio\y,sp0\z+radio\z,texcoordu.f,texcoordv.f,color)
Next
Next
;Para no cerrar el lazo, comentar esta linea:
For j=0 To nverticescirctuberia:MeshVertex(primercirculo(j)\x,primercirculo(j)\y,primercirculo(j)\z,texcoordu.f,texcoordv.f,color):Next
For i=0 To nverticestuberia
For j=1 To nverticescirctuberia
ncara+1
MeshFace(ncara+nverticescirctuberia+1,ncara+nverticescirctuberia,ncara)
MeshFace(ncara+nverticescirctuberia,ncara-1,ncara)
Next
ncara+1
Next
FinishMesh(1); <- FinishMesh(0) si la malla va con 'node' en lugar de con 'entity'
; NormalizeMesh(#mallatuberia,0)
; UpdateMeshBoundingBox(#mallatuberia)
CreateEntity(#tuberia,MeshID(#mallatuberia),MaterialID(#materialtuberia)); <- si la malla va con 'node' quitar esta linea
FreeArray(primercirculo.D3DXVECTOR3())
EndProcedure
MoveNode(#Pivotcamara,0,0,0,#PB_Absolute):RotateNode(#Pivotcamara,0,0,0,#PB_Absolute)
MoveCamera(#camara,0,0,9,#PB_Absolute)
MouseLocate(RX/2,RY/2)
ShowGUI(180,1,#camara,1)
InputEvent3D(0,0,1)
wireframe.b=1:CameraRenderMode(#camara,#PB_Camera_Wireframe)
TuberiaBezier(0)
;/ BUCLE
Repeat
Repeat:evento.i=WindowEvent()
Until evento=#PB_Event_None
;
ExamineMouse():ExamineKeyboard()
CursorX.f=MouseX():CursorY.f=MouseY():lmb.b=MouseButton(#PB_MouseButton_Left):rmb.b=MouseButton(#PB_MouseButton_Right):mmb.b=MouseButton(#PB_MouseButton_Middle)
DELTA\x=MouseDeltaX():DELTA\y=MouseDeltaY():DELTA\z=MouseWheel():DELTA\m=getmodulo(DELTA)
wCursorX.f=WindowMouseX(#ventana):wCursorY.f=WindowMouseY(#ventana)
OrbitarObjeto1SobreObjeto0(LeftControl,Camera,#camara,Node,#Pivotcamara)
InputEvent3D(CursorX.f,CursorY.f,lmb.b); <- para el cursor del ratón nada más.
lmbe.b=MouseButtonEdgeDetection(#PB_MouseButton_Left,lmb)
mmbe.b=MouseButtonEdgeDetection(#PB_MouseButton_Middle,mmb)
If lmbe.b=1 Or mmbe.b=1
;buscar el punto spline más cercano al puntero
mindistanciaspuntostuberia.f=4000
ForEach puntosbeziertuberia()
px.f=CameraProjectionX(#Camara,puntosbeziertuberia()\x,puntosbeziertuberia()\y,puntosbeziertuberia()\z)
py.f=CameraProjectionY(#Camara,puntosbeziertuberia()\x,puntosbeziertuberia()\y,puntosbeziertuberia()\z)
distanciaspuntostuberia.f=Sqr(Pow(px-CursorX,2)+Pow(py-CursorY,2))
If mindistanciaspuntostuberia>distanciaspuntostuberia
mindistanciaspuntostuberia=distanciaspuntostuberia
nodotuberia.a=ListIndex(puntosbeziertuberia())
EndIf
Next
EntidadSeleccionada.i=#PSpline0+nodotuberia
EntidadSeleccionada$="PSpline"+Str(nodotuberia)
anchuratexto.u=Len(EntidadSeleccionada$)*12
pick\x=PickX():pick\y=PickY():pick\z=PickZ()
pos\x=EntityX(EntidadSeleccionada):pos\y=EntityY(EntidadSeleccionada):pos\z=EntityZ(EntidadSeleccionada)
pick=pos
OpenWindow3D(#TextoInfoObjeto,CameraProjectionX(#camara,pick\x,pick\y,pick\z),CameraProjectionY(#camara,pick\x,pick\y,pick\z),anchuratexto.u,32,"detalles objeto",#PB_Window3D_SizeGadget|#PB_Window3D_BorderLess)
TextGadget3D(#TextoInfoObjeto,0,-1,anchuratexto.u,32,EntidadSeleccionada$)
EndIf
If DELTA\m And EntidadSeleccionada$ And IsWindow3D(#TextoInfoObjeto)
THETA=DELTA:THETA\x/100:THETA\y/100:THETA\z/20:THETA\m=getmodulo(THETA)
If lmb.b; mover
pos\x=EntityX(EntidadSeleccionada):pos\y=EntityY(EntidadSeleccionada):pos\z=EntityZ(EntidadSeleccionada)
pick\x=CameraProjectionX(#camara,pos\x,pos\y,pos\z);+pickv\x
pick\y=CameraProjectionY(#camara,pos\x,pos\y,pos\z);+pickv\y
ResizeWindow3D(#TextoInfoObjeto,pick\x,pick\y,anchuratexto.u,#PB_Ignore)
desplazardesdepuntodevista(EntidadSeleccionada); <- mover
If FindString(EntidadSeleccionada$,"PSpline")
nodotuberia.a=Val(Right(EntidadSeleccionada$,1))
SelectElement(puntosbeziertuberia(),nodotuberia)
puntosbeziertuberia()\x+THETA\x:puntosbeziertuberia()\y+THETA\y:puntosbeziertuberia()\z+THETA\z
TuberiaBezier()
EndIf
EndIf
EndIf
If KeyboardPushed(#PB_Key_Right)
If grosortuberia<2:grosortuberia+0.01:TuberiaBezier():EndIf
ElseIf KeyboardPushed(#PB_Key_Left)
If grosortuberia>0.01:grosortuberia-0.01:TuberiaBezier():EndIf
ElseIf KeyboardPushed(#PB_Key_Up)
If nverticestuberia<255:nverticestuberia+1:TuberiaBezier():EndIf
ElseIf KeyboardPushed(#PB_Key_Down)
If nverticestuberia>npuntosbeziertuberia:nverticestuberia-1:TuberiaBezier():EndIf
ElseIf KeyboardPushed(#PB_Key_Home)
If nverticescirctuberia<255:nverticescirctuberia+1:TuberiaBezier():EndIf
ElseIf KeyboardPushed(#PB_Key_End)
If nverticescirctuberia>3:nverticescirctuberia-1:TuberiaBezier():EndIf
ElseIf KeyboardReleased(#PB_Key_W):wireframe.b!1:If wireframe.b:CameraRenderMode(#camara,#PB_Camera_Wireframe):Else:CameraRenderMode(#camara,#PB_Camera_Textured):EndIf
EndIf
TimeSinceLastFrame.i=RenderWorld(50)
FlipBuffers()
Delay(6)
Until KeyboardPushed(#PB_Key_Escape)
;\
leftcontrol+mousemove (to change viewpoint), #PB_Key_Right, #PB_Key_Left, #PB_Key_Up, #PB_Key_Down, #PB_Key_Home, #PB_Key_End , and #PB_Key_W for toggle wireframe view.