Page 2 of 3

Re: Advice needed before I begin a project

Posted: Sun Sep 29, 2013 2:58 am
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

Re: Advice needed before I begin a project

Posted: Sun Sep 29, 2013 10:08 am
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.

Re: Advice needed before I begin a project

Posted: Sun Sep 29, 2013 7:36 pm
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)

Re: Advice needed before I begin a project

Posted: Sun Sep 29, 2013 8:36 pm
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.

Re: Advice needed before I begin a project

Posted: Sun Sep 29, 2013 8:59 pm
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.

Re: Advice needed before I begin a project

Posted: Sun Sep 29, 2013 9:25 pm
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!

Re: Advice needed before I begin a project

Posted: Mon Sep 30, 2013 11:18 pm
by IdeasVacuum

Re: Advice needed before I begin a project

Posted: Fri Oct 04, 2013 2:25 am
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!

Re: Advice needed before I begin a project

Posted: Fri Oct 04, 2013 3:08 am
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

Re: Advice needed before I begin a project

Posted: Fri Oct 04, 2013 3:23 am
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.

Re: Advice needed before I begin a project

Posted: Fri Oct 04, 2013 3:42 am
by IdeasVacuum
...The points of each triangle. I'd go for anti-clockwise, just incase it matters later.

Re: Advice needed throughout my first 3D project

Posted: Sat Oct 05, 2013 5:28 pm
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.

Re: Advice needed throughout my first 3D project

Posted: Sat Oct 05, 2013 6:17 pm
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.

Re: Advice needed throughout my first 3D project

Posted: Sat Oct 05, 2013 6:26 pm
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.

Re: Advice needed throughout my first 3D project

Posted: Sat Oct 05, 2013 6:31 pm
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)