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; }
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); }