Advice needed throughout my first 3D project

Everything related to 3D programming
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Advice needed before I begin a project

Post by IdeasVacuum »

@Samuel, much depends on what you can determine from the relationship of the SVG lines that make-up the 2D polygon. We can see that your sample shape would be easy to triangulate, but we need to be able to classify the shape to apply the correct triangulation solution ('walk' around the perimeter) - though I wonder if there is a building on the map which is both such an odd shape and the roof for that shape is flat and continuous (all the same height).

I always feel that 'less is more' and a full-blown triangulation lib could be the proverbial hammer to crack a nut, though the two that Seymour has found do look very promising, perhaps avoiding the need to re-invent the wheel. Joseph O'Rourke is an expert in the field, the book is a good read and it would probably help in the understanding of the libs too (the code from the book is available for download).

We can see from the discussion thus far, that this project is not one for the faint hearted :D

Edit: A pertinent section of O'Rourke's book is featured in Amazon's 'look inside':
http://www.amazon.co.uk/Computational-G ... 0521649765
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
Samuel
Enthusiast
Enthusiast
Posts: 756
Joined: Sun Jul 29, 2012 10:33 pm
Location: United States

Re: Advice needed before I begin a project

Post by Samuel »

Thanks for that link, IdeasVacuum. I think I'll have to pick that book up sometime.
Looks like it will be a nice addition to my collection.
Seymour Clufley
Addict
Addict
Posts: 1267
Joined: Wed Feb 28, 2007 9:13 am
Location: London

Re: Advice needed before I begin a project

Post by Seymour Clufley »

I have been working on polygon triangulation. The ideal would be a solution that was guaranteed to work for any polygon - Jonathan Shewchuk's Triangle or Ivan Fratric's PolyPartition, for example - but in the absence of that I have attempted the challenge myself. I'm pretty amazed, but it seems to work. I haven't tried it with "real world" polygons yet, just randomly drawn ones, so maybe it will fail with more unpredictable shapes. But as I say it seems to work, so I'll put it up here in case anyone else can use it or improve it. It might save somebody some time in the future. The demo below will keep creating and triangulating polygons - press RETURN to get to the next one, press ESCAPE to abort. If you find any bugs, please let me know.

Code: Select all

;- "REPORTING" FUNCTIONS
Global c13.s = Chr(13)

Macro R(t)
  MessageRequester("Report",t,0)
EndMacro

Macro StandardReportingWindowStuff(win)
  escapekey = 1
  spacekey = 2
  returnkey = 3
  AddKeyboardShortcut(win,#PB_Shortcut_Escape,escapekey)
  AddKeyboardShortcut(win,#PB_Shortcut_Space,spacekey)
  AddKeyboardShortcut(win,#PB_Shortcut_Return,returnkey)
  
  Repeat
    If WindowEvent()=#PB_Event_Menu : Break : EndIf
    Delay(10)
  ForEver
  
  CloseWindow(win)
EndMacro





;- GENERAL FUNCTIONS

Macro DefeatThis(a,b)
  If a>b
    a=b
  EndIf
  ;a = Defeat(a,b)
EndMacro
Macro BeatThis(a,b)
  If b>a
    a=b
  EndIf
  ;a = Beat(a,b)
EndMacro

Procedure.f Difference(a.f,b.f)
  
  If a=b
    ProcedureReturn 0
  EndIf
  
  If a>b
    ProcedureReturn a-b
  Else
    ProcedureReturn b-a
  EndIf
  
EndProcedure




;- GEOMETRIC FUNCTIONS

Structure PointF
  x.f
  y.f
EndStructure

Procedure.f DoubleCrossProduct(*a.PointF,*b.PointF,*c.PointF)
  dx1.f = *b\x-*a\x
  dy1.f = *b\y-*a\y
  dx2.f = *c\x-*b\x
  dy2.f = *c\y-*b\y
  ProcedureReturn dx1*dy2 - dy1*dx2
EndProcedure


Procedure.f DistanceBetweenTwoPoints(*a.PointF,*b.PointF)
  xdif.f = Difference(*a\x,*b\x)
  ydif.f = Difference(*a\y,*b\y)
  ProcedureReturn Sqr((xdif*xdif)+(ydif*ydif))
EndProcedure


Procedure.f DegreeAngleBetweenTwoPoints(*o.PointF,*b.PointF)
  x.f = *b\x - *o\x
  y.f = *b\y - *o\y
  ProcedureReturn Degree(ATan(y/x))
EndProcedure

Procedure.b CoordsFromPoint(*base.PointF,radia.d,distance.d,*c.PointF)
  *c\x = (Cos(radia)*distance)+*base\x
  *c\y = (Sin(radia)*distance)+*base\y
EndProcedure
Macro DegreeCoordsFromPoint(base,degrees,distance,c)
  CoordsFromPoint(base,Radian(degrees),distance,c)
EndMacro


Macro PointsIdentical(p1,p2)
  (p1\x=p2\x And p1\y=p2\y)
EndMacro


Enumeration ; polygon types
  #Polygon_Convex
  #Polygon_Concave
  #Polygon_Triangle
EndEnumeration

Procedure.b IdentifyPolygonType(points.i,Array pnt.PointF(1))
  
  If points=3
    ProcedureReturn #Polygon_Triangle
  EndIf
  
  hasneg.b
  haspos.b
  zcrossproduct.f = DoubleCrossProduct(@pnt(1),@pnt(2),@pnt(3))
  If zcrossproduct>0
    haspos=#True
  Else
    If zcrossproduct<0
      hasneg=#True
    EndIf
  EndIf
  
  For p = 2 To points
    a = p
    b = p+1
    c = p+2
    If p=points-1
      c=1
    Else
      If p=points
        b=1
        c=2
      EndIf
    EndIf
    zcrossproduct.f = DoubleCrossProduct(@pnt(a),@pnt(b),@pnt(c))
    If zcrossproduct>0
      haspos=#True
    Else
      If zcrossproduct<0
        hasneg=#True
      EndIf
    EndIf
  Next p
  If haspos And hasneg
    ProcedureReturn #Polygon_Concave
  Else
    ProcedureReturn #Polygon_Convex
  EndIf
EndProcedure


Procedure.b GetUsableCentrePoint(points.i,Array pnt.PointF(1),*c.PointF)
  br.PointF
  For p = 1 To points
    BeatThis(br\x,pnt(p)\x)
    BeatThis(br\y,pnt(p)\y)
  Next p
  CopyStructure(@br,@tl.PointF,PointF)
  For p = 1 To points
    DefeatThis(tl\x,pnt(p)\x)
    DefeatThis(tl\y,pnt(p)\y)
  Next p
  
  dist.f = DistanceBetweenTwoPoints(@tl,@br)
  deg.f = DegreeAngleBetweenTwoPoints(@tl,@br)
  DegreeCoordsFromPoint(@tl,deg,dist/2,*c)
EndProcedure




;- TRIANGULATION

Structure TriangleStructure
  a.PointF
  b.PointF
  c.PointF
EndStructure
Structure Triangulation
  triangles.i
  Array triangle.TriangleStructure(0)
EndStructure

Procedure.b TriangulateConvexPolygon(points.i,Array pnt.PointF(1),*t.Triangulation)
  
  GetUsableCentrePoint(points,pnt(),@cnt.PointF) ; maybe getting the centroid would be better, but this seems to work
  
  *t\triangles = points
  Dim *t\triangle(points)
  For p = 1 To points
    If p=points
      p2=1
    Else
      p2=p+1
    EndIf
    CopyStructure(@pnt(p),*t\triangle(p)\a,PointF)
    CopyStructure(@cnt,*t\triangle(p)\b,PointF)
    CopyStructure(@pnt(p2),*t\triangle(p)\c,PointF)
  Next p
  
EndProcedure


Procedure.f TriangleArea(*t.TriangleStructure)
  ProcedureReturn 0.5*(-*t\b\y**t\c\x + *t\a\y*(-*t\b\x + *t\c\x) + *t\a\x*(*t\b\y - *t\c\y) + *t\b\x**t\c\y)
EndProcedure

Procedure.b PointIsInsideTriangle(*p.PointF,*t.TriangleStructure)
  Area.f = TriangleArea(*t)
  If Area=0
    R("AREA: "+StrF(Area)+c13+c13+StrF(*t\a\x)+","+StrF(*t\a\y)+c13+StrF(*t\b\x)+","+StrF(*t\b\y)+c13+StrF(*t\c\x)+","+StrF(*t\c\y))
  EndIf
  s.f = 1/(2*Area)*(*t\a\y**t\c\x - *t\a\x**t\c\y + (*t\c\y - *t\a\y)* *p\x + (*t\a\x - *t\c\x) * *p\y)
  t.f = 1/(2*Area)*(*t\a\x**t\b\y - *t\a\y**t\b\x + (*t\a\y - *t\b\y)* *p\x + (*t\b\x - *t\a\x)* *p\y)
  If s>0 And t>0 And (1-s-t)>0
    ProcedureReturn #True
  EndIf
EndProcedure

Procedure.b TriangleCentre(*t.TriangleStructure,*c.PointF)
  *c\x = (*t\a\x + *t\b\x + *t\c\x) / 3
  *c\y = (*t\a\y + *t\b\y + *t\c\y) / 3
EndProcedure

Macro DrawTriangle(t,clr)
  LineXY(t\a\x,t\a\y,t\b\x,t\b\y,clr)
  LineXY(t\b\x,t\b\y,t\c\x,t\c\y,clr)
  LineXY(t\c\x,t\c\y,t\a\x,t\a\y,clr)
  TriangleCentre(@t,@dtcnt.PointF)
  FillArea(dtcnt\x,dtcnt\y,-1,clr)
EndMacro

Macro TriangleHasPoint(t,p)
  ( PointsIdentical(t\a,p) Or PointsIdentical(t\b,p) Or PointsIdentical(t\c,p) )
EndMacro


Structure UsePoint
  p.i
  valid.b
EndStructure

Procedure.i RemoveDeadPoints(points.i,Array nt.UsePoint(1))
  
  Dim nt2.UsePoint(points)
  newusepoints = 0
  For p = 1 To points
    If nt(p)\valid
      newusepoints+1
      CopyStructure(@nt(p),@nt2(newusepoints),UsePoint)
    EndIf
  Next p
  
  CopyArray(nt2(),nt())
  ProcedureReturn newusepoints
  
EndProcedure

Procedure.i UsePointSum(Array u.UsePoint(1))
  usepoints = 0
  For a = 1 To ArraySize(u())
    If u(a)\valid = #True
      usepoints+1
    EndIf
  Next
  ProcedureReturn usepoints
EndProcedure

Procedure.b PointsVirtuallyIdentical(*p1.PointF,*p2.PointF)
  If Difference( *p1\x,*p2\x)<1 And Difference(*p1\y,*p2\y)<1
    ProcedureReturn #True
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure.f AngleBetweenThreePoints(*c.PointF,*p1.Point,*p2.PointF)
  tpnt.PointF
  
  cdist1.f = DistanceBetweenTwoPoints(*c,*p1)
  cdeg1.f = DegreeAngleBetweenTwoPoints(*c,*p1)
  DegreeCoordsFromPoint(*c,cdeg1,cdist1,@tpnt)
  While Not PointsVirtuallyIdentical(*p1,@tpnt)
    cdeg1+180
    DegreeCoordsFromPoint(*c,cdeg1,cdist1,@tpnt)
  Wend
  If cdeg1<0
    cdeg1+360
  Else
    While cdeg1>360 : cdeg1-360 : Wend
  EndIf
  
  cdist2.f = DistanceBetweenTwoPoints(*c,*p2)
  cdeg2.f = DegreeAngleBetweenTwoPoints(*c,*p2)
  DegreeCoordsFromPoint(*c,cdeg1,cdist1,@tpnt)
  While Not PointsVirtuallyIdentical(*p2,@tpnt)
    cdeg2+180
    DegreeCoordsFromPoint(*c,cdeg2,cdist2,@tpnt)
  Wend
  If cdeg2<0
    cdeg2+360
  Else
    While cdeg2>360 : cdeg2-360 : Wend
  EndIf
  
  mdeg.f = cdeg2-cdeg1
  If mdeg<0 : mdeg+360 : ElseIf mdeg>360 : mdeg-360 : EndIf
  ProcedureReturn mdeg
  
EndProcedure


Procedure.b TriangulateConcavePolygon(points.i,Array pnt.PointF(1),*t.Triangulation)
  
  Dim u.UsePoint(points)
  For p = 1 To points
    u(p)\p = p
    u(p)\valid = #True
  Next p
  
  NewList temptri.TriangleStructure()
  
  usum = UsePointSum(u())
  While usum>3
    For a = 1 To usum
      u1 = a
      u2 = a+1
      u3 = a+2
      If a=usum
        u2 = 1
        u3 = 2
      Else
        If a=usum-1
          u3 = 1
        EndIf
      EndIf
      
      ; now test whether this triangle is an "ear"
      ear.b = #True
      temp.TriangleStructure
      CopyStructure(@pnt(u(u1)\p),@temp\a,PointF)
      CopyStructure(@pnt(u(u2)\p),@temp\b,PointF)
      CopyStructure(@pnt(u(u3)\p),@temp\c,PointF)
      
      ; it must have some area - x coords must differ and y coords must differ
      If (temp\a\x=temp\b\x And temp\a\x=temp\c\x) Or (temp\a\y=temp\b\y And temp\a\y=temp\c\y)
        ear = #False
      EndIf
      ; it must have some area - no two consecutive points can be identical
      If PointsIdentical(temp\a,temp\b) Or PointsIdentical(temp\b,temp\c) Or PointsIdentical(temp\c,temp\a)
        R("CRASH. TWO POINTS THAT ARE CONSECUTIVE (AT LEAST AFTER CLIPPING) ARE ALSO IDENTICAL.")
        ProcedureReturn #False
        ear = #False
      EndIf
      
      ; it must not be convex
      If ear And AngleBetweenThreePoints(@pnt(u(u2)\p),@pnt(u(u3)\p),@pnt(u(u1)\p)) > 180
        ear = #False
      EndIf
      
      ; no other points must be inside it
      If ear
        For p = 1 To points
          If p<>u(u1)\p And p<>u(u2)\p And p<>u(u3)\p
            If PointIsInsideTriangle(@pnt(p),@temp)
              ;Debug "Point #"+Str(p)+" is inside triangle"
              ear = #False
              Break
            EndIf
          EndIf
        Next p
      EndIf
      
      
      If ear
        AddElement(temptri())
        CopyStructure(@temp,@temptri(),TriangleStructure)
        
        u(u2)\valid = #False
        usum = RemoveDeadPoints(usum,u())
        
        ;Break 2
        ;Break
      EndIf
      
    Next a
  Wend
  ;R("END USUM: "+Str(usum))
  If usum=3
    AddElement(temptri())
    founds = 0
    For a = 1 To usum
      If u(a)\valid
        p = u(a)\p
        founds+1
        Select founds
          Case 1
            CopyStructure(@pnt(p),@temptri()\a,PointF)
          Case 2
            CopyStructure(@pnt(p),@temptri()\b,PointF)
          Case 3
            CopyStructure(@pnt(p),@temptri()\c,PointF)
        EndSelect
      EndIf
    Next a
  EndIf
  
  *t\triangles = ListSize(temptri())
  Dim *t\triangle(*t\triangles)
  a=0
  ForEach temptri()
    a+1
    CopyStructure(@temptri(),*t\triangle(a),TriangleStructure)
  Next
  FreeList(temptri())
  
EndProcedure


Procedure.b TriangulatePolygon(points,Array pnt.PointF(1),*t.Triangulation)
  Select IdentifyPolygonType(points,pnt())
    Case #Polygon_Triangle ; the polygon IS a triangle, so no need to split it up
      *t\triangles = 1
      Dim *t\triangle(1)
      CopyStructure(@pnt(1),*t\triangle(1)\a,PointF)
      CopyStructure(@pnt(2),*t\triangle(1)\b,PointF)
      CopyStructure(@pnt(3),*t\triangle(1)\c,PointF)
      ProcedureReturn #True
    Case #Polygon_Concave
      ProcedureReturn TriangulateConcavePolygon(points,pnt(),*t)
    Case #Polygon_Convex
      ProcedureReturn TriangulateConvexPolygon(points,pnt(),*t)
  EndSelect
EndProcedure


Procedure.b ThickLine(*p1.PointF,*p2.PointF,clr.i)
  LineXY(*p1\x,*p1\y,*p2\x,*p2\y,clr)
  LineXY(*p1\x+1,*p1\y,*p2\x+1,*p2\y,clr)
  LineXY(*p1\x,*p1\y+1,*p2\x,*p2\y+1,clr)
  LineXY(*p1\x+1,*p1\y+1,*p2\x+1,*p2\y+1,clr)
  LineXY(*p1\x-1,*p1\y,*p2\x-1,*p2\y,clr)
  LineXY(*p1\x,*p1\y-1,*p2\x,*p2\y-1,clr)
  LineXY(*p1\x-1,*p1\y-1,*p2\x-1,*p2\y-1,clr)
EndProcedure


ExamineDesktops()
iw.f = DesktopWidth(0)
ih.f = DesktopHeight(0)

win = OpenWindow(#PB_Any,0,0,iw,ih,"Triangulation",#PB_Window_BorderLess)
SetWindowColor(win,#Black)
returnkey = 1
AddKeyboardShortcut(win,#PB_Shortcut_Return,returnkey)
escapekey = 2
AddKeyboardShortcut(win,#PB_Shortcut_Escape,escapekey)
imgad = ImageGadget(#PB_Any,0,0,iw,ih,0)
quit.b = #False

cnt.PointF
cnt\x = iw/2
cnt\y = ih/2
r.f = (ih/2)-5
Repeat
  points = 5+Random(15)
  ;points=30
  Dim pnt.PointF(points)
  deg.f = 360/(points-1)
  For p = 0 To points-1
    dist.f = r/100*(20+Random(75))
    DegreeCoordsFromPoint(@cnt,deg*p,dist,@pnt(p+1))
  Next p
  
  ;If IdentifyPolygonType(points,pnt())<>#Polygon_Concave : Continue : EndIf ; use this line to see only concave, convex, etc.
  
  pgimg = CreateImage(#PB_Any,iw,ih,32,#PB_Image_Transparent)
  StartDrawing(ImageOutput(pgimg))
  DrawingMode(#PB_2DDrawing_AlphaBlend)
  outlineclr = RGBA(255,255,255,255)
  For p = 1 To points-1
    ThickLine(@pnt(p),@pnt(p+1),outlineclr)
  Next p
  ThickLine(@pnt(points),@pnt(1),outlineclr) ; closer line (back to first point)
  StopDrawing()
  
  img = CreateImage(#PB_Any,iw,ih,32)
  StartDrawing(ImageOutput(img))
  
  start = ElapsedMilliseconds()
  TriangulatePolygon(points,pnt(),@tri.Triangulation)
  finish = ElapsedMilliseconds()
  
  If tri\triangles
    For t = 1 To tri\triangles
      clr = RGB(Random(255),Random(255),Random(255))
      DrawTriangle(tri\triangle(t),clr)
    Next t
  EndIf
  
  DrawAlphaImage(ImageID(pgimg),0,0,255)
  For p = 1 To points
    Circle(pnt(p)\x,pnt(p)\y,2,#White)
  Next p
  FreeImage(pgimg)
  
  DrawText(20,20,Str(points)+" vertices",#White)
  DrawText(20,36,Str(tri\triangles)+" triangles",#White)
  DrawText(20,52,"Processing time: "+Str(finish-start)+"ms",#White)
  
  StopDrawing()
  SetGadgetState(imgad,ImageID(img))
  
  
  Repeat
    Delay(10)
    If WindowEvent()=#PB_Event_Menu
      Select EventMenu()
        Case returnkey
          Break
        Case escapekey
          quit = #True
          Break
      EndSelect
    EndIf
  ForEver
  FreeImage(img)
  
Until quit
CloseWindow(win)
Last edited by Seymour Clufley on Sun Sep 29, 2013 9:35 pm, edited 1 time in total.
JACK WEBB: "Coding in C is like sculpting a statue using only sandpaper. You can do it, but the result wouldn't be any better. So why bother? Just use the right tools and get the job done."
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Advice needed before I begin a project

Post by IdeasVacuum »

Excellent job Seymour 8)
I very much doubt that you will encounter shapes as difficult as that for the real-world project, so you are well on the way to what you require.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
Samuel
Enthusiast
Enthusiast
Posts: 756
Joined: Sun Jul 29, 2012 10:33 pm
Location: United States

Re: Advice needed before I begin a project

Post by Samuel »

That's a very nice example. I tested it with a large amount of points and so far no issues.
I'll let you know if I spot something when I'm tinkering with it.
Seymour Clufley
Addict
Addict
Posts: 1267
Joined: Wed Feb 28, 2007 9:13 am
Location: London

Re: Advice needed before I begin a project

Post by Seymour Clufley »

Thanks for the feedback, guys.

I should have said that this document helped me to do it, though I probably didn't follow it exactly. I also didn't bother to accommodate polygons containing holes - there aren't any such polygons in my town map so I don't need this ability.

I just can't believe that I managed it. I'm pretty sure I've overlooked something and there'll be a serious bug somewhere!
JACK WEBB: "Coding in C is like sculpting a statue using only sandpaper. You can do it, but the result wouldn't be any better. So why bother? Just use the right tools and get the job done."
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Advice needed before I begin a project

Post by IdeasVacuum »

IdeasVacuum
If it sounds simple, you have not grasped the complexity.
Seymour Clufley
Addict
Addict
Posts: 1267
Joined: Wed Feb 28, 2007 9:13 am
Location: London

Re: Advice needed before I begin a project

Post by Seymour Clufley »

I've run into a problem with creating meshes. Any shape which has four corners, and therefore only two triangles, only shows one of its triangles. I've made an example using two shapes.

Here's how it should look:
Image

Here's how it does look:
Image

The first shape displays correctly. The second shape, which is much simpler, doesn't.

Here's the code:

Code: Select all

Structure VectorF
	x.f
	y.f
	z.f
EndStructure

Structure TriangleStructure
	Array p.VectorF(3)
EndStructure

Structure Triangulation
	triangles.i
	Array triangle.TriangleStructure(0)
EndStructure




Global yellowmat.i

Procedure.i EntityFromTriangulation(*tri.Triangulation,xpos.f,zpos.f)
	
	msh = CreateMesh(#PB_Any,#PB_Mesh_TriangleList,#PB_Mesh_Dynamic)
	
	vertex = -1
	For t = 1 To *tri\triangles
		For p = 1 To 3
			MeshVertexPosition(*tri\triangle(t)\p(p)\x,*tri\triangle(t)\p(p)\y,*tri\triangle(t)\p(p)\z)
			vertex + 1
		Next p
		;MeshFace(vertex-2,vertex-1,vertex)
	Next t
	
	; finish...
	FinishMesh(#True)
	ent = CreateEntity(#PB_Any,MeshID(msh),MaterialID(yellowmat),xpos,0,zpos)
	
	ProcedureReturn ent
	
EndProcedure




;- PROGRAM START

Enumeration 1
	#KB_Escape
EndEnumeration

ExamineDesktops()
ww = DesktopWidth(0)
wh = DesktopHeight(0)-30
win = OpenWindow(#PB_Any,0,0,ww,wh,"Outer Bum",#PB_Window_ScreenCentered)
AddKeyboardShortcut(win,#PB_Shortcut_Escape,#KB_Escape)
InitEngine3D()
InitSprite()
screen = OpenWindowedScreen(WindowID(win),0,0,ww,wh)


Structure CameraStructure
	pb.i
	rotating.b
	shiftsize.f
	x.f
	y.f
	z.f
EndStructure
Global cam.CameraStructure

cam\pb = CreateCamera(#PB_Any,0,0,100,100)
CameraRange(cam\pb,0,10000)
CameraBackColor(cam\pb,#Black)
CameraProjectionMode(cam\pb,#PB_Camera_Perspective)
CameraFixedYawAxis(cam\pb,#False)
RotateCamera(cam\pb,-90,0,0)
cam\x = 200
cam\y = 500
cam\z = 0
MoveCamera(cam\pb,cam\x,cam\y,cam\z,#PB_Absolute|#PB_World)




whitetex = CreateTexture(#PB_Any,1024,1024)
If StartDrawing(TextureOutput(whitetex))
	DrawingMode(#PB_2DDrawing_Gradient)
	BackColor(#Gray)
	FrontColor(#White)
	CircularGradient(512,512,100)
	Box(0,0,1024,1024)
	StopDrawing()
EndIf
yellowmat = CreateMaterial(#PB_Any,TextureID(whitetex))
DisableMaterialLighting(yellowmat,#True)




tri.Triangulation


; This shape, which is much more complicated, comes out correctly.
tri\triangles = 9
Dim tri\triangle(tri\triangles)

tri\triangle(1)\p(1)\x = 0
tri\triangle(1)\p(1)\z = 0

tri\triangle(1)\p(2)\x = 0
tri\triangle(1)\p(2)\z = 45

tri\triangle(1)\p(3)\x = 20
tri\triangle(1)\p(3)\z = 65

tri\triangle(2)\p(1)\x = 20
tri\triangle(2)\p(1)\z = 65

tri\triangle(2)\p(2)\x = 20
tri\triangle(2)\p(2)\z = 85

tri\triangle(2)\p(3)\x = 110
tri\triangle(2)\p(3)\z = 85

tri\triangle(3)\p(1)\x = 20
tri\triangle(3)\p(1)\z = 65

tri\triangle(3)\p(2)\x = 110
tri\triangle(3)\p(2)\z = 85

tri\triangle(3)\p(3)\x = 240
tri\triangle(3)\p(3)\z = 67

tri\triangle(4)\p(1)\x = 240
tri\triangle(4)\p(1)\z = 67

tri\triangle(4)\p(2)\x = 240
tri\triangle(4)\p(2)\z = 5

tri\triangle(4)\p(3)\x = 205
tri\triangle(4)\p(3)\z = 5

tri\triangle(5)\p(1)\x = 240
tri\triangle(5)\p(1)\z = 67

tri\triangle(5)\p(2)\x = 205
tri\triangle(5)\p(2)\z = 5

tri\triangle(5)\p(3)\x = 190
tri\triangle(5)\p(3)\z = 20

tri\triangle(6)\p(1)\x = 240
tri\triangle(6)\p(1)\z = 67

tri\triangle(6)\p(2)\x = 190
tri\triangle(6)\p(2)\z = 20

tri\triangle(6)\p(3)\x = 135
tri\triangle(6)\p(3)\z = 20

tri\triangle(7)\p(1)\x = 135
tri\triangle(7)\p(1)\z = 20

tri\triangle(7)\p(2)\x = 115
tri\triangle(7)\p(2)\z = 0

tri\triangle(7)\p(3)\x = 0
tri\triangle(7)\p(3)\z = 0

tri\triangle(8)\p(1)\x = 240
tri\triangle(8)\p(1)\z = 67

tri\triangle(8)\p(2)\x = 135
tri\triangle(8)\p(2)\z = 20

tri\triangle(8)\p(3)\x = 0
tri\triangle(8)\p(3)\z = 0

tri\triangle(9)\p(1)\x = 240
tri\triangle(9)\p(1)\z = 67

tri\triangle(9)\p(2)\x = 0
tri\triangle(9)\p(2)\z = 0

tri\triangle(9)\p(3)\x = 20
tri\triangle(9)\p(3)\z = 65

EntityFromTriangulation(@tri,0,0)


; This shape doesn't come out correctly. It comprises two triangles, but only one of them shows.
tri\triangles = 2
Dim tri\triangle(tri\triangles)

tri\triangle(1)\p(1)\x = 120
tri\triangle(1)\p(1)\z = 0

tri\triangle(1)\p(2)\x = 120
tri\triangle(1)\p(2)\z = 41

tri\triangle(1)\p(3)\x = 0
tri\triangle(1)\p(3)\z = 0

tri\triangle(2)\p(1)\x = 120
tri\triangle(2)\p(1)\z = 41

tri\triangle(2)\p(2)\x = 0
tri\triangle(2)\p(2)\z = 0

tri\triangle(2)\p(3)\x = 0
tri\triangle(2)\p(3)\z = 60

EntityFromTriangulation(@tri,250,5)




Repeat
	Select WindowEvent()
		Case #PB_Event_CloseWindow
			Break
		Case #PB_Event_Menu
			Select EventMenu()
				Case #KB_Escape
					Break
			EndSelect
	EndSelect
	RenderWorld()
	FlipBuffers()
	Delay(10)
ForEver
It's probably that I'm not doing something correctly. If anyone could tell me what it is, I'd be very grateful. The whole PB Mesh thing is confusing me!
JACK WEBB: "Coding in C is like sculpting a statue using only sandpaper. You can do it, but the result wouldn't be any better. So why bother? Just use the right tools and get the job done."
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Advice needed before I begin a project

Post by IdeasVacuum »

The points need to be in sequence (If SubSystem = OpenGL, may need to be anticlockwise sequence):

Code: Select all

Structure VectorF
   x.d
   y.d
   z.d
EndStructure

Structure TriangleStructure
   Array p.VectorF(3)
EndStructure

Structure Triangulation
   triangles.i
   Array triangle.TriangleStructure(0)
EndStructure




Global yellowmat.i

Procedure.i EntityFromTriangulation(*tri.Triangulation,xpos.d,zpos.d)
   
   msh = CreateMesh(#PB_Any,#PB_Mesh_TriangleList,#PB_Mesh_Dynamic)
   
   vertex = -1
   For t = 1 To *tri\triangles
      For p = 1 To 3
         MeshVertexPosition(*tri\triangle(t)\p(p)\x,*tri\triangle(t)\p(p)\y,*tri\triangle(t)\p(p)\z)
         vertex + 1
      Next p
      ;MeshFace(vertex-2,vertex-1,vertex)
   Next t
   
   ; finish...
   FinishMesh(#True)
   ent = CreateEntity(#PB_Any,MeshID(msh),MaterialID(yellowmat),xpos,0,zpos)
   
   ProcedureReturn ent
   
EndProcedure




;- PROGRAM START

Enumeration 1
   #KB_Escape
EndEnumeration

ExamineDesktops()
ww = DesktopWidth(0)-20
wh = DesktopHeight(0)-30
win = OpenWindow(#PB_Any,0,0,ww,wh,"Outer Bum",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
AddKeyboardShortcut(win,#PB_Shortcut_Escape,#KB_Escape)
InitEngine3D()
InitSprite()
screen = OpenWindowedScreen(WindowID(win),0,0,ww,wh)


Structure CameraStructure
   pb.i
   rotating.b
   shiftsize.f
   x.f
   y.f
   z.f
EndStructure
Global cam.CameraStructure

cam\pb = CreateCamera(#PB_Any,0,0,100,100)
CameraRange(cam\pb,0,10000)
CameraBackColor(cam\pb,#Black)
CameraProjectionMode(cam\pb,#PB_Camera_Perspective)
CameraFixedYawAxis(cam\pb,#False)
RotateCamera(cam\pb,-90,0,0)
cam\x = 200
cam\y = 500
cam\z = 0
MoveCamera(cam\pb,cam\x,cam\y,cam\z,#PB_Absolute|#PB_World)




whitetex = CreateTexture(#PB_Any,1024,1024)
If StartDrawing(TextureOutput(whitetex))
   DrawingMode(#PB_2DDrawing_Gradient)
   BackColor(#Gray)
   FrontColor(#White)
   CircularGradient(512,512,100)
   Box(0,0,1024,1024)
   StopDrawing()
EndIf
yellowmat = CreateMaterial(#PB_Any,TextureID(whitetex))
DisableMaterialLighting(yellowmat,#True)




tri.Triangulation


; This shape, which is much more complicated, comes out correctly.
tri\triangles = 9
Dim tri\triangle(tri\triangles)

tri\triangle(1)\p(1)\x = 0
tri\triangle(1)\p(1)\z = 0

tri\triangle(1)\p(2)\x = 0
tri\triangle(1)\p(2)\z = 45

tri\triangle(1)\p(3)\x = 20
tri\triangle(1)\p(3)\z = 65

tri\triangle(2)\p(1)\x = 20
tri\triangle(2)\p(1)\z = 65

tri\triangle(2)\p(2)\x = 20
tri\triangle(2)\p(2)\z = 85

tri\triangle(2)\p(3)\x = 110
tri\triangle(2)\p(3)\z = 85

tri\triangle(3)\p(1)\x = 20
tri\triangle(3)\p(1)\z = 65

tri\triangle(3)\p(2)\x = 110
tri\triangle(3)\p(2)\z = 85

tri\triangle(3)\p(3)\x = 240
tri\triangle(3)\p(3)\z = 67

tri\triangle(4)\p(1)\x = 240
tri\triangle(4)\p(1)\z = 67

tri\triangle(4)\p(2)\x = 240
tri\triangle(4)\p(2)\z = 5

tri\triangle(4)\p(3)\x = 205
tri\triangle(4)\p(3)\z = 5

tri\triangle(5)\p(1)\x = 240
tri\triangle(5)\p(1)\z = 67

tri\triangle(5)\p(2)\x = 205
tri\triangle(5)\p(2)\z = 5

tri\triangle(5)\p(3)\x = 190
tri\triangle(5)\p(3)\z = 20

tri\triangle(6)\p(1)\x = 240
tri\triangle(6)\p(1)\z = 67

tri\triangle(6)\p(2)\x = 190
tri\triangle(6)\p(2)\z = 20

tri\triangle(6)\p(3)\x = 135
tri\triangle(6)\p(3)\z = 20

tri\triangle(7)\p(1)\x = 135
tri\triangle(7)\p(1)\z = 20

tri\triangle(7)\p(2)\x = 115
tri\triangle(7)\p(2)\z = 0

tri\triangle(7)\p(3)\x = 0
tri\triangle(7)\p(3)\z = 0

tri\triangle(8)\p(1)\x = 240
tri\triangle(8)\p(1)\z = 67

tri\triangle(8)\p(2)\x = 135
tri\triangle(8)\p(2)\z = 20

tri\triangle(8)\p(3)\x = 0
tri\triangle(8)\p(3)\z = 0

tri\triangle(9)\p(1)\x = 240
tri\triangle(9)\p(1)\z = 67

tri\triangle(9)\p(2)\x = 0
tri\triangle(9)\p(2)\z = 0

tri\triangle(9)\p(3)\x = 20
tri\triangle(9)\p(3)\z = 65

EntityFromTriangulation(@tri,0,0)


; This shape doesn't come out correctly. It comprises two triangles, but only one of them shows.
tri\triangles = 2
Dim tri\triangle(tri\triangles)

tri\triangle(1)\p(1)\x = 0
tri\triangle(1)\p(1)\z = 0

tri\triangle(1)\p(2)\x = 120
tri\triangle(1)\p(2)\z = 41

tri\triangle(1)\p(3)\x = 120
tri\triangle(1)\p(3)\z = 0

tri\triangle(2)\p(1)\x = 0
tri\triangle(2)\p(1)\z = 0

tri\triangle(2)\p(2)\x = 0
tri\triangle(2)\p(2)\z = 60

tri\triangle(2)\p(3)\x = 120
tri\triangle(2)\p(3)\z = 41

EntityFromTriangulation(@tri,250,5)




Repeat
   Select WindowEvent()
      Case #PB_Event_CloseWindow
         Break
      Case #PB_Event_Menu
         Select EventMenu()
            Case #KB_Escape
               Break
         EndSelect
   EndSelect
   RenderWorld()
   FlipBuffers()
   Delay(10)
ForEver
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
Seymour Clufley
Addict
Addict
Posts: 1267
Joined: Wed Feb 28, 2007 9:13 am
Location: London

Re: Advice needed before I begin a project

Post by Seymour Clufley »

Thanks, IV. Do you mean the points of each triangle, or the triangles themselves? I've been wondering whether it will matter which order the vertices are added to a mesh.
JACK WEBB: "Coding in C is like sculpting a statue using only sandpaper. You can do it, but the result wouldn't be any better. So why bother? Just use the right tools and get the job done."
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Advice needed before I begin a project

Post by IdeasVacuum »

...The points of each triangle. I'd go for anti-clockwise, just incase it matters later.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
Seymour Clufley
Addict
Addict
Posts: 1267
Joined: Wed Feb 28, 2007 9:13 am
Location: London

Re: Advice needed throughout my first 3D project

Post by Seymour Clufley »

I'm making good progress with my project. Here is a screenshot:

Image

But, as you can see, there are no shadows and you can't tell the side of a building from the roof. I did add a light but that had no effect on the scene whatsoever.

Adding either of these lines:
WorldShadows(#PB_Shadow_Modulative)
WorldShadows(#PB_Shadow_Additive)
causes this immediate crash:
Image

Could this be related to the fact that I have no graphics card? I'm using the motherboard's onboard graphics. This seems like a ridiculous question but I have to ask, since everything has been working fine up till now.
JACK WEBB: "Coding in C is like sculpting a statue using only sandpaper. You can do it, but the result wouldn't be any better. So why bother? Just use the right tools and get the job done."
User avatar
Bananenfreak
Enthusiast
Enthusiast
Posts: 519
Joined: Mon Apr 15, 2013 12:22 pm

Re: Advice needed throughout my first 3D project

Post by Bananenfreak »

I don´t think this will be a solution, but add for every Mesh

Code: Select all

BuildMeshShadowVolume()
.

http://www.ogre3d.org/forums/viewtopic.php?f=2&t=68371
There could also be a Problem with your selfbuild houses.
Image
User avatar
Samuel
Enthusiast
Enthusiast
Posts: 756
Joined: Sun Jul 29, 2012 10:33 pm
Location: United States

Re: Advice needed throughout my first 3D project

Post by Samuel »

Looks like your mesh lacks normals.

EDIT: You can use NormalizeMesh(#Mesh [, SubMesh]) to generate flat shading. Just make sure every face has its own 3 vertices.
If the face is sharing a vertex with a another the command won't work right. The reason is each vertex can only have one normal, but you can have many vertices at the same point each with a different normal. That will give you flat shading and for a building I believe that's what you want.

In order to get smooth shading like for a sphere. You have to calculate the average normal of the faces that are connected at a shared vertex. Then use MeshVertexNormal(x, y, z) to set the individual normal for that vertex.

I'm sorry If I confused you with all this gibberish. I'm not the best when it comes to explaining this stuff. I'm sure you can find some more info on vertex normals with a little searching.
Last edited by Samuel on Sat Oct 05, 2013 6:42 pm, edited 2 times in total.
User avatar
Comtois
Addict
Addict
Posts: 1432
Joined: Tue Aug 19, 2003 11:36 am
Location: Doubs - France

Re: Advice needed throughout my first 3D project

Post by Comtois »

without a snipet, it's difficult to say why it crash, may be because you dont use index ?

http://www.forums.purebasic.com/english ... 36&t=56514


[EDIT]
I have tested your code, add this and it will not crash.

Code: Select all

MeshFace(vertex-2,vertex-1,vertex)
Please correct my english
http://purebasic.developpez.com/
Post Reply