bool load_bk3d_scene( const char* filename, bake::Scene& scene, float scene_bbox_min[3], float scene_bbox_max[3], SceneMemory*& base_memory, size_t num_instances_per_mesh )
{
    void * pBk3dBufferMemory = NULL;
    unsigned int bk3dBufferMemorySz = 0;
    bk3d::FileHeader* bk3dData = bk3d::load(filename, &pBk3dBufferMemory, &bk3dBufferMemorySz);
    if (!bk3dData) return false;

    Bk3dSceneMemory* memory = new Bk3dSceneMemory(bk3dData, pBk3dBufferMemory);

    assert(bk3dData->pMeshes);
    memory->meshes.reserve(bk3dData->pMeshes->n);
    memory->instances.reserve(bk3dData->pMeshes->n);  // will have at least as many instances as meshes

    std::fill(scene_bbox_min, scene_bbox_min+3, FLT_MAX);
    std::fill(scene_bbox_max, scene_bbox_max+3, -FLT_MAX);

    for (int meshIdx = 0; meshIdx < bk3dData->pMeshes->n; ++meshIdx) {
        // Assumptions (enforced with assertions):
        // - vertices are float
        // - vertices are in Attribute 0
        // - normals are in Attribute 1
        // - indices are unsigned int format (could be unsigned short etc.)
        // - bk3d file doesn't give separate indices for attributes

        // Make separate mesh/instance per prim group
        bk3d::Mesh* pMesh = bk3dData->pMeshes->p[meshIdx];

        // Only GL_TRIANGLES are supported, not strips or fans
        bool skip_mesh = true;
        for (int pg = 0; pg < pMesh->pPrimGroups->n; pg++) {
            bk3d::PrimGroup* pPG = pMesh->pPrimGroups->p[pg];
            if (pPG->topologyGL == GL_TRIANGLES) {
                skip_mesh = false;
                break;
            }
        }
        if (skip_mesh) continue;

        // get the slot where the vertex pos is located (maybe mixed with other attributes)

        RT_ASSERT( pMesh->pAttributes->n >= 1 && "Mesh must have position attribute" );

        bk3d::Attribute* pPositionAttr = pMesh->pAttributes->p[0];
        RT_ASSERT( pPositionAttr->formatGL == GL_FLOAT && "Mesh must have vertex positions of type float" );

        bk3d::Slot* pPositionSlot = pMesh->pSlots->p[pPositionAttr->slot];
        float* vertices = (float*)pPositionAttr->pAttributeBufferData;
        const size_t num_vertices = pPositionSlot->vertexCount;
        const unsigned vertex_stride_bytes = pPositionAttr->strideBytes;

        float* normals = NULL;
        unsigned normal_stride_bytes = 0;
        if (pMesh->pAttributes->n > 1) {
            bk3d::Attribute* pNormalAttr = pMesh->pAttributes->p[1];
            RT_ASSERT( pNormalAttr->formatGL == GL_FLOAT && "Mesh must have normals of type float" );

            bk3d::Slot* pNormalSlot = pMesh->pSlots->p[pNormalAttr->slot];
            normals = (float*)pNormalAttr->pAttributeBufferData;
            normal_stride_bytes = pNormalAttr->strideBytes;
        }

        optix::Matrix4x4 mesh_xform = optix::Matrix4x4::identity();
        if (pMesh->pTransforms && pMesh->pTransforms->n > 0) {
            // Note: OptiX matrices are transposed from OpenGL/bk3d
            mesh_xform = optix::Matrix4x4(pMesh->pTransforms->p[0]->Matrix().m).transpose();
        }

        for (int pg = 0; pg < pMesh->pPrimGroups->n; pg++) {
            bk3d::PrimGroup* pPG = pMesh->pPrimGroups->p[pg];
            if(pPG->topologyGL != GL_TRIANGLES) continue;

            RT_ASSERT( pPG->indexFormatGL == GL_UNSIGNED_INT );

            bake::Mesh bake_mesh;

            // Same vertex buffer for each primgroup. Prime can also share these.
            bake_mesh.num_vertices  = num_vertices;
            bake_mesh.vertices      = vertices;
            bake_mesh.vertex_stride_bytes = vertex_stride_bytes;

            bake_mesh.normals       = normals;
            bake_mesh.normal_stride_bytes = normal_stride_bytes;

            bake_mesh.num_triangles = pPG->primitiveCount;
            bake_mesh.tri_vertex_indices = (unsigned int*)pPG->pIndexBufferData;

            bool compute_bbox = false;
            for (int k = 0; k < 3; ++k) {
                bake_mesh.bbox_min[k] = pPG->aabbox.min[k];
                bake_mesh.bbox_max[k] = pPG->aabbox.max[k];
                if (bake_mesh.bbox_min[k] > bake_mesh.bbox_max[k]) {
                    compute_bbox = true;
                    break;
                }
            }

            if (compute_bbox) {
                // Bbox stored in file is empty, so compute from vertices.
                std::fill(bake_mesh.bbox_min, bake_mesh.bbox_min+3, FLT_MAX);
                std::fill(bake_mesh.bbox_max, bake_mesh.bbox_max+3, -FLT_MAX);
                unsigned char* p = reinterpret_cast<unsigned char*>(bake_mesh.vertices);
                for (size_t i = 0; i < bake_mesh.num_vertices; ++i) {
                    expand_bbox(bake_mesh.bbox_min, bake_mesh.bbox_max, reinterpret_cast<float*>(p));
                    p += bake_mesh.vertex_stride_bytes ? bake_mesh.vertex_stride_bytes : 3*sizeof(float);
                }
            }

            bake::Instance instance;
            instance.mesh_index = (unsigned)memory->meshes.size();
            instance.storage_identifier = (uint64_t(meshIdx) << 32) | uint64_t(pg);

            optix::Matrix4x4 group_xform = optix::Matrix4x4::identity();
            if (pPG->pTransforms && pPG->pTransforms->n > 0) {
                group_xform = optix::Matrix4x4(pPG->pTransforms->p[0]->Matrix().m).transpose();
            }
            optix::Matrix4x4 mat = mesh_xform * group_xform;
            std::copy(mat.getData(), mat.getData()+16, instance.xform);
            xform_bbox(mat, bake_mesh.bbox_min, bake_mesh.bbox_max, instance.bbox_min, instance.bbox_max);

            expand_bbox(scene_bbox_min, scene_bbox_max, instance.bbox_min);
            expand_bbox(scene_bbox_min, scene_bbox_max, instance.bbox_max);

            memory->meshes.push_back(bake_mesh);
            memory->instances.push_back(instance);
        }
    }

    if (num_instances_per_mesh > 1) {
        make_debug_instances(memory->meshes, memory->instances, num_instances_per_mesh-1, scene_bbox_min, scene_bbox_max);
    }

    scene.meshes = &memory->meshes[0];
    scene.num_meshes = memory->meshes.size();
    scene.instances = &memory->instances[0];
    scene.num_instances = memory->instances.size();
    base_memory = memory;

    return true;
}
Exemplo n.º 2
0
void HEListElm::Display(FramesDocument* doc, const AffinePos& pos, long width, long height, BOOL background, BOOL expand_area)
{
	Image img = GetImage();

#ifdef HAS_ATVEF_SUPPORT
	if (img.IsAtvefImage())
	{
		VisualDevice* vis_dev = NULL;
		OP_ASSERT(this->doc && this->doc->GetVisualDevice());

		if (this->doc)
			vis_dev = this->doc->GetVisualDevice();

		if (vis_dev && g_tvManager)
		{
			OpRect view_bbox(0, 0, width, height);
			pos.Apply(view_bbox);

			OpRect screen_rect = vis_dev->ScaleToScreen(view_bbox);
			screen_rect = vis_dev->OffsetToContainerAndScroll(screen_rect);
			OpPoint screen_origo(0, 0);
			screen_origo = vis_dev->GetOpView()->ConvertToScreen(screen_origo);
			screen_rect.OffsetBy(screen_origo);

			URL tv_url = GetElm()->GetImageURL(FALSE, doc->GetLogicalDocument());
			g_tvManager->SetDisplayRect(&tv_url, screen_rect);
			g_tvManager->OnTvWindowAvailable(&tv_url, TRUE);
		}

		image_pos = pos;
		image_width = width;
		image_height = height;

		SetImageVisible(TRUE);
		return;
	}

#endif

	if (!GetImageVisible())
	{
		if (!img.IsEmpty())
		{
			if (background)
				GetElm()->SetHasBgImage(TRUE);

			OP_STATUS status = img.IncVisible(this);
			if (OpStatus::IsError(status))
			{
				if (OpStatus::IsMemoryError(status))
					doc->GetWindow()->RaiseCondition(OpStatus::ERR_NO_MEMORY);
				return;
			}
		}

		expand_area = FALSE;
	}

	if (expand_area)
	{
		// FIXME: Not the faintest idea how to make this work for transforms.
		OpRect current_bbox = GetImageBBox();
		OpRect expand_bbox(0, 0, width, height);
		pos.Apply(expand_bbox);

		current_bbox.UnionWith(expand_bbox);

		image_pos.SetTranslation(current_bbox.x, current_bbox.y);
		image_width = current_bbox.width;
		image_height = current_bbox.height;
	}
	else
	{
		image_pos = pos;
		image_width = width;
		image_height = height;
	}

	SetImageVisible(TRUE);

	SetHasPendingAnimationInvalidation(FALSE);

	if (doc && img.IsAnimated() && !animation_handler)
		animation_handler = ImageAnimationHandler::GetImageAnimationHandler(this, this->doc, syncronize_animation);
}