glob3mobile / g3m

The multiplatform advanced visualization framework
http://www.glob3mobile.com/
Other
116 stars 56 forks source link

LineShape in iOS #212

Open mememto opened 7 years ago

mememto commented 7 years ago

Hi to everyone and thanks in advance. I've made LineShape class for iOS but i'm experiencing some kind of problems. The class seems to work fine, but whenever I call shapesRenderer->removeAllShapes(); i get the following exception:

pointer being freed was not allocated *** set a breakpoint in malloc_error_break to debug

Not sure of what is causing this. Any help would be appreciated since it's been years since the last time i used C++ :/ By the way sorry for the indentation, not sure of how to do this :/

.HPP class LineShape : public AbstractMeshShape { private: void computeOrientationParams(const Planet *planet); protected: Mesh* createMesh(const G3MRenderContext* rc); public: float _width; Color* _color; Vector3D* _cartesianStartPos; Geodetic3D* _geodeticEndPos;

`LineShape(Geodetic3D* startPosition,`
         `Geodetic3D* endPosition,`
         `AltitudeMode altitudeMode,`
         `float width,`
         `const Color& color) :`
`AbstractMeshShape(startPosition, altitudeMode),`
`_cartesianStartPos(),`
`_geodeticEndPos(endPosition),`
`_width(width),`
`_color(new Color(color))`
`{}`

`~LineShape() {`
    `delete _color;`
    `delete _cartesianStartPos;`
    `delete _geodeticEndPos;`
`}`

std::vector<double> intersectionsDistances(const Planet* planet, const Vector3D& origin, const Vector3D& direction) const; };

.CPP void LineShape::computeOrientationParams(const Planet *planet) {

_cartesianStartPos = new Vector3D(planet->toCartesian(getPosition()));
Vector3D cartesianEndPos(planet->toCartesian(*_geodeticEndPos));
Vector3D line = cartesianEndPos.sub(*_cartesianStartPos);
setScale(1, 1, line.length());
Vector3D normal = planet->geodeticSurfaceNormal(*_cartesianStartPos);
setPitch(line.angleBetween(normal).times(-1));
Vector3D north2D = planet->getNorth().projectionInPlane(normal);
Vector3D projectedLine = line.projectionInPlane(normal);
setHeading(projectedLine.signedAngleBetween(north2D, normal));

}

Mesh* LineShape::createMesh(const G3MRenderContext* rc) { FloatBufferBuilderFromCartesian3D* vertices = FloatBufferBuilderFromCartesian3D::builderWithoutCenter();

vertices->add(0.0f, 0.0f, 0.0f); vertices->add(0.0f, 0.0f, 1.0f);

`if (_cartesianStartPos == NULL)`
    `computeOrientationParams(rc->getPlanet());`

`Mesh* mesh = new DirectMesh(GLPrimitive::lines(), true, vertices->getCenter(), vertices->create(), _width, 1, _color);`

`delete vertices;`

`return mesh;`

}

std::vector<double> LineShape::intersectionsDistances(const Planet* planet, const Vector3D& origin, const Vector3D& direction) const {

`std::vector<double> intersections;`
`return intersections;`

}

DiegoGomezDeck commented 7 years ago

Hi @mememto

It doesn't look like a G3M issue.

BTW, taking a very quick overview, the problem seems to be that _cartesianStartPos pointer is not initialized to NULL and it has a dangling pointer.

DiegoGomezDeck commented 7 years ago

And please google for "xcode add exception breakpoint". It's very helpful to know where the exception is thrown.

mememto commented 7 years ago

Hi @DiegoGomezDeck. Thanks for your tip, i will check in some hours and let you know something.

mememto commented 7 years ago

Hi again @DiegoGomezDeck. I've initialized _cartesianStartPos to NULL, but the same thing happens. To get deep into the issue this is how i use LineShape:

- (void) paintLines { if (points != nil && points.count > 0) { shapesRenderer->removeAllShapes(); for (int i = 0; i < points.count - 1; i++) { Geodetic3D *origin = new Geodetic3D(Angle::fromDegrees(((CLLocation *)[points objectAtIndex:i]).coordinate.latitude), Angle::fromDegrees(((CLLocation *)[points objectAtIndex:i]).coordinate.longitude), 0); Geodetic3D *end = new Geodetic3D(Angle::fromDegrees(((CLLocation *)[points objectAtIndex:(i+1)]).coordinate.latitude), Angle::fromDegrees(((CLLocation *)[points objectAtIndex:(i+1)]).coordinate.longitude), 0); Shape *line = new LineShape(origin, end, RELATIVE_TO_GROUND, 10, Color::fromRGBA(1.0f, 0.0f, 0.0f, 1.0f)); shapesRenderer->addShape(line); } [self paintPoints]; } }

This method is called several times, since the number of CLLocation elements inside points array is increased or decreased depending on user. My objective is to draw a multi-line. If there are at least two CLLocation elements inside points array, the for loop creates one new ShapeLine and add it to shapesRenderer:

shapesRenderer = builder.createShapesRenderer(); builder.addRenderer(shapesRenderer);

This works fine. The problem takes place when one CLLocation element is added to points array and the paintLines method is called again. This time, the shapesRenderer->removeAllShapes(); triggers an malloc_error_break exception complaining about delete _flatColor; line in AbstractMesh.cpp file. Any suggestions? Thanks in advance =)

mememto commented 7 years ago

One more thing, commenting the delete _flatColor line seems to fix the issue, but i'm not sure of how this will affect other things 😣

mememto commented 7 years ago

Anyway, the result is not as promising as i thought. Here is a screenshot of the "multi-line". Only the first segment seems visible, the others are strangely cut:

image

DiegoGomezDeck commented 7 years ago

Mesh* mesh = new DirectMesh(GLPrimitive::lines(), true, vertices->getCenter(), vertices->create(), _width, 1, _color);

You're passing object hold in _color and also deleting it from the constructor. DirectMesh assumes it's the owner of _flatColor pointer and handles its deletion.

DiegoGomezDeck commented 7 years ago

Anyway, the result is not as promising as i thought. Here is a screenshot of the "multi-line". Only the first segment seems visible, the others are strangely cut:

Sure, you're drawing straight lines and the earth surface has a curvature. Disabling depth test helps sometimes.

mememto commented 7 years ago

Thanks for your help @DiegoGomezDeck