This issue could be summed up like this: how to turn a TGLPolygon into a TGLMultiPolygon?
Now the details:
I’m using GLscene to render a 3D representation of buildings. A building is made of construction elements (wall, roof, etc.). Each element is represented by a polygon, for which 3D coordinates are known.
Up to now, I’ve been using TGLPolygon to render these construction elements. Here’s what a sample building it looks like:
Now I’d like to take into account openings for doors and windows and display “holes” in those areas. I think using TGLMultipolygon instead of TGLPolygon is the right way to do this, as it allows to define an outer contour as well as various inner contours for the “holes”.
But I’m having trouble using TGLMultiPolygon. As I understand it, the contours must be defined in the XY plane, or otherwise they’re projected onto it.
So I project each of my 3D polygons onto their own plane in order to get a 2D polygon and build the outer contours. Here’s what the building walls looks like using TGLMultiPolygon. Everything is on the XY plane, as expected. I set up the positions of the TGLMultiPolygon at the original polygons’centers so placement should be OK.
Now I think I need to modify the “Direction” and “Up” vectors or the “rollangle”, “pitchAngle” and “turnAngle” properties of the TGLPolygons in order to orientate them properly. And that’s where I’m having trouble. If I had a single building, I could do it manually for each element. But here I need to be able to display any building. So I need a function that does it automatically for any element of any building. I already spend a lot of time playing with those parameters and whenever I fix the orientation of something, something else gets messed up. For example, here’s what it looks like after setting up the “direction” vector according to the normal vector of the original polygons:
Then some polygons should be rotated. But I cannot automatically find which ones and by which angle. In that particular case, it’s either by 90° or -90°.
So I’m stuck. Anyone could help?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi can you provide me your full project in a zip. It's to hard to tell you what's wrong with just this code.
Why you don't use methods in GLGeometry for vectors ?
It's not a good idea to use extend because it's not compatible with 64 bits use Double instead
Thanks
Cheers
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I extracted the relevant code and made a sample application. Please see attached zip.
Currently, the app uses our own library to represent and manipulate 2D and 3D objects. I might update to GLgeometry if I manage to display what I want using GLscene.
The function I'm having trouble with is called "AddGLMultiPolygon". It transforms a standard 3D polygon (array of 3D points) into a TGLMultiPolygon. That is done by projecting the 3D polygon onto its own plate in order to build the contour. However, by doing that I lose information about the polygone orientation.
Thanks in advance!
PS: There is a problem with sample app crashing when moving the camera around but I cannot figure out what's wrong. It doesn't happen in the original app.
Hi Bob i converted your sample to Lazarus, and take a look it seems the problem is in your D23PolypointToPolygon method. For me is wrong, this method dosen't project a point on a SPECIFIC plane so. You can see if you render only the first fourth polygons,
I've also a doubt with your "n" value ;)
Please try to use the methods in GLVectorGeometry unit you have all you need for making what you want and all methods are approved and deeply tested ;) AffineVectorMake
VectorSubstract
VectorAdd
VectorNormalize
VectorCrossProduct
VectorDotProduct
VectorLength
PointPlaneProjection
IsColinear
etc....
Ca ne sert à rien de réinventer la roue. Par exemple pour D3VectorsAreColinear il y a plus simple ;) regardes IsColinear
A+
Jérôme
Last edit: Jerome.D (BeanzMaster) 2020-04-06
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks for trying to help. I let this problem rest for a while bu I'm back at it trying to find a solution. Regarding your last comment, I'm not trying to reinvent the wheel, just using some code that dates from way back, maybe even before GLScene came around. But I'll look into the GLVectorGeometry as you suggested, and update my code accordingly.
Regarding the issue, I don't think the problem comes from the projection function. I tested it on a few polygons and it gives me what I expect. I think the problem probably rather comes from me. From what I am expecting, what I give this function to eat or from what I do with the result. So I need some help figuring that out.
Let's take a simple example:
1) A 3D polygon defined by the 4 following points: P1(0,0,0), P2(0,0,3), P3(6,6,3), P4(6,6,0). In the following picture, it’s represented by a TGLPolygon.
2) I’m trying to use a TGLMultiPolygon to represent it. So I need to create a contour on the XY plane representing the polygon. In order to do that, I project these 4 points onto the plane on which they all are. That plane is defined by:
- the point P0=(3,3,1.5), which corresponds to the center of the polygon
- the vector U=(0.707,0.707,0), which is on the XY plane
- the vector V=(0,0,1), along the Z axis.
The resulting 2D polygon, according to the new referential (p0,u,v), has the following 4 points (rounded coordinates) : a1(-4.24,-1.5), a2(-4.24,1.5), a3(4.24,1.5), a4(4.24,-1.5)
So this 2D polygon has the right dimensions, 8.48x3, which is what I was expecting.
Now when I create a contour, I use these 4 points to create nodes on the XY plane, just adding zero as Z coordinate. The 4 nodes are: (-4.24,-1.5,0), (-4.24,1.5,0), (4.24,1.5,0), (4.24,-1.5,0)
3) Then I set the position the TGLMultipolygon at the center point P0 (3,3,1.5) and setup the direction as vector n = (-0.707,0.707,0), which was the vector perpendicular to the original polygon. The result is this:
The position and the direction are correct. However, the GLMultipolygon is rotated. This could be corrected this by changing the rollangle but I have no idea how to evaluate the angle.
Does all this make sense or do I go at it all wrong? There might be something I haven’t understood about how to create the contour.
Thanks.
Last edit: bobmc 2020-05-14
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi Everton,
Sorry I only see your post now. Unfortunately, despite spending many hours on this last year, I was never able to figure out how to use the TGLMultipolygon properly. I think my latest post above sums it up well so if anyone has an idea how to solve this, your help is welcome!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hello,
I know this is an "cold case" but i faced it yesterday.
Your polygon coordinates are absolute 3d coordinates.
there ist currently no information about rotations and translations.
You can see it if you turn polyGL.ShowAxes on. All Polygons have the same positions and angles.
This ist not the way GLScene works. All Polygons should be defined in x/y plane around the centerpoint at 0/0 and then using Translation and Rotation to set it in the right places.
We can determine the needed informations as the position is the centerpoint. For the angles we can create a plane using 3 points and calculate the angles using vectoranglecosine.
I have made that in your procedure DisplayBuilding.
I am sure that it can be done more effectively.
procedureTForm4.DisplayBuilding(aResetCamera:Boolean=false);constcSteps=16;cFactWorld=1.5;vari,j:Integer;center:T3DPoint;polyGrd:TGLPolygon;polyGL:TGLPolygon;mPolyGL:TGLMultiPolygon;obj:TGLBaseSceneObject;poly3D:T3DPolyPoint;dMatrix,uMatrix:TMatrix;cp:T3DPoint;vcp:TAffineVector;Plane:THmgPlane;p1,p2,p3:TAffineVector; // to create the planebegin//removeexistingpolygonsi:=0;whilei<GLScene.Objects.Countdobeginobj:=GLScene.Objects[i];if(objisTGLExtrusionSolid)or(objisTGLPolygon)or(objisTGLMultiPolygon)or(objisTGLLines)thenbeginGLScene.Objects.Remove(obj,false);obj.Free;endelseInc(i);end;//worldextentinxandycoordinatesFdX:=Abs(FExtentP0[0])+Abs(FExtentP1[0]);FdY:=Abs(FExtentP0[1])+Abs(FExtentP1[1]);//centerofbuildingonXYplanecenter[0]:=(FExtentP0[0]+FExtentP1[0])/2;center[1]:=(FExtentP0[1]+FExtentP1[1])/2;center[2]:=0;//drawgroundrectangleifckShowGround.CheckedthenbeginpolyGrd:=TGLPolygon.Create(nil);withpolyGrddobeginMaterial.MaterialLibrary:=GLMaterialLibrary;Material.LibMaterialName:='Ground';AddNode(center[0]-cFactWorld*FdX,center[1]-cFactWorld*FdY,0);AddNode(center[0]+cFactWorld*FdX,center[1]-cFactWorld*FdY,0);AddNode(center[0]+cFactWorld*FdX,center[1]+cFactWorld*FdY,0);AddNode(center[0]-cFactWorld*FdX,center[1]+cFactWorld*FdY,0);end;GLScene.Objects.AddChild(polyGrd);end;GLDummyCube.Position.X:=center[0];GLDummyCube.Position.Y:=center[1];GLDummyCube.Position.Z:=center[2];GLDummyCube.CubeSize:=Max(FdX,FdY);GLDummyCube.Visible:=true;ifaResetCamerathenGLSCameraReset;fori:=0toLength(FBld)-1dobeginpoly3D:=FBLD[i];cp:=D3PolyPointCenter(poly3D);vcp:=AffineVectorMake(-cp[0],-cp[1],-cp[2]);Assert(Length(poly3D)>2);p1:=AffineVectorMake(poly3D[0][0],poly3D[0][1],poly3D[0][2]);p2:=AffineVectorMake(poly3D[1][0],poly3D[1][1],poly3D[1][2]);p3:=AffineVectorMake(poly3D[2][0],poly3D[2][1],poly3D[2][2]);Plane:=PlaneMake(p1,p2,p3);dMatrix:=CreateTranslationMatrix(vcp);dMatrix:=MatrixMultiPly(dMatrix,CreateRotationMatrix(ZVector,ArcCos(VectorAngleCosine(XHmgVector,Plane))));dMatrix:=MatrixMultiply(dMatrix,CreateRotationMatrix(YVector,ArcCos(VectorAngleCosine(ZHmgVector,Plane))));uMatrix:=dMatrix;InvertMatrix(uMatrix);//TGLPOLYGONifRadioGroup1.ItemIndex=0thenbeginpolyGL:=TGLPolygon.Create(nil);forj:=0toLength(poly3D)-1dobeginp1:=VectorTransform(AffineVectorMake(poly3D[j][0],poly3D[j][1],poly3D[j][2]),dMatrix);polyGL.AddNode(p1);end;polyGL.Matrix:=uMatrix;GLScene.Objects.AddChild(polyGL);endelsebeginmpolyGL:=TGLMultiPolygon.Create(nil);forj:=0toLength(poly3D)-1dobeginp1:=VectorTransform(AffineVectorMake(poly3D[j][0],poly3D[j][1],poly3D[j][2]),dMatrix);mpolyGL.AddNode(0,p1);end;mpolyGL.Matrix:=uMatrix;GLScene.Objects.AddChild(mpolyGL);end;end;end;
Michael
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
after playing around with your building i see that there are some wrong polygons.
Within the code above i stupidly used the 3 first points to create a plane.
Unfortunatily are some polygons where the first 3 points lay on a straight line that cannot build an plane.
Michael
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi,
This issue could be summed up like this: how to turn a TGLPolygon into a TGLMultiPolygon?
Now the details:
I’m using GLscene to render a 3D representation of buildings. A building is made of construction elements (wall, roof, etc.). Each element is represented by a polygon, for which 3D coordinates are known.
Up to now, I’ve been using TGLPolygon to render these construction elements. Here’s what a sample building it looks like:
Now I’d like to take into account openings for doors and windows and display “holes” in those areas. I think using TGLMultipolygon instead of TGLPolygon is the right way to do this, as it allows to define an outer contour as well as various inner contours for the “holes”.
But I’m having trouble using TGLMultiPolygon. As I understand it, the contours must be defined in the XY plane, or otherwise they’re projected onto it.
So I project each of my 3D polygons onto their own plane in order to get a 2D polygon and build the outer contours. Here’s what the building walls looks like using TGLMultiPolygon. Everything is on the XY plane, as expected. I set up the positions of the TGLMultiPolygon at the original polygons’centers so placement should be OK.
Now I think I need to modify the “Direction” and “Up” vectors or the “rollangle”, “pitchAngle” and “turnAngle” properties of the TGLPolygons in order to orientate them properly. And that’s where I’m having trouble. If I had a single building, I could do it manually for each element. But here I need to be able to display any building. So I need a function that does it automatically for any element of any building. I already spend a lot of time playing with those parameters and whenever I fix the orientation of something, something else gets messed up. For example, here’s what it looks like after setting up the “direction” vector according to the normal vector of the original polygons:
Then some polygons should be rotated. But I cannot automatically find which ones and by which angle. In that particular case, it’s either by 90° or -90°.
So I’m stuck. Anyone could help?
Hi can you provide you're sample code please.
Cheers
Hi Jerome,
Here's a extact from my code:
First some types definition: a building is made of polygons, which are made of XYZ points.
Then the global function which is called to daw a building:
and finally, the function that I cannot get to work properly, which is supposed to return a TGLMultiPolygon:
The problem is when I project the polygon onto its on plane, in order to build the contour, I lose its orientation.
Thanks for your help.
Last edit: bobmc 2020-03-26
Hi can you provide me your full project in a zip. It's to hard to tell you what's wrong with just this code.
Why you don't use methods in GLGeometry for vectors ?
It's not a good idea to use extend because it's not compatible with 64 bits use Double instead
Thanks
Cheers
Hi,
I extracted the relevant code and made a sample application. Please see attached zip.
Currently, the app uses our own library to represent and manipulate 2D and 3D objects. I might update to GLgeometry if I manage to display what I want using GLscene.
The function I'm having trouble with is called "AddGLMultiPolygon". It transforms a standard 3D polygon (array of 3D points) into a TGLMultiPolygon. That is done by projecting the 3D polygon onto its own plate in order to build the contour. However, by doing that I lose information about the polygone orientation.
Thanks in advance!
PS: There is a problem with sample app crashing when moving the camera around but I cannot figure out what's wrong. It doesn't happen in the original app.
Last edit: bobmc 2020-03-31
Hi Bob i converted your sample to Lazarus, and take a look it seems the problem is in your D23PolypointToPolygon method. For me is wrong, this method dosen't project a point on a SPECIFIC plane so. You can see if you render only the first fourth polygons,
I've also a doubt with your "n" value ;)
Please try to use the methods in GLVectorGeometry unit you have all you need for making what you want and all methods are approved and deeply tested ;)
AffineVectorMake
VectorSubstract
VectorAdd
VectorNormalize
VectorCrossProduct
VectorDotProduct
VectorLength
PointPlaneProjection
IsColinear
etc....
Ca ne sert à rien de réinventer la roue. Par exemple pour D3VectorsAreColinear il y a plus simple ;) regardes IsColinear
A+
Jérôme
Last edit: Jerome.D (BeanzMaster) 2020-04-06
Hi,
Thanks for trying to help. I let this problem rest for a while bu I'm back at it trying to find a solution. Regarding your last comment, I'm not trying to reinvent the wheel, just using some code that dates from way back, maybe even before GLScene came around. But I'll look into the GLVectorGeometry as you suggested, and update my code accordingly.
Regarding the issue, I don't think the problem comes from the projection function. I tested it on a few polygons and it gives me what I expect. I think the problem probably rather comes from me. From what I am expecting, what I give this function to eat or from what I do with the result. So I need some help figuring that out.
Let's take a simple example:
1) A 3D polygon defined by the 4 following points: P1(0,0,0), P2(0,0,3), P3(6,6,3), P4(6,6,0). In the following picture, it’s represented by a TGLPolygon.
2) I’m trying to use a TGLMultiPolygon to represent it. So I need to create a contour on the XY plane representing the polygon. In order to do that, I project these 4 points onto the plane on which they all are. That plane is defined by:
- the point P0=(3,3,1.5), which corresponds to the center of the polygon
- the vector U=(0.707,0.707,0), which is on the XY plane
- the vector V=(0,0,1), along the Z axis.
The resulting 2D polygon, according to the new referential (p0,u,v), has the following 4 points (rounded coordinates) : a1(-4.24,-1.5), a2(-4.24,1.5), a3(4.24,1.5), a4(4.24,-1.5)
So this 2D polygon has the right dimensions, 8.48x3, which is what I was expecting.
Now when I create a contour, I use these 4 points to create nodes on the XY plane, just adding zero as Z coordinate. The 4 nodes are: (-4.24,-1.5,0), (-4.24,1.5,0), (4.24,1.5,0), (4.24,-1.5,0)
3) Then I set the position the TGLMultipolygon at the center point P0 (3,3,1.5) and setup the direction as vector n = (-0.707,0.707,0), which was the vector perpendicular to the original polygon. The result is this:
The position and the direction are correct. However, the GLMultipolygon is rotated. This could be corrected this by changing the rollangle but I have no idea how to evaluate the angle.
Does all this make sense or do I go at it all wrong? There might be something I haven’t understood about how to create the contour.
Thanks.
Last edit: bobmc 2020-05-14
Hello bobmc,
I am facing the same difficulty that you had, did you find any solution?
Hi Everton,
Sorry I only see your post now. Unfortunately, despite spending many hours on this last year, I was never able to figure out how to use the TGLMultipolygon properly. I think my latest post above sums it up well so if anyone has an idea how to solve this, your help is welcome!
Hello,
I know this is an "cold case" but i faced it yesterday.
Your polygon coordinates are absolute 3d coordinates.
there ist currently no information about rotations and translations.
You can see it if you turn polyGL.ShowAxes on. All Polygons have the same positions and angles.
This ist not the way GLScene works. All Polygons should be defined in x/y plane around the centerpoint at 0/0 and then using Translation and Rotation to set it in the right places.
We can determine the needed informations as the position is the centerpoint. For the angles we can create a plane using 3 points and calculate the angles using vectoranglecosine.
I have made that in your procedure DisplayBuilding.
I am sure that it can be done more effectively.
Michael
Hello,
after playing around with your building i see that there are some wrong polygons.
Within the code above i stupidly used the 3 first points to create a plane.
Unfortunatily are some polygons where the first 3 points lay on a straight line that cannot build an plane.
Michael