コード例 #1
0
void ofApp::mapData() {
	//map the data
	for (int j = 0; j < _csv.data.size(); j++) {
		float myX = ofMap(ofToFloat(_csv.data[j][0]), -180, 180, 2000, -2000);
		float myY = ofMap(ofToFloat(_csv.data[j][1]), -90, 90, -1000, 1000);
		ofVec3f thisPoint(myY, myX, 0.0f);
		_mesh.addVertex(thisPoint);
		_mesh.addColor(ofFloatColor(1, 1));
	}
}
コード例 #2
0
ファイル: Circle3DOverlay.cpp プロジェクト: MarcelEdward/hifi
void Circle3DOverlay::render(RenderArgs* args) {
    if (!_visible) {
        return; // do nothing if we're not visible
    }

    float alpha = getAlpha();

    if (alpha == 0.0f) {
        return; // do nothing if our alpha is 0, we're not visible
    }

    // Create the circle in the coordinates origin
    float outerRadius = getOuterRadius();
    float innerRadius = getInnerRadius(); // only used in solid case
    float startAt = getStartAt();
    float endAt = getEndAt();

    bool geometryChanged = (startAt != _lastStartAt || endAt != _lastEndAt ||
                                innerRadius != _lastInnerRadius || outerRadius != _lastOuterRadius);


    const float FULL_CIRCLE = 360.0f;
    const float SLICES = 180.0f;  // The amount of segment to create the circle
    const float SLICE_ANGLE = FULL_CIRCLE / SLICES;

    //const int slices = 15;
    xColor colorX = getColor();
    const float MAX_COLOR = 255.0f;
    glm::vec4 color(colorX.red / MAX_COLOR, colorX.green / MAX_COLOR, colorX.blue / MAX_COLOR, alpha);

    bool colorChanged = colorX.red != _lastColor.red || colorX.green != _lastColor.green || colorX.blue != _lastColor.blue;
    _lastColor = colorX;

    auto geometryCache = DependencyManager::get<GeometryCache>();
    
    Q_ASSERT(args->_batch);
    auto& batch = *args->_batch;
    batch._glLineWidth(_lineWidth);
    
    auto transform = _transform;
    transform.postScale(glm::vec3(getDimensions(), 1.0f));
    batch.setModelTransform(transform);
    DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch, false, false);
    
    // for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise
    // we just draw a line...
    if (getIsSolid()) {
        if (_quadVerticesID == GeometryCache::UNKNOWN_ID) {
            _quadVerticesID = geometryCache->allocateID();
        }
        
        if (geometryChanged || colorChanged) {
            
            QVector<glm::vec2> points;
            
            float angle = startAt;
            float angleInRadians = glm::radians(angle);
            glm::vec2 mostRecentInnerPoint(cosf(angleInRadians) * innerRadius, sinf(angleInRadians) * innerRadius);
            glm::vec2 mostRecentOuterPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
            
            while (angle < endAt) {
                angleInRadians = glm::radians(angle);
                glm::vec2 thisInnerPoint(cosf(angleInRadians) * innerRadius, sinf(angleInRadians) * innerRadius);
                glm::vec2 thisOuterPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
                
                points << mostRecentInnerPoint << mostRecentOuterPoint << thisOuterPoint; // first triangle
                points << mostRecentInnerPoint << thisInnerPoint << thisOuterPoint; // second triangle
                
                angle += SLICE_ANGLE;

                mostRecentInnerPoint = thisInnerPoint;
                mostRecentOuterPoint = thisOuterPoint;
            }
            
            // get the last slice portion....
            angle = endAt;
            angleInRadians = glm::radians(angle);
            glm::vec2 lastInnerPoint(cosf(angleInRadians) * innerRadius, sinf(angleInRadians) * innerRadius);
            glm::vec2 lastOuterPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);

            points << mostRecentInnerPoint << mostRecentOuterPoint << lastOuterPoint; // first triangle
            points << mostRecentInnerPoint << lastInnerPoint << lastOuterPoint; // second triangle
            
            geometryCache->updateVertices(_quadVerticesID, points, color);
        }
        
        geometryCache->renderVertices(batch, gpu::TRIANGLES, _quadVerticesID);
        
    } else {
        if (_lineVerticesID == GeometryCache::UNKNOWN_ID) {
            _lineVerticesID = geometryCache->allocateID();
        }
        
        if (geometryChanged || colorChanged) {
            QVector<glm::vec2> points;
            
            float angle = startAt;
            float angleInRadians = glm::radians(angle);
            glm::vec2 firstPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
            points << firstPoint;
            
            while (angle < endAt) {
                angle += SLICE_ANGLE;
                angleInRadians = glm::radians(angle);
                glm::vec2 thisPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
                points << thisPoint;
                
                if (getIsDashedLine()) {
                    angle += SLICE_ANGLE / 2.0f; // short gap
                    angleInRadians = glm::radians(angle);
                    glm::vec2 dashStartPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
                    points << dashStartPoint;
                }
            }
            
            // get the last slice portion....
            angle = endAt;
            angleInRadians = glm::radians(angle);
            glm::vec2 lastPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius);
            points << lastPoint;
            
            geometryCache->updateVertices(_lineVerticesID, points, color);
        }
        
        if (getIsDashedLine()) {
            geometryCache->renderVertices(batch, gpu::LINES, _lineVerticesID);
        } else {
            geometryCache->renderVertices(batch, gpu::LINE_STRIP, _lineVerticesID);
        }
    }
    
    // draw our tick marks
    // for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise
    // we just draw a line...
    if (getHasTickMarks()) {
        
        if (_majorTicksVerticesID == GeometryCache::UNKNOWN_ID) {
            _majorTicksVerticesID = geometryCache->allocateID();
        }
        if (_minorTicksVerticesID == GeometryCache::UNKNOWN_ID) {
            _minorTicksVerticesID = geometryCache->allocateID();
        }
        
        if (geometryChanged) {
            QVector<glm::vec2> majorPoints;
            QVector<glm::vec2> minorPoints;
            
            // draw our major tick marks
            if (getMajorTickMarksAngle() > 0.0f && getMajorTickMarksLength() != 0.0f) {
                
                float tickMarkAngle = getMajorTickMarksAngle();
                float angle = startAt - fmodf(startAt, tickMarkAngle) + tickMarkAngle;
                float angleInRadians = glm::radians(angle);
                float tickMarkLength = getMajorTickMarksLength();
                float startRadius = (tickMarkLength > 0.0f) ? innerRadius : outerRadius;
                float endRadius = startRadius + tickMarkLength;
                
                while (angle <= endAt) {
                    angleInRadians = glm::radians(angle);
                    
                    glm::vec2 thisPointA(cosf(angleInRadians) * startRadius, sinf(angleInRadians) * startRadius);
                    glm::vec2 thisPointB(cosf(angleInRadians) * endRadius, sinf(angleInRadians) * endRadius);
                    
                    majorPoints << thisPointA << thisPointB;
                    
                    angle += tickMarkAngle;
                }
            }
            
            // draw our minor tick marks
            if (getMinorTickMarksAngle() > 0.0f && getMinorTickMarksLength() != 0.0f) {
                
                float tickMarkAngle = getMinorTickMarksAngle();
                float angle = startAt - fmodf(startAt, tickMarkAngle) + tickMarkAngle;
                float angleInRadians = glm::radians(angle);
                float tickMarkLength = getMinorTickMarksLength();
                float startRadius = (tickMarkLength > 0.0f) ? innerRadius : outerRadius;
                float endRadius = startRadius + tickMarkLength;
                
                while (angle <= endAt) {
                    angleInRadians = glm::radians(angle);
                    
                    glm::vec2 thisPointA(cosf(angleInRadians) * startRadius, sinf(angleInRadians) * startRadius);
                    glm::vec2 thisPointB(cosf(angleInRadians) * endRadius, sinf(angleInRadians) * endRadius);
                    
                    minorPoints << thisPointA << thisPointB;
                    
                    angle += tickMarkAngle;
                }
            }
            
            xColor majorColorX = getMajorTickMarksColor();
            glm::vec4 majorColor(majorColorX.red / MAX_COLOR, majorColorX.green / MAX_COLOR, majorColorX.blue / MAX_COLOR, alpha);
            
            geometryCache->updateVertices(_majorTicksVerticesID, majorPoints, majorColor);
            
            xColor minorColorX = getMinorTickMarksColor();
            glm::vec4 minorColor(minorColorX.red / MAX_COLOR, minorColorX.green / MAX_COLOR, minorColorX.blue / MAX_COLOR, alpha);
            
            geometryCache->updateVertices(_minorTicksVerticesID, minorPoints, minorColor);
        }
        
        geometryCache->renderVertices(batch, gpu::LINES, _majorTicksVerticesID);
        
        geometryCache->renderVertices(batch, gpu::LINES, _minorTicksVerticesID);
    }
    
    if (geometryChanged) {
        _lastStartAt = startAt;
        _lastEndAt = endAt;
        _lastInnerRadius = innerRadius;
        _lastOuterRadius = outerRadius;
    }
}
コード例 #3
0
void urgTimelapse::run(float speed, float periodSize, bool bClockwise, float alignmentAngle, float startPeriod) {
    
    // exit function if frame number is -1
    if (frameNum == -1) return;
    
    // reset frame (MUST DO THIS)
    renderedFrame.clear();
    
    // ------------------------------------
    // ------------ FILL FRAME ------------
    // ------------------------------------
    
    // reset counter
    int scanNum = 0;
    
    // add scans to the mesh as dictated by the frames
    ofBuffer::Line it = buffer.getLines().begin();
    advance(it, frames[frameNum].start);
    ofBuffer::Line end = buffer.getLines().end();
    for (it, end; it != end; ++it) {
        
        // get line
        string line = *it;
        vector<string> values = ofSplitString(line, ",");
        
        // put all the points in a scan in the mesh
        for (int i = minIndex; i < maxIndex; i++) {
            
            // find the x and y coordinates
            float px = ofToFloat(values[2 * i + 1]);
            float py = ofToFloat(values[2 * i + 2]);
            
            // find the vector to this point
            ofVec3f thisPoint(px, py, 0.);
            
            // remove points too close
            double sqDist = thisPoint.distanceSquared(ofVec3f(0.,0.,0.));
            if (sqDist < minSqDist2Cam) continue;
            
            // rotate this point 90 degrees about the z axis to orient it upwards
            thisPoint.rotate(90., ofVec3f(0., 0., 1.));
            
            // apply the alignment angle stretch or compression to realign the two chuncks
            float alignmentFactor = (float)i / 682. * alignmentAngle;
            thisPoint.rotate(alignmentFactor, ofVec3f(0., 0., 1.));
            
            // rotate this point about the y axis an amount proportional to this scanNumber and the number of scans in this frame (since this changes)
            float rotationAmt = (float)scanNum / (float)frames[frameNum].length * periodSize;
            
            // if clockwise is true, rotate in negative direction
            if (bClockwise) rotationAmt *= -1.;
            // if period is 180 and frame is odd, rotate 180 degrees
            if ((int)periodSize == 180 && (frameNum % 2)) rotationAmt += 180.;
            thisPoint.rotate(rotationAmt, ofVec3f(0., 1., 0.));
            
            // add the point to the mesh with a color
            renderedFrame.addVertex(thisPoint);
            renderedFrame.addColor(ofFloatColor(1.));
        }
        
        scanNum++;
        if (scanNum >= frames[frameNum].length) break;
    }
    
    cout << "rendered frame # " << frameNum << endl;
    
    // increment the frame number
    frameNum++;
    if (frameNum >= frames.size()) {
        // stop running this operation
        frameNum = -1;
    }
    
    
    // NOW RENDER
    ofPushMatrix();
    
    // rotate the original frame
    ofRotate(startRotateX, 1, 0, 0);
    ofRotate(startRotateY, 0, 1, 0);
    ofRotate(startRotateZ, 0, 0, 1);
    
    renderedFrame.drawVertices();
    
    ofPopMatrix();
    
    // SAVE IMAGE
    ofSaveFrame();
    
}
コード例 #4
0
// fill mesh with the first capture
// scans are spaced out according to the speed of the rotations (degrees/sec; default = 225/64) and the timestamp of each step
// each period is 180 degrees since we're recording both sides of the lidar every scan
void urgTimelapse::fillFirstFrame(float speed, float periodSize, bool bClockwise, float alignmentAngle, float startPeriod) {
    
    // clear mesh for good measure
    firstFrame.clear();
    
    // ------------------------------------
    // ------- FIND SCANS IN FRAME --------
    // ------------------------------------
    
    // holds first time (in seconds)
    float timeZero;
    
    // interval of interest of the scans
    long frameStart = -1;
    long frameLength = -1;
    
    // find max interval within which to search one period
    float overfillAmt = 1.25;
    long maxSearchInterval = long(periodSize * 1/speed * 10. * overfillAmt); // overfillAmt times ideal number of scans in one frame
    
    // start and stop times to search for
    float startTime = startPeriod * periodSize / speed * 1000.;
    float stopTime = (startPeriod * periodSize + periodSize) / speed * 1000.;
    
    // For the first frame, find the start and stop scans
    // Note: last line may be empty
    long thisScanNumber = 0;
    for (ofBuffer::Line it = buffer.getLines().begin(), end = buffer.getLines().end(); it != end; ++it) {
        
        // get the first number (time) in this line
        string line = *it;
        if (line.empty()) {
            cout << "Skipping empty line" << endl;
            // increment counter here?
            continue;
        }
        line.resize((int)line.find_first_of(','));
        float timeNow = ofToFloat(line); // in milliseconds
//        cout << timeNow << endl;
        
        // check if this scan is the start of the frame so long as it has not yet been found
        if (frameStart == -1) {
            if (timeNow >= startTime) {
                frameStart = thisScanNumber;
                timeZero = timeNow / 1000.;
            }
        }
        
        // check if it's the end of the interval
        if (frameStart != -1) {
            if (timeNow >= stopTime) {
                frameLength = thisScanNumber - frameStart;
                break;
            }
        }
        
        // increment the counter
        thisScanNumber++;
        if (thisScanNumber > frameStart + maxSearchInterval) {
            cout << "Couldn't find end of first frame. Try increasing search interval." << endl;
            break;
        }
    }
    
    // ------------------------------------
    // --------- FILL FIRST FRAME ---------
    // ------------------------------------
    
    // reset counter
    thisScanNumber = 0;
    
    // add all scans to the mesh
    ofBuffer::Line it = buffer.getLines().begin();
    advance(it, frameStart);
    ofBuffer::Line end = buffer.getLines().begin();
    advance(end, frameStart + frameLength);
    for (it; it != end; ++it) {
        
        // get this line and split up the measurements
        string line = *it;
        if (line.empty()) {
            cout << "Skipping empty line" << endl;
            continue;
        }
        vector<string> values = ofSplitString(line, ",");
        
        // get timeNow
        float timeNow = ofToFloat(values[0]) / 1000. - timeZero; // in seconds
        
        // put all the points in a scan in the mesh
        for (int i = minIndex; i < maxIndex; i++) {
            
            // find the x and y coordinates
            float px = ofToFloat(values[2 * i + 1]);
            float py = ofToFloat(values[2 * i + 2]);
            
            // find the vector to this point
            ofVec3f thisPoint(px, py, 0.);
            
            // remove points too close
            double sqDist = thisPoint.distanceSquared(ofVec3f(0.,0.,0.));
            if (sqDist < minSqDist2Cam) continue;
            
            // rotate this point 90 degrees about the z axis to orient it upwards
            thisPoint.rotate(90., ofVec3f(0., 0., 1.));
            
            // apply the alignment angle stretch or compression to realign the two chuncks
            float alignmentFactor = (float)i / 682. * alignmentAngle;
            thisPoint.rotate(alignmentFactor, ofVec3f(0., 0., 1.));
            
            // rotate this point about the y axis an amount proportional to this scanNumber and the number of scans in this frame (since this changes)
            float rotationAmt = (float)thisScanNumber / (float)frameLength * periodSize;
//            cout << rotationAmt << endl;

            // if clockwise is true, rotate in negative direction
            if (bClockwise) rotationAmt *= -1.;
            thisPoint.rotate(rotationAmt, ofVec3f(0., 1., 0.));
            
            // add the point to the mesh with a color
            firstFrame.addVertex(thisPoint);
            firstFrame.addColor(ofFloatColor(1.));
        }
        
        thisScanNumber++;
    }
}
コード例 #5
0
// fill mesh with a spherical capture
// scans are spaced out according to the speed of the rotations (degrees/sec; default = 225/64) and the timestamp of each step
// each period is 180 degrees since we're recording both sides of the lidar every scan
void urgDisplay::fillPointMeshTXYSpherical(float speed, float period, bool bClockwise, float startingPeriod, float numPeriods, float alignmentAngle) {
    
    // clear the mesh
    pointMesh.clear();
    
    // if either variable is -1, set it to default or max
    if (startingPeriod == -1.) startingPeriod = 0;
    if (numPeriods == -1.) numPeriods = 99999.;
    
    // ------------------------------------------
    // ------- FIND INTERVAL OF INTEREST --------
    // ------------------------------------------
    
    // set time zero
    float timeZero;
    
    // interval of interest of the scans
    int startIndex = -1;
    int endIndex = -1;
    
    // first, find the starting points and ending points for the sphere
    for (int i = 0; i < nScans; i++) {
        
        // find the current time
        float timeNow = csv.getFloat(i, 0) / 1000.; // in seconds
        
        // check if this scan is the start of the interval of interest so long as it has not yet been found
        if (startIndex == -1) {
            if ((timeNow * speed) >= (startingPeriod * period)) {
                startIndex = i;
                timeZero = timeNow;
            }
        }
        
        // check if it's the end of the interval
        if (startIndex != -1) {
            if ((timeNow * speed) >= ((startingPeriod + numPeriods) * period)) {
                endIndex = i;
                break;
            }
        }
    }
    
    // if endIndex wasn't assigned, assign it to the total number of scans
    if (endIndex == -1) endIndex = nScans;
    
    // ------------------------------------------
    // ---------- FILL THE POINT MESH -----------
    // ------------------------------------------
    
    // for every scan within the interval, add it to the mesh
    for (int i = startIndex; i < endIndex; i++) {
        
        // get the current time
        float timeNow = csv.getFloat(i, 0) / 1000. - timeZero;
        
        // put all the points in a scan in the mesh
        for (int j = minIndex; j < maxIndex; j++) { // NOTE: I've been doing this wrong (i.e. wrong order of operations... this is why there are so many points at zero, zero)... it's right here now
            
            // find the x and y coordinates
            float px = csv.getFloat(i, 2 * j + 1);
            float py = csv.getFloat(i, 2 * j + 2);
            
            // find the vector to this point
            ofVec3f thisPoint(px, py, 0.);
            
            
            
            // remove points too close
            double sqDist = thisPoint.distanceSquared(ofVec3f(0.,0.,0.));
            
//            cout << sqDist << endl;

            if (sqDist < minSqDist2Cam) continue;

            
//            if (px < 100. && py < 100.) continue;
            
            // rotate this point 90 degrees about the z axis to orient it upwards
            thisPoint.rotate(90., ofVec3f(0., 0., 1.));
            
            // apply the alignment angle stretch or compression to realign the two chuncks
            float alignmentFactor = (float)j / 682. * alignmentAngle;
            thisPoint.rotate(alignmentFactor, ofVec3f(0., 0., 1.));
            
            // rotate the point about the y axis an amount proportional to the elapsed time and the speed
            float rotationAmt = timeNow * speed;
            // if clockwise is true, rotate in negative direction
            if (bClockwise) rotationAmt *= -1.;
            thisPoint.rotate(rotationAmt, ofVec3f(0., 1., 0.));
            
            // add the point to the mesh with a color
            pointMesh.addVertex(thisPoint);
            pointMesh.addColor(ofFloatColor(1.));
        }
    }
}
コード例 #6
0
void Circle3DOverlay::render(RenderArgs* args) {
    if (!_visible) {
        return; // do nothing if we're not visible
    }

    float alpha = getAlpha();
    if (alpha == 0.0f) {
        return; // do nothing if our alpha is 0, we're not visible
    }

    bool geometryChanged = _dirty;
    _dirty = false;

    const float FULL_CIRCLE = 360.0f;
    const float SLICES = 180.0f;  // The amount of segment to create the circle
    const float SLICE_ANGLE = FULL_CIRCLE / SLICES;
    const float MAX_COLOR = 255.0f;

    auto geometryCache = DependencyManager::get<GeometryCache>();

    Q_ASSERT(args->_batch);
    auto& batch = *args->_batch;
    if (args->_pipeline) {
        batch.setPipeline(args->_pipeline->pipeline);
    }

    // FIXME: THe line width of _lineWidth is not supported anymore, we ll need a workaround

    auto transform = getTransform();
    transform.postScale(glm::vec3(getDimensions(), 1.0f));
    batch.setModelTransform(transform);

    // for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise
    // we just draw a line...
    if (getIsSolid()) {
        if (!_quadVerticesID) {
            _quadVerticesID = geometryCache->allocateID();
        }

        if (geometryChanged) {
            QVector<glm::vec2> points;
            QVector<glm::vec4> colors;

            float pulseLevel = updatePulse();
            vec4 pulseModifier = vec4(1);
            if (_alphaPulse != 0.0f) {
                pulseModifier.a = (_alphaPulse >= 0.0f) ? pulseLevel : (1.0f - pulseLevel);
            }
            if (_colorPulse != 0.0f) {
                float pulseValue = (_colorPulse >= 0.0f) ? pulseLevel : (1.0f - pulseLevel);
                pulseModifier = vec4(vec3(pulseValue), pulseModifier.a);
            }
            vec4 innerStartColor = vec4(toGlm(_innerStartColor), _innerStartAlpha) * pulseModifier;
            vec4 outerStartColor = vec4(toGlm(_outerStartColor), _outerStartAlpha) * pulseModifier;
            vec4 innerEndColor = vec4(toGlm(_innerEndColor), _innerEndAlpha) * pulseModifier;
            vec4 outerEndColor = vec4(toGlm(_outerEndColor), _outerEndAlpha) * pulseModifier;

            if (_innerRadius <= 0) {
                _solidPrimitive = gpu::TRIANGLE_FAN;
                points << vec2();
                colors << innerStartColor;
                for (float angle = _startAt; angle <= _endAt; angle += SLICE_ANGLE) {
                    float range = (angle - _startAt) / (_endAt - _startAt);
                    float angleRadians = glm::radians(angle);
                    points << glm::vec2(cosf(angleRadians) * _outerRadius, sinf(angleRadians) * _outerRadius);
                    colors << glm::mix(outerStartColor, outerEndColor, range);
                }
            } else {
                _solidPrimitive = gpu::TRIANGLE_STRIP;
                for (float angle = _startAt; angle <= _endAt; angle += SLICE_ANGLE) {
                    float range = (angle - _startAt) / (_endAt - _startAt);

                    float angleRadians = glm::radians(angle);
                    points << glm::vec2(cosf(angleRadians) * _innerRadius, sinf(angleRadians) * _innerRadius);
                    colors << glm::mix(innerStartColor, innerEndColor, range);

                    points << glm::vec2(cosf(angleRadians) * _outerRadius, sinf(angleRadians) * _outerRadius);
                    colors << glm::mix(outerStartColor, outerEndColor, range);
                }
            }
            geometryCache->updateVertices(_quadVerticesID, points, colors);
        }
        
        geometryCache->renderVertices(batch, _solidPrimitive, _quadVerticesID);
        
    } else {
        if (!_lineVerticesID) {
            _lineVerticesID = geometryCache->allocateID();
        }
        
        if (geometryChanged) {
            QVector<glm::vec2> points;
            
            float angle = _startAt;
            float angleInRadians = glm::radians(angle);
            glm::vec2 firstPoint(cosf(angleInRadians) * _outerRadius, sinf(angleInRadians) * _outerRadius);
            points << firstPoint;
            
            while (angle < _endAt) {
                angle += SLICE_ANGLE;
                angleInRadians = glm::radians(angle);
                glm::vec2 thisPoint(cosf(angleInRadians) * _outerRadius, sinf(angleInRadians) * _outerRadius);
                points << thisPoint;
                
                if (getIsDashedLine()) {
                    angle += SLICE_ANGLE / 2.0f; // short gap
                    angleInRadians = glm::radians(angle);
                    glm::vec2 dashStartPoint(cosf(angleInRadians) * _outerRadius, sinf(angleInRadians) * _outerRadius);
                    points << dashStartPoint;
                }
            }
            
            // get the last slice portion....
            angle = _endAt;
            angleInRadians = glm::radians(angle);
            glm::vec2 lastPoint(cosf(angleInRadians) * _outerRadius, sinf(angleInRadians) * _outerRadius);
            points << lastPoint;
            geometryCache->updateVertices(_lineVerticesID, points, vec4(toGlm(getColor()), getAlpha()));
        }
        
        if (getIsDashedLine()) {
            geometryCache->renderVertices(batch, gpu::LINES, _lineVerticesID);
        } else {
            geometryCache->renderVertices(batch, gpu::LINE_STRIP, _lineVerticesID);
        }
    }
    
    // draw our tick marks
    // for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise
    // we just draw a line...
    if (getHasTickMarks()) {
        
        if (_majorTicksVerticesID == GeometryCache::UNKNOWN_ID) {
            _majorTicksVerticesID = geometryCache->allocateID();
        }
        if (_minorTicksVerticesID == GeometryCache::UNKNOWN_ID) {
            _minorTicksVerticesID = geometryCache->allocateID();
        }
        
        if (geometryChanged) {
            QVector<glm::vec2> majorPoints;
            QVector<glm::vec2> minorPoints;
            
            // draw our major tick marks
            if (getMajorTickMarksAngle() > 0.0f && getMajorTickMarksLength() != 0.0f) {
                
                float tickMarkAngle = getMajorTickMarksAngle();
                float angle = _startAt - fmodf(_startAt, tickMarkAngle) + tickMarkAngle;
                float angleInRadians = glm::radians(angle);
                float tickMarkLength = getMajorTickMarksLength();
                float startRadius = (tickMarkLength > 0.0f) ? _innerRadius : _outerRadius;
                float endRadius = startRadius + tickMarkLength;
                
                while (angle <= _endAt) {
                    angleInRadians = glm::radians(angle);
                    
                    glm::vec2 thisPointA(cosf(angleInRadians) * startRadius, sinf(angleInRadians) * startRadius);
                    glm::vec2 thisPointB(cosf(angleInRadians) * endRadius, sinf(angleInRadians) * endRadius);
                    
                    majorPoints << thisPointA << thisPointB;
                    
                    angle += tickMarkAngle;
                }
            }
            
            // draw our minor tick marks
            if (getMinorTickMarksAngle() > 0.0f && getMinorTickMarksLength() != 0.0f) {
                
                float tickMarkAngle = getMinorTickMarksAngle();
                float angle = _startAt - fmodf(_startAt, tickMarkAngle) + tickMarkAngle;
                float angleInRadians = glm::radians(angle);
                float tickMarkLength = getMinorTickMarksLength();
                float startRadius = (tickMarkLength > 0.0f) ? _innerRadius : _outerRadius;
                float endRadius = startRadius + tickMarkLength;
                
                while (angle <= _endAt) {
                    angleInRadians = glm::radians(angle);
                    
                    glm::vec2 thisPointA(cosf(angleInRadians) * startRadius, sinf(angleInRadians) * startRadius);
                    glm::vec2 thisPointB(cosf(angleInRadians) * endRadius, sinf(angleInRadians) * endRadius);
                    
                    minorPoints << thisPointA << thisPointB;
                    
                    angle += tickMarkAngle;
                }
            }
            
            xColor majorColorX = getMajorTickMarksColor();
            glm::vec4 majorColor(majorColorX.red / MAX_COLOR, majorColorX.green / MAX_COLOR, majorColorX.blue / MAX_COLOR, alpha);
            
            geometryCache->updateVertices(_majorTicksVerticesID, majorPoints, majorColor);
            
            xColor minorColorX = getMinorTickMarksColor();
            glm::vec4 minorColor(minorColorX.red / MAX_COLOR, minorColorX.green / MAX_COLOR, minorColorX.blue / MAX_COLOR, alpha);
            
            geometryCache->updateVertices(_minorTicksVerticesID, minorPoints, minorColor);
        }
        
        geometryCache->renderVertices(batch, gpu::LINES, _majorTicksVerticesID);
        
        geometryCache->renderVertices(batch, gpu::LINES, _minorTicksVerticesID);
    }
}
コード例 #7
0
int PointPrototype::y() const
{
    return thisPoint()->y();
}
コード例 #8
0
void PointPrototype::setY(int y)
{
    thisPoint()->setY(y);
}
コード例 #9
0
void PointPrototype::setX(int x)
{
    thisPoint()->setX(x);
}
コード例 #10
0
int PointPrototype::x() const
{
    return thisPoint()->x();
}
コード例 #11
0
ファイル: conversion.cpp プロジェクト: ArtemusRus/warzone2100
int QWzmViewer::savePIE(const char *filename, const MODEL *psModel, int pieVersion, int type)
{
	std::fstream file;
	int i, j, k;

	/* variable ptOffset: Temporary storage of calculated index
	 *		for a give face OR vertex in the WZM vertex array.
	 */
	/* variable ptSetIndex: Index of a vertex in the set
	 *		of PIE points for a given PIE level.
	 */
	// variable polyFlag: Use to compose the flag for a PIE polygon
	unsigned int ptOffset, ptSetIndex, polyFlag;

	/* Temporary stringstream used to accomodate
	 * the order PIE polygon data is written
	 */
	std::stringstream animTmpSs;

	MESH *mesh;

	/* variable unitW: Width of the bounding box for
	 *		a single tex. anim. "frame" of a polygon.
	 * variable unitH: Same as unitW except represents
	 *		the height.
	 */
	/* variable t: represents the top of the bounding box
	 *		when estimating the tex. anim.'s
	 *		height.
	 * variable b: Same as t except represents the
	 *		bottom.
	 */
	double unitW, unitH, t, b;

	/* variable ptSet: for creating a unique set
	 *		of PIE points for a given PIE level.
	 */
	std::set< pie_Point> ptSet;

	/* variable textures: Temporary storage of
	 *		texture coordinates to avoid redundant
	 *		ptOffset calculations.
	 */
	std::queue< textCoords, std::list<textCoords> > textures;

	file.open(filename, std::fstream::out);

	if (!file.is_open())
	{
		qWarning("QWzmViewer::savePIE - Failed to open file.");
		return -1;
	}

	file << "PIE " << pieVersion << '\n';
	file << "TYPE " << std::hex << type << std::dec << "\n";

	// Texture directive:
	file << "TEXTURE 0 " << psModel->texPath;
	switch (pieVersion)
	{
	case 2:
		if (psModel->pixmap != NULL)
		{
			file << ' ' << psModel->pixmap->h << ' ' << psModel->pixmap->w << '\n';
		}
		else
		{
			file << " 256 256\n";
		}
		break;
	case 3:
		file << " 0 0\n";
		break;
	default:
		file.close();
		qWarning("QWzmViewer::savePIE - Unsupported pie version");
		return -1;
	}

	// LEVELS directive
	file << "LEVELS " << psModel->meshes << '\n';

	// For each WZM mesh a PIE level.
	for (i = 0; i < psModel->meshes; i++)
	{
		ptSet.clear();
		mesh = &(psModel->mesh[i]);

		// LEVEL directive
		file << "LEVEL " << i + 1 << "\n";

		// Create the set of unique points.
		for (j = 0; j < mesh->vertices; j++)
		{
			ptSet.insert(pie_Point(mesh->vertexArray[j*VERTICES_PER_TRIANGLE],
								   mesh->vertexArray[j*VERTICES_PER_TRIANGLE+1],
								   mesh->vertexArray[j*VERTICES_PER_TRIANGLE+2]));
		}

		if (ptSet.size() > pie_MAX_POLYGONS)
		{
			file.close();
			qWarning("QWzmViewer::savePIE - Model has too many vertices to save as PIE.");
			return -1;
		}

		// POINTS directive
		file << "POINTS " << ptSet.size() << '\n';

		// print out all the points in the set
		std::set< pie_Point>::iterator it;
		for (it = ptSet.begin(); it != ptSet.end(); it++)
		{
			GLfloat x, y, z;
			it->getXYZ(x, y, z);
			switch (pieVersion)
			{
			case 2:
				file << '\t' << (int)rintf(x) << ' ' << (int)rintf(y) << ' ' << (int)rintf(z) << '\n';
				break;
			case 3:
				file << '\t' << x << ' ' << y << ' ' << z << '\n';
				break;
			}
		}

		// POLYGONS directive
		file << "POLYGONS " << mesh->faces << '\n';

		for (j = 0; j < mesh->faces; j++)
		{
			polyFlag = iV_IMD_TEX; // Default flag
			animTmpSs.str(std::string());

			if (mesh->textureArrays > 1)
			{
				ptOffset = mesh->indexArray[j*VERTICES_PER_TRIANGLE];

				/*
				 * TODO:
				 * This _if_ statement isn't a robust way of checking
				 * for animations or team colours.
				 */
				if ((mesh->textureArray[0][ptOffset*2] < mesh->textureArray[1][ptOffset*2])
					|| (mesh->textureArray[0][ptOffset*2+1] < mesh->textureArray[mesh->textureArrays-1][ptOffset*2+1]))
				{
					/* Find height and width for team colours
					 * and animations.
					 * TODO: Check that the animations are legal
					 * for the PIE format.
					 */
					unitH = 0;

					// Try to find width the easy way
					unitW = mesh->textureArray[1][ptOffset*2] - mesh->textureArray[0][ptOffset*2];

					// Try to find height the easy way
					for (k = 0; k < mesh->textureArrays - 1; k++)
					{
						// Look for wrap around
						if (mesh->textureArray[k+1][ptOffset*2+1] > mesh->textureArray[k][ptOffset*2+1])
						{
							unitH = mesh->textureArray[k+1][ptOffset*2+1] - mesh->textureArray[k][ptOffset*2+1];
							break;
						}
					}

					// If the easy way failed
					if ( unitH <= 0)
					{
						// Find top and bottom, add pixels to the difference for good luck.
						b = 0; // Search for the bottom starting from the top
						t = 1; // Search for the top starting from the bottom

						// Try every V to find the min and max
						for (k = 0; k < VERTICES_PER_TRIANGLE; k++)
						{
							ptOffset = mesh->indexArray[j*VERTICES_PER_TRIANGLE+k];
							if (mesh->textureArray[0][ptOffset*2+1] < t)
							{
								t = mesh->textureArray[0][ptOffset*2+1];
							}
							if (mesh->textureArray[0][ptOffset*2+1] > b)
							{
								b = mesh->textureArray[0][ptOffset*2+1];
							}
						}

						unitH = fabs(b - t);

						if (psModel->pixmap != NULL && psModel->pixmap->h != 0)
						{
							unitH += 2 / psModel->pixmap->h;
						}
						else if (pieVersion == 2)
						{
							unitH += 2 / OLD_TEXTURE_SIZE_FIX;
						}
					}

					/* If the animations wraps around for each frame
					 * then the easy way of finding width would fail.
					 */
					if (unitW <= 0 && unitH ==0)
					{
						qWarning("QWzmViewer::savePIE - Texture animation appears to be illegal for PIE format.");
						file.close();
						return -1;
					}
					else if ( unitW <=0)
					{
						unitW = 1;
					}

					switch (pieVersion)
					{
						// TODO: Get playback rate and replace the literal " 1 " with it.
					case 2:
						animTmpSs << mesh->textureArrays << " 1 " << (int)rintf(OLD_TEXTURE_SIZE_FIX*unitW)
								<< ' ' << (int)rintf(OLD_TEXTURE_SIZE_FIX*unitH);
						break;
					case 3:
						animTmpSs << mesh->textureArrays << " 1 " << (GLfloat)unitW << ' ' << (GLfloat)unitH;
						break;
					}
					polyFlag |= iV_IMD_TEXANIM;
				}
			}

			// Write out the flag followed by the number of vertices
			file << "\t" << std::hex << polyFlag << std::dec << ' ' << VERTICES_PER_TRIANGLE; // Triangles only

			// Write the three polygon indices
			for (k = 0; k < VERTICES_PER_TRIANGLE; k++)
			{
				ptOffset = mesh->indexArray[j*VERTICES_PER_TRIANGLE+k];

				pie_Point thisPoint(mesh->vertexArray[ptOffset*VERTICES_PER_TRIANGLE],
									mesh->vertexArray[ptOffset*VERTICES_PER_TRIANGLE+1],
									mesh->vertexArray[ptOffset*VERTICES_PER_TRIANGLE+2]);

				ptSetIndex = distance(ptSet.begin(), ptSet.find(thisPoint));

				if (ptSetIndex == ptSet.size())
				{
					file.close();
					qWarning("QWzmViewer::savePIE - Internal error: Failed to find vertex in set.");
					return -1;
				}
				else
				{
					file << ' ' << ptSetIndex;

					// Store the texture coordinates for later
					textures.push(textCoords(mesh->textureArray[0][ptOffset*2],
											 mesh->textureArray[0][ptOffset*2+1]));
				}
			}

			// If the polygon has team colours or animations, write that data now
			if (polyFlag & iV_IMD_TEXANIM)
			{
				file << ' ' << animTmpSs.str();
			}

			// Write out all the texture coordinates
			while (!textures.empty())
			{
				switch (pieVersion)
				{
				case 2:
					file << ' ' << (int)rintf(OLD_TEXTURE_SIZE_FIX*textures.front().u);
					file << ' ' << (int)rintf(OLD_TEXTURE_SIZE_FIX*textures.front().v);
					break;
				case 3:
					file << ' ' << textures.front().u << ' ' << textures.front().v;
					break;
				}
				textures.pop();
			}
			file << '\n';
		}

		// In PIE the CONNECTORS directive is optional
		if (mesh->connectors > 0)
		{
			// CONNECTORS directive
			file << "CONNECTORS " << mesh->connectors << "\n";

			for (j = 0; j < mesh->connectors; j++)
			{
				switch (pieVersion)
				{
				case 2:
					file << "\t" << (int)rintf(mesh->connectorArray[j].pos.x)
							<< ' ' << (int)rintf(mesh->connectorArray[j].pos.y)
							<< ' ' << (int)rintf(mesh->connectorArray[j].pos.z) << '\n';
					break;
				case 3:
					file << "\t" << mesh->connectorArray[j].pos.x
							<< ' ' << mesh->connectorArray[j].pos.y
							<< ' ' << mesh->connectorArray[j].pos.z << '\n';
					break;
				}
			}
		}
	}

	if(file.bad())
	{
		file.close();
		return -1;
	}
	file.close();
	return 0;
}
コード例 #12
0
ファイル: Circle3DOverlay.cpp プロジェクト: RyanDowne/hifi
void Circle3DOverlay::render(RenderArgs* args) {
    if (!_visible) {
        return; // do nothing if we're not visible
    }

    float alpha = getAlpha();

    if (alpha == 0.0) {
        return; // do nothing if our alpha is 0, we're not visible
    }
    
    const float FULL_CIRCLE = 360.0f;
    const float SLICES = 180.0f;  // The amount of segment to create the circle
    const float SLICE_ANGLE = FULL_CIRCLE / SLICES;

    //const int slices = 15;
    xColor color = getColor();
    const float MAX_COLOR = 255.0f;
    glColor4f(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha);


    glDisable(GL_LIGHTING);
    
    glm::vec3 position = getPosition();
    glm::vec3 center = getCenter();
    glm::vec2 dimensions = getDimensions();
    glm::quat rotation = getRotation();

    float glowLevel = getGlowLevel();
    Glower* glower = NULL;
    if (glowLevel > 0.0f) {
        glower = new Glower(glowLevel);
    }

    glPushMatrix();
        glTranslatef(position.x, position.y, position.z);
        glm::vec3 axis = glm::axis(rotation);
        glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z);
        glPushMatrix();
            glm::vec3 positionToCenter = center - position;
            glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z);
            glScalef(dimensions.x, dimensions.y, 1.0f);

            // Create the circle in the coordinates origin
            float outerRadius = getOuterRadius(); 
            float innerRadius = getInnerRadius(); // only used in solid case
            float startAt = getStartAt();
            float endAt = getEndAt();

            glLineWidth(_lineWidth);
            
            // for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise
            // we just draw a line...
            if (getIsSolid()) {
                glBegin(GL_QUAD_STRIP);

                float angle = startAt;
                float angleInRadians = glm::radians(angle);
                glm::vec2 firstInnerPoint(cos(angleInRadians) * innerRadius, sin(angleInRadians) * innerRadius);
                glm::vec2 firstOuterPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius);

                glVertex2f(firstInnerPoint.x, firstInnerPoint.y);
                glVertex2f(firstOuterPoint.x, firstOuterPoint.y);

                while (angle < endAt) {
                    angleInRadians = glm::radians(angle);
                    glm::vec2 thisInnerPoint(cos(angleInRadians) * innerRadius, sin(angleInRadians) * innerRadius);
                    glm::vec2 thisOuterPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius);

                    glVertex2f(thisOuterPoint.x, thisOuterPoint.y);
                    glVertex2f(thisInnerPoint.x, thisInnerPoint.y);
                
                    angle += SLICE_ANGLE;
                }
            
                // get the last slice portion....
                angle = endAt;
                angleInRadians = glm::radians(angle);
                glm::vec2 lastInnerPoint(cos(angleInRadians) * innerRadius, sin(angleInRadians) * innerRadius);
                glm::vec2 lastOuterPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius);
            
                glVertex2f(lastOuterPoint.x, lastOuterPoint.y);
                glVertex2f(lastInnerPoint.x, lastInnerPoint.y);

                glEnd();
            } else {
                if (getIsDashedLine()) {
                    glBegin(GL_LINES);
                } else {
                    glBegin(GL_LINE_STRIP);
                }
                

                float angle = startAt;
                float angleInRadians = glm::radians(angle);
                glm::vec2 firstPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius);
                glVertex2f(firstPoint.x, firstPoint.y);

                while (angle < endAt) {
                    angle += SLICE_ANGLE;
                    angleInRadians = glm::radians(angle);
                    glm::vec2 thisPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius);
                    glVertex2f(thisPoint.x, thisPoint.y);

                    if (getIsDashedLine()) {
                        angle += SLICE_ANGLE / 2.0f; // short gap
                        angleInRadians = glm::radians(angle);
                        glm::vec2 dashStartPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius);
                        glVertex2f(dashStartPoint.x, dashStartPoint.y);
                    }
                }
            
                // get the last slice portion....
                angle = endAt;
                angleInRadians = glm::radians(angle);
                glm::vec2 lastOuterPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius);
                glVertex2f(lastOuterPoint.x, lastOuterPoint.y);
                glEnd();
            }
            
            // draw our tick marks
            // for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise
            // we just draw a line...
            if (getHasTickMarks()) {
                glBegin(GL_LINES);

                // draw our major tick marks
                if (getMajorTickMarksAngle() > 0.0f && getMajorTickMarksLength() != 0.0f) {
                
                    xColor color = getMajorTickMarksColor();
                    glColor4f(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha);
                
                    float tickMarkAngle = getMajorTickMarksAngle();
                    float angle = startAt - fmod(startAt, tickMarkAngle) + tickMarkAngle; 
                    float angleInRadians = glm::radians(angle);
                    float tickMarkLength = getMajorTickMarksLength();
                    float startRadius = (tickMarkLength > 0.0f) ? innerRadius : outerRadius;
                    float endRadius = startRadius + tickMarkLength;

                    while (angle <= endAt) {
                        angleInRadians = glm::radians(angle);

                        glm::vec2 thisPointA(cos(angleInRadians) * startRadius, sin(angleInRadians) * startRadius);
                        glm::vec2 thisPointB(cos(angleInRadians) * endRadius, sin(angleInRadians) * endRadius);

                        glVertex2f(thisPointA.x, thisPointA.y);
                        glVertex2f(thisPointB.x, thisPointB.y);
                
                        angle += tickMarkAngle;
                    }
                }

                // draw our minor tick marks
                if (getMinorTickMarksAngle() > 0.0f && getMinorTickMarksLength() != 0.0f) {
                
                    xColor color = getMinorTickMarksColor();
                    glColor4f(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha);
                
                    float tickMarkAngle = getMinorTickMarksAngle();
                    float angle = startAt - fmod(startAt, tickMarkAngle) + tickMarkAngle; 
                    float angleInRadians = glm::radians(angle);
                    float tickMarkLength = getMinorTickMarksLength();
                    float startRadius = (tickMarkLength > 0.0f) ? innerRadius : outerRadius;
                    float endRadius = startRadius + tickMarkLength;

                    while (angle <= endAt) {
                        angleInRadians = glm::radians(angle);

                        glm::vec2 thisPointA(cos(angleInRadians) * startRadius, sin(angleInRadians) * startRadius);
                        glm::vec2 thisPointB(cos(angleInRadians) * endRadius, sin(angleInRadians) * endRadius);

                        glVertex2f(thisPointA.x, thisPointA.y);
                        glVertex2f(thisPointB.x, thisPointB.y);
                
                        angle += tickMarkAngle;
                    }
                }

                glEnd();
            }
            
 
        glPopMatrix();
    glPopMatrix();
    
    if (glower) {
        delete glower;
    }
}
コード例 #13
0
ファイル: Circle3DOverlay.cpp プロジェクト: ey6es/hifi
void Circle3DOverlay::render(RenderArgs* args) {
    if (!_visible) {
        return; // do nothing if we're not visible
    }

    float alpha = getAlpha();

    if (alpha == 0.0) {
        return; // do nothing if our alpha is 0, we're not visible
    }
    
    // Create the circle in the coordinates origin
    float outerRadius = getOuterRadius();
    float innerRadius = getInnerRadius(); // only used in solid case
    float startAt = getStartAt();
    float endAt = getEndAt();
    
    bool geometryChanged = (startAt != _lastStartAt || endAt != _lastEndAt ||
                                innerRadius != _lastInnerRadius || outerRadius != _lastOuterRadius);

    
    const float FULL_CIRCLE = 360.0f;
    const float SLICES = 180.0f;  // The amount of segment to create the circle
    const float SLICE_ANGLE = FULL_CIRCLE / SLICES;

    //const int slices = 15;
    xColor color = getColor();
    const float MAX_COLOR = 255.0f;
    glColor4f(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha);


    glDisable(GL_LIGHTING);
    
    glm::vec3 position = getPosition();
    glm::vec3 center = getCenter();
    glm::vec2 dimensions = getDimensions();
    glm::quat rotation = getRotation();

    float glowLevel = getGlowLevel();
    Glower* glower = NULL;
    if (glowLevel > 0.0f) {
        glower = new Glower(glowLevel);
    }

    glPushMatrix();
        glTranslatef(position.x, position.y, position.z);
        glm::vec3 axis = glm::axis(rotation);
        glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z);
        glPushMatrix();
            glm::vec3 positionToCenter = center - position;
            glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z);
            glScalef(dimensions.x, dimensions.y, 1.0f);

            glLineWidth(_lineWidth);

            auto geometryCache = DependencyManager::get<GeometryCache>();
            
            // for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise
            // we just draw a line...
            if (getIsSolid()) {
                if (_quadVerticesID == GeometryCache::UNKNOWN_ID) {
                    _quadVerticesID = geometryCache->allocateID();
                }
                
                if (geometryChanged) {
                    
                    QVector<glm::vec2> points;

                    float angle = startAt;
                    float angleInRadians = glm::radians(angle);
                    glm::vec2 firstInnerPoint(cos(angleInRadians) * innerRadius, sin(angleInRadians) * innerRadius);
                    glm::vec2 firstOuterPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius);

                    points << firstInnerPoint << firstOuterPoint;

                    while (angle < endAt) {
                        angleInRadians = glm::radians(angle);
                        glm::vec2 thisInnerPoint(cos(angleInRadians) * innerRadius, sin(angleInRadians) * innerRadius);
                        glm::vec2 thisOuterPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius);

                        points << thisOuterPoint << thisInnerPoint;
                
                        angle += SLICE_ANGLE;
                    }
            
                    // get the last slice portion....
                    angle = endAt;
                    angleInRadians = glm::radians(angle);
                    glm::vec2 lastInnerPoint(cos(angleInRadians) * innerRadius, sin(angleInRadians) * innerRadius);
                    glm::vec2 lastOuterPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius);
            
                    points << lastOuterPoint << lastInnerPoint;

                    geometryCache->updateVertices(_quadVerticesID, points);
                }
                
                geometryCache->renderVertices(GL_QUAD_STRIP, _quadVerticesID);

            } else {
                if (_lineVerticesID == GeometryCache::UNKNOWN_ID) {
                    _lineVerticesID = geometryCache->allocateID();
                }

                if (geometryChanged) {
                    QVector<glm::vec2> points;
                    
                    float angle = startAt;
                    float angleInRadians = glm::radians(angle);
                    glm::vec2 firstPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius);
                    points << firstPoint;

                    while (angle < endAt) {
                        angle += SLICE_ANGLE;
                        angleInRadians = glm::radians(angle);
                        glm::vec2 thisPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius);
                        points << thisPoint;

                        if (getIsDashedLine()) {
                            angle += SLICE_ANGLE / 2.0f; // short gap
                            angleInRadians = glm::radians(angle);
                            glm::vec2 dashStartPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius);
                            points << dashStartPoint;
                        }
                    }
            
                    // get the last slice portion....
                    angle = endAt;
                    angleInRadians = glm::radians(angle);
                    glm::vec2 lastPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius);
                    points << lastPoint;

                    geometryCache->updateVertices(_lineVerticesID, points);
                }

                if (getIsDashedLine()) {
                    geometryCache->renderVertices(GL_LINES, _lineVerticesID);
                } else {
                    geometryCache->renderVertices(GL_LINE_STRIP, _lineVerticesID);
                }
            }
            
            // draw our tick marks
            // for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise
            // we just draw a line...
            if (getHasTickMarks()) {

                if (_majorTicksVerticesID == GeometryCache::UNKNOWN_ID) {
                    _majorTicksVerticesID = geometryCache->allocateID();
                }
                if (_minorTicksVerticesID == GeometryCache::UNKNOWN_ID) {
                    _minorTicksVerticesID = geometryCache->allocateID();
                }

                if (geometryChanged) {
                    QVector<glm::vec2> majorPoints;
                    QVector<glm::vec2> minorPoints;

                    // draw our major tick marks
                    if (getMajorTickMarksAngle() > 0.0f && getMajorTickMarksLength() != 0.0f) {
                
                        float tickMarkAngle = getMajorTickMarksAngle();
                        float angle = startAt - fmod(startAt, tickMarkAngle) + tickMarkAngle; 
                        float angleInRadians = glm::radians(angle);
                        float tickMarkLength = getMajorTickMarksLength();
                        float startRadius = (tickMarkLength > 0.0f) ? innerRadius : outerRadius;
                        float endRadius = startRadius + tickMarkLength;

                        while (angle <= endAt) {
                            angleInRadians = glm::radians(angle);

                            glm::vec2 thisPointA(cos(angleInRadians) * startRadius, sin(angleInRadians) * startRadius);
                            glm::vec2 thisPointB(cos(angleInRadians) * endRadius, sin(angleInRadians) * endRadius);

                            majorPoints << thisPointA << thisPointB;
                
                            angle += tickMarkAngle;
                        }
                    }

                    // draw our minor tick marks
                    if (getMinorTickMarksAngle() > 0.0f && getMinorTickMarksLength() != 0.0f) {
                
                        float tickMarkAngle = getMinorTickMarksAngle();
                        float angle = startAt - fmod(startAt, tickMarkAngle) + tickMarkAngle; 
                        float angleInRadians = glm::radians(angle);
                        float tickMarkLength = getMinorTickMarksLength();
                        float startRadius = (tickMarkLength > 0.0f) ? innerRadius : outerRadius;
                        float endRadius = startRadius + tickMarkLength;

                        while (angle <= endAt) {
                            angleInRadians = glm::radians(angle);

                            glm::vec2 thisPointA(cos(angleInRadians) * startRadius, sin(angleInRadians) * startRadius);
                            glm::vec2 thisPointB(cos(angleInRadians) * endRadius, sin(angleInRadians) * endRadius);

                            minorPoints << thisPointA << thisPointB;
                
                            angle += tickMarkAngle;
                        }
                    }

                    geometryCache->updateVertices(_majorTicksVerticesID, majorPoints);
                    geometryCache->updateVertices(_minorTicksVerticesID, minorPoints);
                }

                xColor majorColor = getMajorTickMarksColor();
                glColor4f(majorColor.red / MAX_COLOR, majorColor.green / MAX_COLOR, majorColor.blue / MAX_COLOR, alpha);
                geometryCache->renderVertices(GL_LINES, _majorTicksVerticesID);

                xColor minorColor = getMinorTickMarksColor();
                glColor4f(minorColor.red / MAX_COLOR, minorColor.green / MAX_COLOR, minorColor.blue / MAX_COLOR, alpha);
                geometryCache->renderVertices(GL_LINES, _minorTicksVerticesID);
            }
            
 
        glPopMatrix();
    glPopMatrix();
    
    if (geometryChanged) {
        _lastStartAt = startAt;
        _lastEndAt = endAt;
        _lastInnerRadius = innerRadius;
        _lastOuterRadius = outerRadius;
    }
    
    if (glower) {
        delete glower;
    }
}