Porting to newer OpenCV 'C' interface; cv.h file not found - c
I have a file, included below, that when I compile, I get the error that cv.h file not found. This, I believe, is because I use opencv4 which doesn't support cv.h. I've seen similar posts recommending one to simply downgrade opencv versions, but I don't want to do that.
My question is this:
How do I find what part of the code is dependent on cv.h, so that. I can simply try to update it for opencv4 compatibility?
file:
#ifndef _GUARD_cvl1qc_h_
#define _GUARD_cvl1qc_h_
#include <cv.h>
#include "cvcgsolve.h"
/* taken A, B, X, minimize ||X||_{L1} with constraint: ||AX - B|| < \epsilon */
int cvL1QCSolve( CvMat* A, CvMat* B, CvMat* X, double epsilon, double mu = 10., CvTermCriteria lb_term_crit = cvTermCriteria( CV_TERMCRIT_EPS, 0, 1e-3 ), CvTermCriteria cg_term_crit = cvTermCriteria( CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 200, 1e-16 ) );
/* taken AOps, AtOps, it specially designed for large scale, AOps is for AX, AtOps is for A'X */
int cvL1QCSolve( CvMatOps AOps, CvMatOps AtOps, void* userdata, CvMat* B, CvMat* X, double epsilon, double mu = 10., CvTermCriteria lb_term_crit = cvTermCriteria( CV_TERMCRIT_EPS, 0, 1e-3 ), CvTermCriteria cg_term_crit = cvTermCriteria( CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 200, 1e-16 ) );
static int icvL1QCNewton( CvMat* A, CvMat* B, CvMat* X, CvMat* U, double epsilon, double tau, CvTermCriteria nt_term_crit, CvTermCriteria cg_term_crit )
{
const double alpha = .01;
const double beta = .5;
CvMat* R = cvCreateMat( B->rows, B->cols, CV_MAT_TYPE(B->type) );
cvGEMM( A, X, 1, B, -1, R );
CvMat* fu1 = cvCreateMat( X->rows, X->cols, CV_MAT_TYPE(X->type) );
CvMat* fu2 = cvCreateMat( X->rows, X->cols, CV_MAT_TYPE(X->type) );
CvMat* lfu1 = cvCreateMat( fu1->rows, fu1->cols, CV_MAT_TYPE(fu1->type) );
CvMat* lfu2 = cvCreateMat( fu2->rows, fu2->cols, CV_MAT_TYPE(fu2->type) );
cvSub( U, X, lfu1 );
cvAdd( X, U, lfu2 );
cvSubRS( lfu1, cvScalar(0), fu1 );
cvSubRS( lfu2, cvScalar(0), fu2 );
double epsilon2 = epsilon * epsilon;
double tau_inv = 1. / tau;
double fe = .5 * (cvDotProduct( R, R ) - epsilon2);
double fe_inv = 1. / fe;
cvLog( lfu1, lfu1 );
cvLog( lfu2, lfu2 );
CvScalar sumU = cvSum( U );
CvScalar sumfu1 = cvSum( lfu1 );
CvScalar sumfu2 = cvSum( lfu2 );
double f = sumU.val[0] - tau_inv * (sumfu1.val[0] + sumfu2.val[0] + log(-fe));
CvMat* atr = cvCreateMat( X->rows, X->cols, CV_MAT_TYPE(X->type) );
CvMat* ntgx = cvCreateMat( X->rows, X->cols, CV_MAT_TYPE(X->type) );
CvMat* ntgu = cvCreateMat( X->rows, X->cols, CV_MAT_TYPE(X->type) );
CvMat* sig1211 = cvCreateMat( X->rows, X->cols, CV_MAT_TYPE(X->type) );
CvMat* sigx = cvCreateMat( X->rows, X->cols, CV_MAT_TYPE(X->type) );
CvMat* w1 = cvCreateMat( X->rows, X->cols, CV_MAT_TYPE(X->type) );
CvMat* AtA = cvCreateMat( A->cols, A->cols, CV_MAT_TYPE(A->type) );
CvMat* H11 = cvCreateMat( A->cols, A->cols, CV_MAT_TYPE(A->type) );
CvMat* du = cvCreateMat( X->rows, X->cols, CV_MAT_TYPE(X->type) );
CvMat* pX = cvCreateMat( X->rows, X->cols, CV_MAT_TYPE(X->type) );
CvMat* pU = cvCreateMat( U->rows, U->cols, CV_MAT_TYPE(U->type) );
CvMat* pR = cvCreateMat( R->rows, R->cols, CV_MAT_TYPE(R->type) );
CvMat* pfu1 = cvCreateMat( fu1->rows, fu1->cols, CV_MAT_TYPE(fu1->type) );
CvMat* pfu2 = cvCreateMat( fu2->rows, fu2->cols, CV_MAT_TYPE(fu2->type) );
CvMat* Adx = cvCreateMat( B->rows, B->cols, CV_MAT_TYPE(B->type) );
CvMat* dx = cvCreateMat( X->rows, X->cols, CV_MAT_TYPE(X->type) );
int result = nt_term_crit.max_iter;
int t, i;
for ( t = 0; t < nt_term_crit.max_iter; ++t )
{
cvGEMM( A, R, 1, NULL, 0, atr, CV_GEMM_A_T );
cvGEMM( A, A, 1, NULL, 0, AtA, CV_GEMM_A_T );
cvGEMM( atr, atr, 1, NULL, 0, H11, CV_GEMM_B_T );
double* atrp = atr->data.db;
double* fu1p = fu1->data.db;
double* fu2p = fu2->data.db;
double* ntgxp = ntgx->data.db;
double* ntgup = ntgu->data.db;
double* sig1211p = sig1211->data.db;
double* sigxp = sigx->data.db;
double* w1p = w1->data.db;
double* dup = du->data.db;
for ( i = 0; i < X->rows; ++i, ++atrp, ++fu1p, ++fu2p, ++ntgxp, ++ntgup, ++sig1211p, ++sigxp, ++w1p, ++dup )
{
double fu1_inv = 1. / (*fu1p);
double fu2_inv = 1. / (*fu2p);
double ntgxv = fu1_inv - fu2_inv + fe_inv * (*atrp);
double ntguv = -tau - fu1_inv - fu2_inv;
double sig11 = fu1_inv * fu1_inv + fu2_inv * fu2_inv;
double sig12 = -fu1_inv * fu1_inv + fu2_inv * fu2_inv;
*sig1211p = sig12 / sig11;
*sigxp = sig11 - sig12 * (*sig1211p);
*w1p = ntgxv - (*sig1211p) * ntguv;
*ntgxp = -tau_inv * ntgxv;
*ntgup = -tau_inv * ntguv;
*dup = ntguv / sig11;
}
cvAddWeighted( AtA, -fe_inv, H11, -fe_inv * fe_inv, 0, H11 );
sigxp = sigx->data.db;
double* H11p = H11->data.db;
for ( i = 0; i < A->cols; ++i, ++sigxp, H11p += A->cols + 1 )
*H11p += *sigxp;
if ( cvCGSolve( H11, w1, dx, cg_term_crit ) > .5 )
{
result = t;
goto __clean_up__;
}
cvMatMul( A, dx, Adx );
dup = du->data.db;
sig1211p = sig1211->data.db;
double* dxp = dx->data.db;
for ( i = 0; i < X->rows; ++i, ++dup, ++sig1211p, ++dxp )
*dup -= (*sig1211p) * (*dxp);
/* minimum step size that stays in the interior */
double aqe = cvDotProduct( Adx, Adx );
double bqe = 2. * cvDotProduct( R, Adx );
double cqe = cvDotProduct( R, R ) - epsilon2;
double smax = MIN( 1, -bqe + sqrt( bqe * bqe - 4 * aqe * cqe ) / (2 * aqe) );
dup = du->data.db;
dxp = dx->data.db;
fu1p = fu1->data.db;
fu2p = fu2->data.db;
for ( i = 0; i < X->rows; ++i, ++dup, ++dxp, ++fu1p, ++fu2p )
{
if ( (*dxp) - (*dup) > 0 )
smax = MIN( smax, -(*fu1p) / ((*dxp) - (*dup)) );
if ( (*dxp) + (*dup) < 0 )
smax = MIN( smax, (*fu2p) / ((*dxp) + (*dup)) );
}
smax *= .99;
/* backtracking line search */
bool suffdec = 0;
int backiter = 0;
double fep = fe;
double fp = f;
double lambda2;
while (!suffdec)
{
cvAddWeighted( X, 1, dx, smax, 0, pX );
cvAddWeighted( U, 1, du, smax, 0, pU );
cvAddWeighted( R, 1, Adx, smax, 0, pR );
cvSub( pU, pX, lfu1 );
cvAdd( pX, pU, lfu2 );
cvSubRS( lfu1, cvScalar(0), pfu1 );
cvSubRS( lfu2, cvScalar(0), pfu2 );
fep = .5 * (cvDotProduct( pR, pR ) - epsilon2);
cvLog( lfu1, lfu1 );
cvLog( lfu2, lfu2 );
CvScalar sumpU = cvSum( pU );
CvScalar sumpfu1 = cvSum( pfu1 );
CvScalar sumpfu2 = cvSum( pfu2 );
fp = sumpU.val[0] - tau_inv * (sumpfu1.val[0] + sumpfu2.val[0] + log(-fep));
lambda2 = cvDotProduct( ntgx, dx ) + cvDotProduct( ntgu, du );
double flin = f + alpha * smax * lambda2;
suffdec = (fp <= flin);
smax = beta * smax;
++backiter;
if ( backiter > 32 )
{
result = t;
goto __clean_up__;
}
}
/* set up for next iteration */
cvCopy( pX, X );
cvCopy( pU, U );
cvCopy( pR, R );
cvCopy( pfu1, fu1 );
cvCopy( pfu2, fu2 );
fe = fep;
fe_inv = 1. / fe;
f = fp;
lambda2 = -lambda2 * .5;
if ( lambda2 < nt_term_crit.epsilon )
{
result = t + 1;
break;
}
}
__clean_up__:
cvReleaseMat( &pfu2 );
cvReleaseMat( &pfu1 );
cvReleaseMat( &pR );
cvReleaseMat( &pU );
cvReleaseMat( &pX );
cvReleaseMat( &dx );
cvReleaseMat( &Adx );
cvReleaseMat( &du );
cvReleaseMat( &H11 );
cvReleaseMat( &AtA );
cvReleaseMat( &w1 );
cvReleaseMat( &sigx );
cvReleaseMat( &sig1211 );
cvReleaseMat( &ntgu );
cvReleaseMat( &ntgx );
cvReleaseMat( &lfu2 );
cvReleaseMat( &lfu1 );
cvReleaseMat( &fu2 );
cvReleaseMat( &fu1 );
cvReleaseMat( &R );
return result;
}
int cvL1QCSolve( CvMat* A, CvMat* B, CvMat* X, double epsilon, double mu, CvTermCriteria lb_term_crit, CvTermCriteria cg_term_crit )
{
CvMat* AAt = cvCreateMat( A->rows, A->rows, CV_MAT_TYPE(A->type) );
cvGEMM( A, A, 1, NULL, 0, AAt, CV_GEMM_B_T );
CvMat* W = cvCreateMat( A->rows, 1, CV_MAT_TYPE(X->type) );
if ( cvCGSolve( AAt, B, W, cg_term_crit ) > .5 )
{
cvReleaseMat( &W );
cvReleaseMat( &AAt );
return -1;
}
cvGEMM( A, W, 1, NULL, 0, X, CV_GEMM_A_T );
cvReleaseMat( &W );
cvReleaseMat( &AAt );
CvMat* U = cvCreateMat( X->rows, X->cols, CV_MAT_TYPE(X->type) );
cvAbsDiffS( X, U, cvScalar(0) );
CvScalar sumAbsX = cvSum( U );
double minAbsX, maxAbsX;
cvMinMaxLoc( U, &minAbsX, &maxAbsX );
cvConvertScale( U, U, .95, maxAbsX * .1 );
double tau = MAX( (2 * X->rows + 1) / sumAbsX.val[0], 1 );
if ( !(lb_term_crit.type & CV_TERMCRIT_ITER) )
lb_term_crit.max_iter = ceil( (log(2 * X->rows + 1) - log(lb_term_crit.epsilon) - log(tau)) / log(mu) );
CvTermCriteria nt_term_crit = cvTermCriteria( CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 50, lb_term_crit.epsilon );
for ( int i = 0; i < lb_term_crit.max_iter; ++i )
{
icvL1QCNewton( A, B, X, U, epsilon, tau, nt_term_crit, cg_term_crit );
tau *= mu;
}
cvReleaseMat( &U );
return 0;
}
typedef struct {
CvMatOps AOps;
CvMatOps AtOps;
CvMat* AR;
CvMat* AtR;
void* userdata;
} CvAAtOpsData;
static void icvAAtOps( CvMat* X, CvMat* Y, void* userdata )
{
CvAAtOpsData* data = (CvAAtOpsData*)userdata;
data->AtOps( X, data->AtR, data->userdata );
data->AOps( data->AtR, Y, data->userdata );
}
typedef struct {
CvMatOps AOps;
CvMatOps AtOps;
CvMat* AR;
CvMat* AtR;
CvMat* tX;
CvMat* sigx;
CvMat* atr;
double fe_inv;
double fe_inv_2;
void* userdata;
} CvH11OpsData;
static void icvH11Ops( CvMat* X, CvMat* Y, void* userdata )
{
CvH11OpsData* h11 = (CvH11OpsData*)userdata;
h11->AOps( X, h11->AR, h11->userdata );
h11->AtOps( h11->AR, h11->AtR, h11->userdata );
double rc = h11->fe_inv_2 * cvDotProduct( h11->atr, X );
cvAddWeighted( h11->AtR, -h11->fe_inv, h11->atr, rc, 0, h11->AtR );
cvMul( h11->sigx, X, h11->tX );
cvAdd( h11->tX, h11->AtR, Y );
}
static int icvL1QCNewton( CvAAtOpsData& AAtData, CvMat* B, CvMat* X, CvMat* U, double epsilon, double tau, CvTermCriteria nt_term_crit, CvTermCriteria cg_term_crit )
{
const double alpha = .01;
const double beta = .5;
CvMat* R = cvCreateMat( B->rows, B->cols, CV_MAT_TYPE(B->type) );
AAtData.AOps( X, AAtData.AR, AAtData.userdata );
cvSub( AAtData.AR, B, R );
CvMat* fu1 = cvCreateMat( X->rows, X->cols, CV_MAT_TYPE(X->type) );
CvMat* fu2 = cvCreateMat( X->rows, X->cols, CV_MAT_TYPE(X->type) );
CvMat* lfu1 = cvCreateMat( fu1->rows, fu1->cols, CV_MAT_TYPE(fu1->type) );
CvMat* lfu2 = cvCreateMat( fu2->rows, fu2->cols, CV_MAT_TYPE(fu2->type) );
cvSub( U, X, lfu1 );
cvAdd( X, U, lfu2 );
cvSubRS( lfu1, cvScalar(0), fu1 );
cvSubRS( lfu2, cvScalar(0), fu2 );
double epsilon2 = epsilon * epsilon;
double tau_inv = 1. / tau;
double fe = .5 * (cvDotProduct( R, R ) - epsilon2);
double fe_inv = 1. / fe;
cvLog( lfu1, lfu1 );
cvLog( lfu2, lfu2 );
CvScalar sumU = cvSum( U );
CvScalar sumfu1 = cvSum( lfu1 );
CvScalar sumfu2 = cvSum( lfu2 );
double f = sumU.val[0] - tau_inv * (sumfu1.val[0] + sumfu2.val[0] + log(-fe));
CvMat* atr = cvCreateMat( X->rows, X->cols, CV_MAT_TYPE(X->type) );
CvMat* ntgx = cvCreateMat( X->rows, X->cols, CV_MAT_TYPE(X->type) );
CvMat* ntgu = cvCreateMat( X->rows, X->cols, CV_MAT_TYPE(X->type) );
CvMat* sig1211 = cvCreateMat( X->rows, X->cols, CV_MAT_TYPE(X->type) );
CvMat* sigx = cvCreateMat( X->rows, X->cols, CV_MAT_TYPE(X->type) );
CvMat* w1 = cvCreateMat( X->rows, X->cols, CV_MAT_TYPE(X->type) );
CvMat* du = cvCreateMat( X->rows, X->cols, CV_MAT_TYPE(X->type) );
CvMat* pX = cvCreateMat( X->rows, X->cols, CV_MAT_TYPE(X->type) );
CvMat* pU = cvCreateMat( U->rows, U->cols, CV_MAT_TYPE(U->type) );
CvMat* pR = cvCreateMat( R->rows, R->cols, CV_MAT_TYPE(R->type) );
CvMat* pfu1 = cvCreateMat( fu1->rows, fu1->cols, CV_MAT_TYPE(fu1->type) );
CvMat* pfu2 = cvCreateMat( fu2->rows, fu2->cols, CV_MAT_TYPE(fu2->type) );
CvMat* Adx = cvCreateMat( B->rows, B->cols, CV_MAT_TYPE(B->type) );
CvMat* dx = cvCreateMat( X->rows, X->cols, CV_MAT_TYPE(X->type) );
CvMat* tX = cvCreateMat( X->rows, X->cols, CV_MAT_TYPE(X->type) );
int result = nt_term_crit.max_iter;
CvH11OpsData H11OpsData;
H11OpsData.AOps = AAtData.AOps;
H11OpsData.AtOps = AAtData.AtOps;
H11OpsData.AR = AAtData.AR;
H11OpsData.AtR = AAtData.AtR;
H11OpsData.userdata = AAtData.userdata;
H11OpsData.tX = tX;
H11OpsData.atr = atr;
H11OpsData.sigx = sigx;
int t, i;
for ( t = 0; t < nt_term_crit.max_iter; ++t )
{
AAtData.AtOps( R, atr, AAtData.userdata );
double* atrp = atr->data.db;
double* fu1p = fu1->data.db;
double* fu2p = fu2->data.db;
double* ntgxp = ntgx->data.db;
double* ntgup = ntgu->data.db;
double* sig1211p = sig1211->data.db;
double* sigxp = sigx->data.db;
double* w1p = w1->data.db;
double* dup = du->data.db;
for ( i = 0; i < X->rows; ++i, ++atrp, ++fu1p, ++fu2p, ++ntgxp, ++ntgup, ++sig1211p, ++sigxp, ++w1p, ++dup )
{
double fu1_inv = 1. / (*fu1p);
double fu2_inv = 1. / (*fu2p);
double ntgxv = fu1_inv - fu2_inv + fe_inv * (*atrp);
double ntguv = -tau - fu1_inv - fu2_inv;
double sig11 = fu1_inv * fu1_inv + fu2_inv * fu2_inv;
double sig12 = -fu1_inv * fu1_inv + fu2_inv * fu2_inv;
*sig1211p = sig12 / sig11;
*sigxp = sig11 - sig12 * (*sig1211p);
*w1p = ntgxv - (*sig1211p) * ntguv;
*ntgxp = -tau_inv * ntgxv;
*ntgup = -tau_inv * ntguv;
*dup = ntguv / sig11;
}
H11OpsData.fe_inv = fe_inv;
H11OpsData.fe_inv_2 = fe_inv * fe_inv;
if ( cvCGSolve( icvH11Ops, &H11OpsData, w1, dx, cg_term_crit ) > .5 )
{
result = t;
goto __clean_up__;
}
AAtData.AOps( dx, Adx, AAtData.userdata );
dup = du->data.db;
sig1211p = sig1211->data.db;
double* dxp = dx->data.db;
for ( i = 0; i < X->rows; ++i, ++dup, ++sig1211p, ++dxp )
*dup -= (*sig1211p) * (*dxp);
/* minimum step size that stays in the interior */
double aqe = cvDotProduct( Adx, Adx );
double bqe = 2. * cvDotProduct( R, Adx );
double cqe = cvDotProduct( R, R ) - epsilon2;
double smax = MIN( 1, -bqe + sqrt( bqe * bqe - 4 * aqe * cqe ) / (2 * aqe) );
dup = du->data.db;
dxp = dx->data.db;
fu1p = fu1->data.db;
fu2p = fu2->data.db;
for ( i = 0; i < X->rows; ++i, ++dup, ++dxp, ++fu1p, ++fu2p )
{
if ( (*dxp) - (*dup) > 0 )
smax = MIN( smax, -(*fu1p) / ((*dxp) - (*dup)) );
if ( (*dxp) + (*dup) < 0 )
smax = MIN( smax, (*fu2p) / ((*dxp) + (*dup)) );
}
smax *= .99;
/* backtracking line search */
bool suffdec = 0;
int backiter = 0;
double fep = fe;
double fp = f;
double lambda2;
while (!suffdec)
{
cvAddWeighted( X, 1, dx, smax, 0, pX );
cvAddWeighted( U, 1, du, smax, 0, pU );
cvAddWeighted( R, 1, Adx, smax, 0, pR );
cvSub( pU, pX, lfu1 );
cvAdd( pX, pU, lfu2 );
cvSubRS( lfu1, cvScalar(0), pfu1 );
cvSubRS( lfu2, cvScalar(0), pfu2 );
fep = .5 * (cvDotProduct( pR, pR ) - epsilon2);
cvLog( lfu1, lfu1 );
cvLog( lfu2, lfu2 );
CvScalar sumpU = cvSum( pU );
CvScalar sumpfu1 = cvSum( pfu1 );
CvScalar sumpfu2 = cvSum( pfu2 );
fp = sumpU.val[0] - tau_inv * (sumpfu1.val[0] + sumpfu2.val[0] + log(-fep));
lambda2 = cvDotProduct( ntgx, dx ) + cvDotProduct( ntgu, du );
double flin = f + alpha * smax * lambda2;
suffdec = (fp <= flin);
smax = beta * smax;
++backiter;
if ( backiter > 32 )
{
result = t;
goto __clean_up__;
}
}
/* set up for next iteration */
cvCopy( pX, X );
cvCopy( pU, U );
cvCopy( pR, R );
cvCopy( pfu1, fu1 );
cvCopy( pfu2, fu2 );
fe = fep;
fe_inv = 1. / fe;
f = fp;
lambda2 = -lambda2 * .5;
if ( lambda2 < nt_term_crit.epsilon )
{
result = t + 1;
break;
}
}
__clean_up__:
cvReleaseMat( &pfu2 );
cvReleaseMat( &pfu1 );
cvReleaseMat( &pR );
cvReleaseMat( &pU );
cvReleaseMat( &pX );
cvReleaseMat( &tX );
cvReleaseMat( &dx );
cvReleaseMat( &Adx );
cvReleaseMat( &du );
cvReleaseMat( &w1 );
cvReleaseMat( &sigx );
cvReleaseMat( &sig1211 );
cvReleaseMat( &ntgu );
cvReleaseMat( &ntgx );
cvReleaseMat( &lfu2 );
cvReleaseMat( &lfu1 );
cvReleaseMat( &fu2 );
cvReleaseMat( &fu1 );
cvReleaseMat( &R );
return result;
}
int cvL1QCSolve( CvMatOps AOps, CvMatOps AtOps, void* userdata, CvMat* B, CvMat* X, double epsilon, double mu, CvTermCriteria lb_term_crit, CvTermCriteria cg_term_crit )
{
CvMat* Z = cvCreateMat( X->rows, 1, CV_MAT_TYPE(X->type) );
CvMat* W = cvCreateMat( B->rows, 1, CV_MAT_TYPE(B->type) );
CvAAtOpsData AAtData;
AAtData.AOps = AOps;
AAtData.AtOps = AtOps;
AAtData.AtR = Z;
AAtData.userdata = userdata;
if ( cvCGSolve( icvAAtOps, &AAtData, B, W, cg_term_crit ) > .5 )
{
cvReleaseMat( &W );
cvReleaseMat( &Z );
return -1;
}
AtOps( W, X, userdata );
AAtData.AR = W;
CvMat* U = cvCreateMat( X->rows, X->cols, CV_MAT_TYPE(X->type) );
cvAbsDiffS( X, U, cvScalar(0) );
CvScalar sumAbsX = cvSum( U );
double minAbsX, maxAbsX;
cvMinMaxLoc( U, &minAbsX, &maxAbsX );
cvConvertScale( U, U, .95, maxAbsX * .1 );
double tau = MAX( (2 * X->rows + 1) / sumAbsX.val[0], 1 );
if ( !(lb_term_crit.type & CV_TERMCRIT_ITER) )
lb_term_crit.max_iter = ceil( (log(2 * X->rows + 1) - log(lb_term_crit.epsilon) - log(tau)) / log(mu) );
CvTermCriteria nt_term_crit = cvTermCriteria( CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 50, lb_term_crit.epsilon );
int totaliter = 0;
for ( int i = 0; i < lb_term_crit.max_iter; ++i )
{
totaliter += icvL1QCNewton( AAtData, B, X, U, epsilon, tau, nt_term_crit, cg_term_crit );
tau *= mu;
}
cvReleaseMat( &U );
cvReleaseMat( &W );
cvReleaseMat( &Z );
return 0;
}
#endif
This is the C-interface to OpenCV, not C++. Some of the types seem to be still available, though, with "_c.h" header files, if you still want to use the C code and don't want to convert it to the C++ types and interface.
I managed to get most of your code parsed with OpenCV 4.2 and:
#include <opencv2/core.hpp>
#include <opencv2/core/core_c.h>
However except:
CvMatOps, cvCGSolve
( I didn't find them in the source either, I just searched the OpenCV include directories for these strings, the latter seems to be in that file cvcgsolve.h which is something specific, it's found here: https://github.com/liuliu/l1cs/blob/master/src/cvcgsolve.cpp )
Illustrations:
Related
opengl not showing output from renderFunction
I was implementing this dda algorithm using opengl. However, for some reason, it doesn't plot the second line. I tried putting printf at every line, which shows that it IS executing. However, there is no output in my window #include <GL/gl.h> #include <GL/glut.h> #include <stdio.h> int choice = 0; void DDA(x0, y0, x1, y1) const x0, y0, x1, y1; { glOrtho(-500, 500, -500, 500, -1, 1); float dx = x1 - x0; float dy = y1 - y0; int steps = abs(dx) > abs(dy) ? abs(dx) : abs(dy); float xInc = (float)steps/dx; float yInc = (float)steps/dy; int x = x0, y = y0; for(int i = 0; i < steps; i++) { glBegin(GL_POINTS); glColor3f(1.0, 3.0, 2.0); glVertex2i(x, y); x += xInc; y += yInc; glEnd(); glFlush(); } } void Bresenham(x0, y0, x1, y1) const x0, y0, x1, y1; { glOrtho(-500, 500, -500, 500, -1, 1); int x = x0; int y = y0; int dx = x1 - x0; int dy = y1 - y0; int p = 2*dy-dx; int m = dy / dx; glBegin(GL_POINTS); { glColor3f(2.0, 3.0, 5.0); while(x != x1) { if(m < 1) { glVertex2i(x, y); x++; if(p >= 0) { p += 2*(dy - dx); y++; } else { p += 2*dy; } } else { glVertex2i(x, y); y++; if(p >= 0) { p += 2*(dx - dy); x++; } else { p += 2*dx; } } } glVertex2i(x, y); } glEnd(); glFlush(); } void circle(x0, y0, r) const x0, y0, r; { } void renderDDA(void) { DDA(0, 0, 300, 400); DDA(0, 0, 200, 200); } void renderBresenham(void) { Bresenham(0, 0, 300, 100); Bresenham(0, 0, 500, 0); } void renderCircle(void) { } main(argc, argv) char** argv; { redo: printf("ENTER YOUR CHOICE: "); scanf("%d", &choice); glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); glutInitWindowPosition(0, 0); glutInitWindowSize(1920, 1680); glutCreateWindow(argv[1]); glClear(GL_COLOR_BUFFER_BIT); glClearColor(0.0, 0.0, 0.0, 0.0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); switch (choice) { case 0: glutDisplayFunc(renderDDA); break; case 1: glutDisplayFunc(renderBresenham); break; case 2: glutDisplayFunc(renderCircle); break; default: printf("NO SUCH CHOICE!!"); goto redo; } glutMainLoop(); return 0; } I also tried swapping the lines. Then it draws only the upper line. it does execute the second call however.
glOrtho does not set an orthographic projection, it defines an orthographic projection matrix and multiplies the current matrix by the orthographic projection matrix. You've to set the identity matrix before calling glOrtho: glLoadIdentity(); glOrtho(-500, 500, -500, 500, -1, 1); Further there is an issue in the algorithm. The type of x and y has to be float. If you would trunc the result to int, then it is only possible to draw lines with angles that are aligned to multiples of 45 degreess, because x and y change exactly by 0 or 1 at each step: float x = x0, y = y0; for(int i = 0; i < steps; i++) { glBegin(GL_POINTS); glColor3f(1.0, 3.0, 2.0); glVertex2i((int)(x+0.5f), (int)(y+0.5f)); x += xInc; y += yInc; glEnd(); } Note, changing the type from int to float causes that x and y are tracked with full precision. glVertex2i((int)(x+0.5f), (int)(y+0.5f)) ensures that coordinates (x, y) are rounded to the integral position when the point is draw. I recommend to move the setting of the projection matrix from and glFlush from DDA respectively Bresenham to renderDDA respectively renderBresenham: void DDA(float x0, float y0, float x1, float y1) { float dx = x1 - x0; float dy = y1 - y0; int steps = abs(dx) > abs(dy) ? abs(dx) : abs(dy); float xInc = (float)steps/dx; float yInc = (float)steps/dy; float x = x0, y = y0; for(int i = 0; i < steps; i++) { glBegin(GL_POINTS); glColor3f(1.0, 3.0, 2.0); glVertex2i((int)(x+0.5f), (int)(y+0.5f)); x += xInc; y += yInc; glEnd(); } } void Bresenham(float x0, float y0, float x1, float y1) { int x = x0; int y = y0; int dx = x1 - x0; int dy = y1 - y0; int p = 2*dy-dx; int m = dy / dx; glBegin(GL_POINTS); { glColor3f(2.0, 3.0, 5.0); while(x != x1) { if(m < 1) { glVertex2i(x, y); x++; if(p >= 0) { p += 2*(dy - dx); y++; } else { p += 2*dy; } } else { glVertex2i(x, y); y++; if(p >= 0) { p += 2*(dx - dy); x++; } else { p += 2*dx; } } } glVertex2i(x, y); } glEnd(); } void renderDDA(void) { glLoadIdentity(); glOrtho(-500, 500, -500, 500, -1, 1); DDA(0, 0, 300, 400); DDA(0, 0, 200, 200); glFlush(); glutSwapBuffers(); } void renderBresenham(void) { glLoadIdentity(); glOrtho(-500, 500, -500, 500, -1, 1); Bresenham(0, 0, 300, 100); Bresenham(0, 0, 500, 0); glFlush(); glutSwapBuffers(); }
Scale and translate text in 2D with OpenGL
I am trying to draw text in UI elements with OpenGL but i fail in computing scale and translation values for different font sizes correctly, such that a text would fit nicely into a designated area. This is my first attempt in doing such a thing and it seemed to work until i noticed that with increasing font size the text will not fit into the calculated area anymore. I am not allowed to attach an image for a visual impression of what i mean, which is very sad. First i thought this would be caused by rounding the scaled font width in order to calculate the width that a frame needs but was unable to verify this. After much trial and error i am not even sure anymore if it's the text that gets projected incorrectly, or the frames i am trying to fit the text into. Please have a look and help me find the error, here's an overview of what i do: I construct a UI element by passing a certain font size in pixels. For a frame ( e.g. input box ) that should hold at most n characters the computation would look like this: - Get the width (in pixels) of a single character: x_advance and line_height are given by the fonts glyph description. Since i use mono spaced fonts i treat the x_advance as character width. font_oo_aspect = 1 / ( x_advance / line_height ) font_width = roundf( font_size / font_oo_aspect ) - Computing the actual frame dimension + some margin: frame_height = font_size + 2 * vertical pad frame_width = n * font_width + 2 * horizontal_pad The x and y location in pixels of the frames top left corner are set to be relative to its parents top left corner. When rendering UI elements first all frames are drawn and secondly the text. - Computing scale and translation for a frame: ortho_scale_x = 2 / window_width ortho_scale_y = -2 / window_height wo2 = frame_width * 0.5 ho2 = frame_height * 0.5 dx = parent_x + location_x + wo2 dy = parent_y + location_y + ho2 scale_x = ortho_scale_x * wo2 scale_y = ortho_scale_y * ho2 translation_x = dx / wo2 translation_y = dy / how - Computing scale and translation for a text: view_aspect = window_width / window_height font_scale = line_height / ( view_aspect * font_size ) scale_x = ortho_scale_x * font_scale scale_y = -ortho_scale_y * font_scale translation_x = frame_location_x / font_scale translation_y = -frame_location_y / font_scale The respective scale and translation values are sent to the shader. Here's the vertex shader code which is the same for frames and text: #version 130 in vec2 vertex; in vec2 uv; uniform vec2 scale; uniform vec3 translation; out vec2 coords; void main( void ) { gl_Position = vec4( ( translation.x + vertex.x ) * scale.x - 1.0, ( translation.y + vertex.y ) * scale.y + 1.0, translation.z, 1.0 ); coords = uv; } I hope i provided everything relevant, if not please let me know. Regards and thanks, Alfred Follows the render function for frames and text: // The buffer object data that frames use looks like this: float quad_data[ ] = { // x, y, u, v 1.0f, -1.0f, 1.0f, 0.0f, // bottom right 1.0f, 1.0f, 1.0f, 1.0f, // top right -1.0f, 1.0f, 0.0f, 1.0f, // top left -1.0f, -1.0f, 0.0f, 0.0f // bottom left }; // Each text element is rendered as an individual vertex array object. void render_frame_batches( void ) { int i, j; float f_font_size = 12; // 28; const float h = core.settings.height; const float sx = core.perspective.ortho_scale_x; const float sy = core.perspective.ortho_scale_y; const float view_aspect = core.perspective.view_aspect; float dx, dy, layer, wo2, ho2; Ui_Frame_Renderer *frame_renderer = &core.renderer.queue[ 0 ]; Ui_Render_Batch_Frame *batch = frame_renderer->batch; Ui_Render_Target_Frame *target; Ui_Shader *p = &core.programs[ PROGRAM_FRAME ]; const s16 *uni_loc = p->uniform_locations; glActiveTexture( GL_TEXTURE0 ); glUseProgram( p->program_id ); glUniform1i( ( s32 ) uni_loc[ LOC_U_TEXTURE0 ], 0 ); glBindVertexArray( core.shape_vao[ SHAPE_QUAD ].vao ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, core.shape_vao[ SHAPE_QUAD ].ind ); for( i = 0; i < RENDER_BATCH_FRAME_MAX; i++ ) { layer = ( float ) batch->layer; for( j = 0; j < batch->frame_count; j++ ) { target = &frame_renderer->target[ batch->queue_index + j ]; wo2 = ( float ) target->frame_width * 0.5f; ho2 = ( float ) target->frame_height * 0.5f; dx = ( float ) target->tx + wo2; dy = ( float ) target->ty + ho2; if( j > 0 ) { dx += ( float ) batch->parent_x; dy += ( float ) batch->parent_y; } glUniform2f( ( s32 ) uni_loc[ LOC_U_SCALE ], sx * wo2, sy * ho2 ); glUniform3f( ( s32 ) uni_loc[ LOC_U_TRANSLATION ], dx / wo2, dy / ho2, layer ); glUniform2f( ( s32 ) uni_loc[ LOC_U_LOCATION ], dx, h - dy ); s32 ib, ob; if( target->texture ) { // slider gradients ib = ob = 0; glBindTexture( GL_TEXTURE_1D, core.dynamic_textures[ target->texture ] ); } else { ib = wo2 - target->detail.frame.inner_border; ob = ho2 - target->detail.frame.outer_border; glUniform4fv( ( s32 ) uni_loc[ LOC_U_COLOR_BG ], 1, ( float * ) &core.colors[ target->bg ] ); glUniform4fv( ( s32 ) uni_loc[ LOC_U_COLOR_FG ], 1, ( float * ) &core.colors[ target->fg ] ); } glUniform1i( ( s32 ) uni_loc[ LOC_U_INNER ], ib ); glUniform1i( ( s32 ) uni_loc[ LOC_U_OUTER ], ob ); glDrawElements( GL_TRIANGLES, core.shape_vao[ SHAPE_QUAD ].len, GL_UNSIGNED_SHORT, 0 ); if( target->texture ) { glBindTexture( GL_TEXTURE_1D, 0 ); } } batch++; } frame_renderer++; batch = frame_renderer->batch; p = &core.programs[ PROGRAM_FONT ]; uni_loc = p->uniform_locations; Ui_Font *f = &fonts[ FONT_MENU ]; float font_scale = f->line_height / ( view_aspect * f_font_size ); float ri, ro; font_stroke_radii( f_font_size, f->line_height, view_aspect, &ri, &ro ); glBindTexture( GL_TEXTURE_2D, f->tex_id ); glUseProgram( p->program_id ); glUniform1i( ( s32 ) uni_loc[ LOC_U_TEXTURE0 ], 0 ); glUniform1i( ( s32 ) uni_loc[ LOC_U_FLAGS ], 1 ); glUniform1f( ( s32 ) uni_loc[ LOC_U_INNER ], ri ); glUniform1f( ( s32 ) uni_loc[ LOC_U_OUTER ], ro ); for( i = 0; i < RENDER_BATCH_FRAME_MAX; i++ ) { layer = ( float ) batch->layer; for( j = 0; j < batch->frame_count; j++ ) { target = &frame_renderer->target[ batch->queue_index + j ]; dx = ( float )( target->tx + batch->parent_x ); dy = ( float )( target->ty + batch->parent_y ); glUniform2f( ( s32 ) uni_loc[ LOC_U_SCALE ], sx / font_scale, -sy / font_scale ); glUniform3f( ( s32 ) uni_loc[ LOC_U_TRANSLATION ], dx * font_scale, -dy * font_scale, layer ); glUniform4fv( ( s32 ) uni_loc[ LOC_U_COLOR_FG ], 1, ( float * ) &core.colors[ target->fg ] ); Ui_Text *ui_text = &core.text_vao[ STATIC_STRING_MAX + target->detail.text.id ]; Ui_Vao *obj = &ui_text->vao; glBindVertexArray( obj->vao ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, obj->ind ); glDrawElements( GL_TRIANGLES, obj->len, GL_UNSIGNED_SHORT, 0 ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 ); glBindVertexArray( 0 ); } batch++; } glBindTexture( GL_TEXTURE_2D, 0 ); glUseProgram( 0 ); }
The calculation for the font scale should look like this: font_scale = line_height / font_size Before that i had multiplied the font size with the aspect ratio, which i guess makes no sense as i later divide the two orthographic scale values by the font scale and those already got the width and height "baked" into them. Sorry i can't give a mathematical explanation, it just seems to work nicely with that little change.
camshift object tracking problems
i have developed camshift algorithm by watching some tutorials..but unfortunately it didn't track the selected object....here is my code..i am a beginner to opencv and i need help..problem is the rectangle doesn't follow the object to track... this my code: bool destroy=false; CvRect box; CvRect track_window; bool drawing_box = false; cv::Mat imageROI; IplImage *image = 0, *hsv = 0, *hue = 0, *mask = 0, *backproject = 0, *histimg = 0; CvHistogram *hist = 0; int hdims = 16; float hranges_arr[] = {0,180}; float* hranges = hranges_arr; int vmin = 10, vmax = 256, smin = 30; IplImage *image2; CvScalar hsv2rgb( float hue ); CvConnectedComp track_comp; CvBox2D track_box; void draw_box(Mat img, CvRect rect) { imageROI= img(cv::Rect(box.x,box.y,box.width,box.height)); cv::rectangle(img, cvPoint(box.x, box.y), cvPoint(box.x+box.width,box.y+box.height), cvScalar(0,0,255) ,2); } CvScalar hsv2rgb( float hue ) { int rgb[3], p, sector; static const int sector_data[][3]= {{0,2,1}, {1,2,0}, {1,0,2}, {2,0,1}, {2,1,0}, {0,1,2}}; hue *= 0.033333333333333333333333333333333f; sector = cvFloor(hue); p = cvRound(255*(hue - sector)); p ^= sector & 1 ? 255 : 0; rgb[sector_data[sector][0]] = 255; rgb[sector_data[sector][1]] = 0; rgb[sector_data[sector][2]] = p; return cvScalar(rgb[2], rgb[1], rgb[0],0); } void my_mouse_callback( int event, int x, int y, int flags, void* param ) { IplImage* frame = (IplImage*) param; switch( event ) { case CV_EVENT_MOUSEMOVE: { if( drawing_box ) { box.width = x-box.x; box.height = y-box.y; } } break; case CV_EVENT_LBUTTONDOWN: { drawing_box = true; box = cvRect( x, y, 0, 0 ); } break; case CV_EVENT_LBUTTONUP: { drawing_box = false; if( box.width < 0 ) { box.x += box.width; box.width *= -1; } if( box.height < 0 ) { box.y += box.height; box.height *= -1; } draw_box(frame, box); } break; case CV_EVENT_RBUTTONUP: { destroy=true; } break; default: break; } } int _tmain(int argc, _TCHAR* argv[]) { VideoCapture cap(0); if(!cap.isOpened()) return -1; Mat image; Mat frame; //cv::Mat image= cv::imread("1.jpg"); cap>>image; if (!image.data) return 0; // Display image cv::namedWindow("Image"); cv::imshow("Image",image); IplImage* img = new IplImage(image); cvSmooth(img,img,CV_GAUSSIAN,3,0,0.0,0.0); IplImage* temp = cvCloneImage(img); cvSetMouseCallback("Image", my_mouse_callback, (void*) img); while( 1 ) { if (destroy) { cvDestroyWindow("Image"); break; } cvCopyImage(img, temp); if (drawing_box) draw_box(temp, box); cvShowImage("Image", temp); if (cvWaitKey(15) == 27) break; } cvReleaseImage(&temp); cvDestroyWindow("Image"); for(;;) { int i, bin_w, c; cap >> frame; IplImage* frame_ipl = new IplImage(frame); hsv = cvCreateImage( cvGetSize(frame_ipl), 8, 3 ); image2 = cvCreateImage( cvGetSize(frame_ipl), 8, 3 ); hue = cvCreateImage( cvGetSize(frame_ipl), 8, 1 ); mask = cvCreateImage( cvGetSize(frame_ipl), 8, 1 ); backproject = cvCreateImage( cvGetSize(frame_ipl), 8, 1 ); hist = cvCreateHist( 1, &hdims, CV_HIST_ARRAY, &hranges, 1 ); histimg = cvCreateImage( cvSize(320,200), 8, 3 ); cvZero( histimg ); cvCopy( frame_ipl, image2, 0 ); cvCvtColor( image2, hsv, CV_BGR2HSV ); int _vmin = vmin, _vmax = vmax; cvInRangeS( hsv, cvScalar(0,smin,MIN(_vmin,_vmax),0), cvScalar(180,256,MAX(_vmin,_vmax),0), mask ); cvSplit( hsv, hue, 0, 0, 0 ); float max_val = 0.f; cvSetImageROI( hue, box ); cvSetImageROI( mask, box ); cvCalcHist( &hue, hist, 0, mask ); cvGetMinMaxHistValue( hist, 0, &max_val, 0, 0 ); cvConvertScale( hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0 ); cvResetImageROI( hue ); cvResetImageROI( mask ); track_window = box; cvZero( histimg ); bin_w = histimg->width / hdims; for( i = 0; i < hdims; i++ ) { int val = cvRound( cvGetReal1D(hist->bins,i)*histimg->height/255 ); CvScalar color = hsv2rgb(i*180.f/hdims); cvRectangle( histimg, cvPoint(i*bin_w,histimg->height), cvPoint((i+1)*bin_w,histimg->height - val), color, -1, 8, 0 ); } cvCalcBackProject( &hue, backproject, hist ); cvAnd( backproject, mask, backproject, 0 ); cvCamShift( backproject, track_window, cvTermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 ), &track_comp, &track_box ); track_window = track_comp.rect; cv::rectangle(frame, track_window, cv::Scalar(0,255,0)); cv::namedWindow("result"); cv::imshow("result",frame); if(waitKey(30) >= 0) break; } return 0; }
but I use the c-api What might this code be changed to IplImage : void draw_box(Mat img, CvRect rect) { imageROI= img(cv::Rect(box.x,box.y,box.width,box.height)); cv::rectangle(img, cvPoint(box.x, box.y), cvPoint(box.x+box.width,box.y+box.height), cvScalar(0,0,255) ,2); }
Sierpinsky pyramid recursive algorithm
I am trying to implement a Sierpinsky pyramid, that is like a Sierpinsky triangle but in 3D. I have this structure to contain all the data about a pyramid: typedef struct { GLfloat xUp; GLfloat yUp; GLfloat zUp; GLfloat base; GLfloat height; }pyramid; Then I've written a function that calculates three sub-pyramids: void findSubPyramids( pyramid pyr, pyramid subs[3]) { for(int i=0; i<3; i++) { subs[i].height=pyr.height/2.0; subs[i].base=pyr.base/2.0; } memcpy(subs,&pyr,3*sizeof(GLfloat)); subs[1].yUp= pyr.yUp-pyr.height/2.0; subs[1].xUp= pyr.xUp+pyr.base/4.0; subs[1].zUp= pyr.zUp-pyr.base/4.0; subs[2].yUp= subs[1].yUp; subs[2].xUp= pyr.xUp-pyr.base/4.0; subs[2].zUp= subs[1].zUp; } But this algorithm implementation is wrong: something is wrong with the zUp coordinate of the two sub-pyramids at bottom: indeed the pyramid is not drawn as I want: But if I use glOrtho instead of gluPerspective the pyramid is drawn ok.I know that the gluPerspective and the functions I use are right, but is the algorithm to be wrong. This is where I implement the algorithm that calculated all the sub-pyramids: void drawSierpinskyPyramid (pyramid pyr) { assert(EQUAL(pyr.height, pyr.base)); if(pyr.base > 4.0) { setRandomColor(); pyramid subs[3]; drawPyramid(pyr); findSubPyramids(pyr, subs); for(int i=0; i<3; i++) { drawSierpinskyPyramid(subs[i]); } } } I don't get what's wrong.
Give this a shot: // gcc -std=c99 main.c -lglut -lGL -lGLU #include <GL/glut.h> #include <math.h> #include <stdlib.h> typedef struct { float x, y, z; } Vec3f; void glTriangle( Vec3f* v0, Vec3f* v1, Vec3f* v2 ) { glColor3ub( rand() % 255, rand() % 255, rand() % 255 ); glVertex3fv( (GLfloat*)v0 ); glVertex3fv( (GLfloat*)v1 ); glVertex3fv( (GLfloat*)v2 ); } // v0, v1, v2 = base, v3 = top void glTetrahedron( Vec3f* v0, Vec3f* v1, Vec3f* v2, Vec3f* v3 ) { glTriangle( v0, v2, v1 ); glTriangle( v0, v1, v3 ); glTriangle( v1, v2, v3 ); glTriangle( v2, v0, v3 ); } Vec3f Lerp( Vec3f* v0, Vec3f* v1, float u ) { Vec3f ret = { v0->x + ( v1->x - v0->x ) * u, v0->y + ( v1->y - v0->y ) * u, v0->z + ( v1->z - v0->z ) * u, }; return ret; } void glSierpinskiPyramid( Vec3f* v0, Vec3f* v1, Vec3f* v2, Vec3f* v3, unsigned int level ) { if( level == 0 ) { glTetrahedron( v0, v1, v2, v3 ); return; } // midpoints Vec3f m01 = Lerp( v0, v1, 0.5 ); Vec3f m12 = Lerp( v1, v2, 0.5 ); Vec3f m02 = Lerp( v0, v2, 0.5 ); Vec3f m03 = Lerp( v0, v3, 0.5 ); Vec3f m13 = Lerp( v1, v3, 0.5 ); Vec3f m23 = Lerp( v2, v3, 0.5 ); glSierpinskiPyramid( v0, &m01, &m02, &m03, level-1 ); glSierpinskiPyramid( &m01, v1, &m12, &m13, level-1 ); glSierpinskiPyramid( &m02, &m12, v2, &m23, level-1 ); glSierpinskiPyramid( &m03, &m13, &m23, v3, level-1 ); } void display() { glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); double w = glutGet( GLUT_WINDOW_WIDTH ); double h = glutGet( GLUT_WINDOW_HEIGHT ); gluPerspective( 60, w / h, 0.1, 100 ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glTranslatef( 0, 0, -9 ); srand(0); glPushMatrix(); glScalef( 3, 3, 3 ); static float angle = 0; angle += 1; glRotatef( angle/3, 0.2, 1, 0 ); Vec3f v0 = { -1, -1 / sqrtf(3), -1 / sqrtf(6) }; Vec3f v1 = { 1, -1 / sqrtf(3), -1 / sqrtf(6) }; Vec3f v2 = { 0, 2 / sqrtf(3), -1 / sqrtf(6) }; Vec3f v3 = { 0, 0, 3 / sqrtf(6) }; glBegin( GL_TRIANGLES ); glSierpinskiPyramid( &v0, &v1, &v2, &v3, 3 ); glEnd(); glPopMatrix(); glutSwapBuffers(); } void timer(int extra) { glutPostRedisplay(); glutTimerFunc(16, timer, 0); } int main( int argc, char **argv ) { glutInit( &argc, argv ); glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE ); glutInitWindowSize( 640, 480 ); glutCreateWindow( "Sierpinski Pyramid" ); glutDisplayFunc( display ); glutTimerFunc(0, timer, 0); glEnable( GL_DEPTH_TEST ); glEnable( GL_CULL_FACE ); glutMainLoop(); return 0; }
how to convert OpenGL code using vertex arrays into code using vertex buffer objects?
this is my draw() function written in C, using vertex arrays: void draw(float x1, float x2, float y1, float y2) { glPushMatrix(); glScalef(1.0 / (x2 - x1), 1.0 / (y2 - y1), 1.0); glTranslatef(-x1, -y1, 0.0); glColor3f(1.0, 1.0, 1.0); if( pts.size > 0 ) { glEnableClientState( GL_VERTEX_ARRAY ); glVertexPointer( 2, GL_FLOAT, 0, (float*)pts.data ); glDrawArrays( GL_LINE_STRIP, 0, pts.size / 2 ); glDisableClientState( GL_VERTEX_ARRAY ); } glPopMatrix(); }; before calling draw(), pts get's updated inside the update() function: void update(double (* func)(double x), float x1, float x2, int N) { double x, dx = (double)1.0/(double)N; vector_cleanup( &pts ); m = 0; for(x = x1; x < x2; x += dx) { vector_resize( &pts, pts.size + 2 ); *(float*)vector_get( &pts, pts.size-2 ) = (float)x; *(float*)vector_get( &pts, pts.size-1 ) = (float)func3(x); m++; } } I hope that by converting this code to use VBO, my graphics performance will increase. EDIT: func3() can be anything, e.g. sin(x) or just some linear mapping. All I'm currently trying to do is, to find out how quickly I can plot a bunch of points.
Using GLEW for extension wrangling: #include <stdio.h> #include <stdlib.h> #include <math.h> #include <GL/glew.h> #include <GL/glut.h> typedef struct vector /*dynamic vector of void* pointers. This one is used only by the deflate compressor*/ { void* data; size_t size; /*in groups of bytes depending on type*/ size_t allocsize; /*in bytes*/ unsigned typesize; /*sizeof the type you store in data*/ } vector; static unsigned vector_resize(vector* p, size_t size) /*returns 1 if success, 0 if failure ==> nothing done*/ { if(size * p->typesize > p->allocsize) { size_t newsize = size * p->typesize * 2; void* data = realloc(p->data, newsize); if(data) { p->allocsize = newsize; p->data = data; p->size = size; } else return 0; } else p->size = size; return 1; } static void vector_cleanup(void* p) { ((vector*)p)->size = ((vector*)p)->allocsize = 0; free(((vector*)p)->data); ((vector*)p)->data = NULL; } static void vector_init(vector* p, unsigned typesize) { p->data = NULL; p->size = p->allocsize = 0; p->typesize = typesize; } static void* vector_get(vector* p, size_t index) { return &((char*)p->data)[index * p->typesize]; } /* function to calculate each data point */ float func(float x) { return (float)sin(x); } GLuint vbo = 0; GLsizei vertcount = 0; void update(float (* func)(float x), float x1, float x2, int N) { float x, dx = 1.0f/N; vector pts; vector_init( &pts, sizeof( float ) ); for(x = x1; x < x2; x += dx) { vector_resize( &pts, pts.size + 2 ); *(float*)vector_get( &pts, pts.size-2 ) = x; *(float*)vector_get( &pts, pts.size-1 ) = func(x); } vertcount = (GLsizei)( pts.size / 2 ); glBindBuffer( GL_ARRAY_BUFFER, vbo ); glBufferData( GL_ARRAY_BUFFER, pts.size * pts.typesize, pts.data, GL_DYNAMIC_DRAW ); glBindBuffer( GL_ARRAY_BUFFER, 0 ); vector_cleanup( &pts ); } /* plotting function - very slow */ void draw(float x1, float x2, float y1, float y2) { glPushMatrix(); glScalef( 1.0f / (x2 - x1), 1.0f / (y2 - y1), 1.0f ); glTranslatef( -x1, -y1, 0.0f ); glColor3f( 1.0f, 1.0f, 1.0f ); glBindBuffer( GL_ARRAY_BUFFER, vbo ); glEnableClientState( GL_VERTEX_ARRAY ); glVertexPointer( 2, GL_FLOAT, 0, 0 ); glDrawArrays( GL_LINE_STRIP, 0, vertcount ); glDisableClientState( GL_VERTEX_ARRAY ); glBindBuffer( GL_ARRAY_BUFFER, 0 ); glPopMatrix(); }; /* Redrawing func */ float xmin = -10, xmax = 10, ymin = -5, ymax = 5; void redraw(void) { glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // -x, +x, -y, +y, number points draw(xmin, xmax, ymin, ymax); glutSwapBuffers(); }; /* Idle proc. Redisplays, if called. */ int nPoints = 3000; void idle(void) { // shift 'xmin' & 'xmax' by one. xmin++; xmax++; update(func, xmin, xmax, nPoints); glutPostRedisplay(); }; /* Key press processing */ void key(unsigned char c, int x, int y) { if(c == 27) exit(0); }; /* Window reashape */ void reshape(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, 1, 0, 1, -1, 1); glMatrixMode(GL_MODELVIEW); }; /* Main function */ int main(int argc, char **argv) { GLenum err; glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); glutCreateWindow("Graph plotter"); glutReshapeWindow(1024, 800); // init GLEW and output some GL info err = glewInit(); printf("GL_VERSION : %s\n", glGetString(GL_VERSION) ); printf("GL_VENDOR : %s\n", glGetString(GL_VENDOR) ); printf("GL_RENDERER : %s\n", glGetString(GL_RENDERER) ); if( GLEW_OK != err ) { printf("glewInit failed: %s", glewGetErrorString(err)); return EXIT_FAILURE; } if( !glewIsSupported("GL_VERSION_1_5") ) { printf("OpenGL version 1.5 or greater required.\n"); return EXIT_FAILURE; } glGenBuffers( 1, &vbo ); /* Register GLUT callbacks. */ glutDisplayFunc(redraw); glutKeyboardFunc(key); glutReshapeFunc(reshape); glutIdleFunc(idle); /* Init the GL state */ glLineWidth(2.0); /* Main loop */ glutMainLoop(); return 0; }