SEXP _est_gen_Q_C( SEXP spYdelt, SEXP spZ, SEXP spX, SEXP spMaf, SEXP spParNull) { // int nUsed0, nTotal0; // CFmVector::StatCache( &nTotal0, &nUsed0 ); // int nUsed1, nTotal1; // CFmMatrix::StatCache( &nTotal1, &nUsed1 ); // Rprintf( "Enter C Range, Vec.count=%d, Mat.count=%d\n", nTotal0, nTotal1); CFmMatrix* pFmYDelt = getMatrixData(spYdelt); CFmMatrix* pFmZ = getMatrixData(spZ); CFmMatrix* pFmX = getMatrixData(spX); CFmVector* pFmMaf = getVectorData(spMaf); CFmVector* pFmParNull = getVectorData(spParNull); SEXP ret; try { ret = Xest_gen_Q_C( pFmYDelt, pFmZ, pFmX, pFmMaf, pFmParNull); } catch(const char* str) { _log_error( _HI_, "Exception=%s", str); return( R_NilValue ); } destroy( pFmYDelt ); destroy( pFmZ ); destroy( pFmX ); destroy( pFmMaf ); destroy( pFmParNull ); // CFmVector::StatCache( &nTotal0, &nUsed0 ); // CFmMatrix::StatCache( &nTotal1, &nUsed1 ); // Rprintf( "Leave C Range, Vec.count=%d, Mat.count=%d\n", nTotal0, nTotal1); return(ret); }
API void updateOpenGLLodMap(OpenGLLodMap *lodmap, Vector *position, bool autoExpand) { // update the viewer position assignVector(lodmap->viewerPosition, position); if(autoExpand) { // expand the quadtree to actually cover our position float *positionData = getVectorData(position); expandQuadtree(lodmap->quadtree, positionData[0], positionData[2]); } double range = getLodMapNodeRange(lodmap, lodmap->quadtree->root); // free our previous selection list g_list_free(lodmap->selection); lodmap->selection = NULL; // select the LOD map nodes to be rendered if(lodmapQuadtreeNodeIntersectsSphere(lodmap, lodmap->quadtree->root, position, range)) { lodmap->selection = selectLodMapNodes(lodmap, position, lodmap->quadtree->root); // make all selected nodes visible for(GList *iter = lodmap->selection; iter != NULL; iter = iter->next) { QuadtreeNode *node = iter->data; OpenGLLodMapTile *tile = node->data; // wait until the node is fully loaded g_mutex_lock(&tile->mutex); while(tile->status == OPENGL_LODMAP_TILE_LOADING) { g_cond_wait(&tile->condition, &tile->mutex); } g_mutex_unlock(&tile->mutex); // activate if not active yet if(tile->status != OPENGL_LODMAP_TILE_ACTIVE) { activateLodMapTile(lodmap, node); } tile->model->visible = true; // make model visible for rendering tile->model->polygonMode = lodmap->polygonMode; // set the parent's polygon mode } QuadtreeAABB box = quadtreeNodeAABB(lodmap->quadtree->root); logInfo("Updated LOD map for quadtree covering range [%d,%d]x[%d,%d] on %u levels: %d nodes selected", box.minX, box.maxX, box.minY, box.maxY, lodmap->quadtree->root->level, g_list_length(lodmap->selection)); } }
/** * Activates a loaded LOD map tile by creating an OpenGL model with appropriate transform for it. * * Every node model is derived from the same basic heightmap grid (the one in lodmap->heightmap). While the 2D vertex coordinates range * from [0,tileSize]x[0,tileSize], they are actually scaled down to [0,1]x[0,1] by the vertex shader, which conveniently means that a * node of level n should be scaled by just n in both x and z directions during the transformation into world coordinates. * The transformation for the height values (or correspondingly the y direction) works differently: First, height values all lie in the * [0,1] range, usually originating from a grayscale image, and the node level stretch generally doesn't apply to them. However, the * data source provides us with a heightRatio parameter which we need to take into account and scale all levels with, no matter their * level in the tree. * * @param lodmap the LOD map for which to active the tile * @param node the quadtree node for which to activate the tile */ static void activateLodMapTile(OpenGLLodMap *lodmap, QuadtreeNode *node) { OpenGLLodMapTile *tile = node->data; assert(tile->status == OPENGL_LODMAP_TILE_READY); // Create OpenGL textures tile->heightsTexture = createOpenGLVertexTexture2D(tile->heights); tile->heightsTexture->managed = false; // let us free the image tile->normalsTexture = createOpenGLTexture2D(tile->normals, false); tile->normalsTexture->internalFormat = GL_RGB16; tile->normalsTexture->samplingMode = OPENGL_TEXTURE_SAMPLING_LINEAR; tile->normalsTexture->wrappingMode = OPENGL_TEXTURE_WRAPPING_MIRROR; tile->normalsTexture->managed = false; // let us free the image initOpenGLTexture(tile->normalsTexture); synchronizeOpenGLTexture(tile->normalsTexture); tile->textureTexture = createOpenGLTexture2D(tile->texture, false); tile->textureTexture->samplingMode = OPENGL_TEXTURE_SAMPLING_LINEAR; tile->textureTexture->wrappingMode = OPENGL_TEXTURE_WRAPPING_MIRROR; tile->textureTexture->managed = false; // let us free the image initOpenGLTexture(tile->textureTexture); synchronizeOpenGLTexture(tile->textureTexture); // Create OpenGL model tile->model = createOpenGLModel(lodmap->heightmap); attachOpenGLModelMaterial(tile->model, "lodmap"); // Set model transform unsigned int scale = quadtreeNodeScale(node); // retrieve the scaling level from the node float *positionData = getVectorData(tile->model->translation); positionData[0] = node->x; positionData[1] = 0; positionData[2] = node->y; // y in model coordinates is z in world coordinates tile->model->scaleX = scale; tile->model->scaleY = lodmap->source->heightRatio; tile->model->scaleZ = scale; updateOpenGLModelTransform(tile->model); // At this point our tile is fully loaded except for the uniforms initialization, so let's initialize our parent now so we can grab its textures OpenGLLodMapTile *parentTile; tile->parentOffset = createVector2(0.0f, 0.0f); if(node->parent != NULL) { parentTile = node->parent->data; // wait until the node is fully loaded g_mutex_lock(&parentTile->mutex); while(parentTile->status == OPENGL_LODMAP_TILE_LOADING) { g_cond_wait(&parentTile->condition, &parentTile->mutex); } g_mutex_unlock(&parentTile->mutex); // activate if not active yet if(parentTile->status != OPENGL_LODMAP_TILE_ACTIVE) { activateLodMapTile(lodmap, node->parent); } // determine our index in our parent's node unsigned int parentIndex = quadtreeNodeGetParentContainingChildIndex(node); if(parentIndex & 1) { // second in x direction setVector(tile->parentOffset, 0, 0.5); } if(parentIndex & 2) { // second in y direction setVector(tile->parentOffset, 1, 0.5); } } else { parentTile = tile; } // Attach uniforms to model OpenGLUniformAttachment *uniforms = tile->model->uniforms; OpenGLUniform *heightsTextureUniform = getOpenGLUniform(uniforms, "heights"); assert(heightsTextureUniform != NULL); heightsTextureUniform->content.texture_value = tile->heightsTexture; OpenGLUniform *normalsTextureUniform = getOpenGLUniform(uniforms, "normals"); assert(normalsTextureUniform != NULL); normalsTextureUniform->content.texture_value = tile->normalsTexture; attachOpenGLUniform(uniforms, "texture", createOpenGLUniformTexture(tile->textureTexture)); attachOpenGLUniform(uniforms, "parentNormals", createOpenGLUniformTexture(parentTile->normalsTexture)); attachOpenGLUniform(uniforms, "parentTexture", createOpenGLUniformTexture(parentTile->textureTexture)); attachOpenGLUniform(uniforms, "parentOffset", createOpenGLUniformVector(tile->parentOffset)); attachOpenGLUniform(uniforms, "lodLevel", createOpenGLUniformInt(node->level)); attachOpenGLUniform(uniforms, "enableFragmentMorph", createOpenGLUniformInt(parentTile == tile ? 0 : 1)); // Make model invisible tile->model->visible = false; tile->status = OPENGL_LODMAP_TILE_ACTIVE; }