Notes for OpenGL - 4

本文详细介绍了OpenGL中的两种灯光类型:环境光与漫射光,包括如何使用glLightfv函数进行配置,以及如何通过glEnable开启光照。此外,还探讨了混合(blending)功能及其在实现透明效果中的应用。

今天开始在程序里面添加按键响应(Ketboard)以及灯光(light)。

先从灯光开始。灯光分为两种,一种叫环境光(这个我的翻译,原词是ambient light)。环境光顾名思义是说这并不是从特定的一个方向照射过来的光,在这种光下,我们的图形将没有阴影。(这里错了,其实环境光不是没有阴影,如果希望没有阴影的话,就不需要再“开灯”了。环境光是指所有的物体都将被这个光照射到)

而另一种光叫漫射光(diffuse light),这种就是正常的单方向的光,我们的图形将只有被照到的面会反射光亮,没有照射到的地方将会变暗。(这里也错了,并不是说只有被照到的菜会反光,只是直接照到的会更加亮一些,而没有直接照射到的将会比较暗淡)

glLightfv是我们所用的函数。函数原型是

void glLightfv(GLenum light, GLenum pname, const GLfloat *params)

第一个参数是指定一个灯,灯的数量是由执行情况而定的,但是至少能有8个。我们可以用GL_LIGHTx(0 <= x < GL_MAX_LIGHTS)来指定我们所要使用的灯。

第二个参数指定了单值的灯的光源参数,我们可以使用常量GL_AMBIENTGL_DIFFUSEGL_SPECULAR,GL_POSITIONGL_SPOT_DIRECTIONGL_SPOT_EXPONENTGL_SPOT_CUTOFF,GL_CONSTANT_ATTENUATIONGL_LINEAR_ATTENUATIONGL_QUADRATIC_ATTENUATION。

第三个参数是传入一个关于我们设置的光源参数数组的指针。

光源参数的四个参数其实跟颜色是一样的,前三个表示RGB,第四个是alpha值。如果参数是(1.0f, 0.0f, 0.0f, 1.0f)的话,说明照射过来的光是红色的。

然后还要注意的是我们的光是需要一个光源方向的,这个方向还是由glLightfv来确定,只需将第二个参数改成GL_POSITION即可。第三个参数也是参数数组。数组内的前三个参数跟glTranslatef的三个参数一样,是确定位置的。

我并不确定最后一个参数(这将在以后慢慢补充),现有的测试是,为1.0的时候光源似乎没有太过明显的阴影,而为0.0的时候,当我把光源远离物体的时候将会出现非常明显的阴影。而且这个参数的值越大,阴影越不明显。

 

注意,在使用光照之前,我们务必要先glEnable(GL_LIGHTx)来允许我们设置的灯可以使用,然后要用glEnable(GL_LIGHTING)来开始光照(一开始我并没有加入这句话,结果可想而知,大量时间浪费在找原因上面了...纠结...)。

 

最后是关于一些控制的问题了。其实这部分很简单,在没有做之前我一直以为会有些复杂,其实所有对于图形的控制,只是在更改glTranslatef 里的角度,当角度修改了以后,更新GL就可以完成我们所希望的改动。消息获取么,在QT中直接用mouseMoveEvent、mousePressEvent 还有keyPressEvent 就可以了。

 

 

接下来是关于混合(blending)的几个函数。混合在我现在的理解下(虽说是“理解”,但是其实我对混合并不是非常熟悉)仅仅是颜色、纹理的透明,alpha参数便是透明度。

打开混合需要glEnable(GL_BLEND)来启动,然后调用glBlendFunc(GL_SRC_ALPHA,GL_ONE) 来实现我们的透明效果

import camelot import pdfplumber import json import os import traceback import ctypes import sys import platform import logging # 配置日志记录 logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # 解决libGL缺失问题的前置检查 def check_lib_dependencies(): """检查并尝试解决libGL依赖问题""" try: # 尝试加载GL库 ctypes.CDLL("libGL.so.1") logger.info("libGL.so.1 已找到") except OSError as e: # 提供解决方案 if platform.system() == "Linux": error_msg = f"警告: 缺少libGL.so.1库,PDF处理需要此库: {str(e)}" solution = "解决方案: sudo apt-get update && sudo apt-get install libgl1-mesa-glx" logger.error(error_msg) logger.error(solution) # 抛出明确的错误信息 raise RuntimeError(f"{error_msg}\n{solution}") else: logger.warning(f"非Linux系统依赖问题: {str(e)}") raise # 运行依赖检查(确保在导入图形库前执行) try: check_lib_dependencies() except Exception as e: logger.critical(f"关键依赖检查失败: {str(e)}") def handler(event, context=None): """ 插件入口函数,处理所有请求逻辑 event: 包含输入参数的字典 context: 运行时上下文(可选,默认值为None) """ try: # 验证必要参数 required_params = ['file_url_id', 'task_type', 'question'] for param in required_params: if param not in event: error_msg = f"缺少必要参数: {param}" logger.error(error_msg) return { "status": "error", "error": error_msg } # 解析参数 file_url_id = event['file_url_id'] task_type = event['task_type'] question = event['question'] pages = event.get('pages', []) language = event.get('language', 'zh-CN') # 检查文件是否存在 if not os.path.exists(file_url_id): error_msg = f"文件不存在: {file_url_id}" logger.error(error_msg) return { "status": "error", "error": error_msg } # 根据任务类型执行对应操作 try: logger.info(f"开始处理任务: {task_type} 文件: {file_url_id}") if task_type == 'parse_overview': result = parse_overview(file_url_id) elif task_type == 'parse_text': result = parse_text(file_url_id, pages) elif task_type == 'parse_tables': result = parse_tables(file_url_id, pages) elif task_type == 'summarize_drawing': result = summarize_drawing(file_url_id, language) elif task_type == 'extract_rebar': result = extract_rebar(file_url_id) elif task_type == 'extract_components': result = extract_components(file_url_id, event.get('target_types', [])) else: error_msg = f"不支持的任务类型: {task_type}" logger.error(error_msg) return { "status": "error", "error": error_msg } except RuntimeError as e: # 专门处理依赖错误 logger.error(f"运行时依赖错误: {str(e)}") return { "status": "error", "error": str(e), "solution": "请安装libgl1-mesa-glx: sudo apt-get update && sudo apt-get install libgl1-mesa-glx" } except Exception as e: logger.error(f"处理任务时出错: {str(e)}", exc_info=True) # 处理系统依赖错误 if "libGL.so.1" in str(e) or "libGL" in str(e) or "GL" in str(e): return { "status": "error", "error": "系统缺少必要的图形处理库", "solution": "请安装libgl1-mesa-glx: sudo apt-get update && sudo apt-get install libgl1-mesa-glx" } else: raise # 构造成功响应 logger.info(f"任务 {task_type} 处理成功") return { "status": "success", "result": result, "qa_answer": generate_answer(question, result) } except Exception as e: # 捕获并返回错误信息,包含详细堆栈跟踪以便调试 logger.critical(f"处理请求时发生未捕获异常: {str(e)}", exc_info=True) return { "status": "error", "error": str(e), "traceback": traceback.format_exc() } # 辅助函数:生成问题答案 def generate_answer(question, result): return f"针对问题「{question}」的处理结果:{str(result)[:200]}..." # 解析概览信息 def parse_overview(file_url_id): try: logger.info(f"解析文件概览: {file_url_id}") # 设置环境变量以避免GUI依赖 os.environ["OPENCV_IO_ENABLE_OPENEXR"] = "1" os.environ["CV_IO_ENABLE_OPENEXR"] = "1" with pdfplumber.open(file_url_id) as pdf: pages_count = len(pdf.pages) first_page = pdf.pages[0] if pages_count > 0 else None # 提取第一页文本内容 first_page_text = "" if first_page: try: first_page_text = first_page.extract_text() or "" except Exception as e: logger.warning(f"提取第一页文本失败: {str(e)}") first_page_text = "" return { "document_id": file_url_id, "pages": pages_count, "page_sizes": [{ "width": first_page.width if first_page else 0, "height": first_page.height if first_page else 0, "unit": "pt" }] if first_page else [], "has_text": bool(first_page_text), "has_tables": False, # 简化处理,实际应检测 "has_vectors": False, # 简化处理,实际应检测 "probable_types": ["结构平面图", "建筑详图"] } except Exception as e: logger.error(f"解析概览失败: {str(e)}", exc_info=True) raise Exception(f"解析概览失败: {str(e)}") # 解析文本 def parse_text(file_url_id, pages): try: logger.info(f"解析文本内容: {file_url_id}, 页数: {pages}") text_blocks = [] # 设置环境变量以避免GUI依赖 os.environ["OPENCV_IO_ENABLE_OPENEXR"] = "1" os.environ["CV_IO_ENABLE_OPENEXR"] = "1" with pdfplumber.open(file_url_id) as pdf: # 确定要处理的页面 process_pages = pages if pages else range(len(pdf.pages)) for page_num in process_pages: if 0 <= page_num < len(pdf.pages): page = pdf.pages[page_num] try: text = page.extract_text() or "" except Exception as e: logger.warning(f"提取第 {page_num+1} 页文本失败: {str(e)}") text = "" if text: text_blocks.append({ "page": page_num + 1, # 页码从1开始 "bbox": [0, 0, page.width, page.height], "text": text, "font": "unknown", "size": 12 }) return { "document_id": file_url_id, "items": text_blocks } except Exception as e: logger.error(f"解析文本失败: {str(e)}", exc_info=True) raise Exception(f"解析文本失败: {str(e)}") # 解析表格 def parse_tables(file_url_id, pages): try: logger.info(f"解析表格: {file_url_id}, 页数: {pages}") # 设置环境变量以避免GUI依赖 os.environ["OPENCV_IO_ENABLE_OPENEXR"] = "1" os.environ["CV_IO_ENABLE_OPENEXR"] = "1" # 转换为camelot需要的页码格式 pages_str = ','.join(map(str, [p+1 for p in pages])) if pages else 'all' # 尝试使用不同的解析方式 try: logger.info("尝试使用lattice模式解析表格") tables = camelot.read_pdf( file_url_id, pages=pages_str, flavor='lattice' ) except Exception as e: logger.warning(f"lattice模式失败,尝试stream模式: {str(e)}") try: tables = camelot.read_pdf( file_url_id, pages=pages_str, flavor='stream' ) except Exception as inner_e: logger.error(f"两种表格解析模式均失败: {str(inner_e)}") raise result_tables = [] for table in tables: cells = [] for i, row in enumerate(table.df.values): for j, cell_text in enumerate(row): cells.append({ "row": i, "col": j, "text": cell_text, "bbox": table._bbox }) result_tables.append({ "page": table.page, "title": f"Table on page {table.page}", "cells": cells }) return { "document_id": file_url_id, "items": result_tables } except Exception as e: logger.error(f"解析表格失败: {str(e)}", exc_info=True) # 处理特定的表格解析错误 if "Ghostscript is not installed" in str(e): error_msg = "未安装Ghostscript,请执行: sudo apt-get install ghostscript" logger.error(error_msg) raise Exception(error_msg) raise Exception(f"解析表格失败: {str(e)}") # 图纸摘要生成(简化版) def summarize_drawing(file_url_id, language): logger.info(f"生成图纸摘要: {file_url_id}, 语言: {language}") overview = parse_overview(file_url_id) return { "document_id": file_url_id, "text_summary": f"该图纸包含{overview['pages']}页,可能是{overview['probable_types'][0]}", "structured": { "drawing_type": overview['probable_types'][0], "levels": ["一层", "二层"], "grids": ["1-6", "A-D"], "notes": ["混凝土强度等级为C30"] } } # 钢筋信息提取(简化版) def extract_rebar(file_url_id): logger.info(f"提取钢筋信息: {file_url_id}") # 设置环境变量以避免GUI依赖 os.environ["OPENCV_IO_ENABLE_OPENEXR"] = "1" os.environ["CV_IO_ENABLE_OPENEXR"] = "1" return { "document_id": file_url_id, "summary": { "total_weight_kg": 1250.5, "total_count": 25 }, "items": [ { "mark": "GJ1", "grade": "HRB400", "diameter": "Φ20", "spacing": "200mm", "length": 6500, "quantity": 10 } ] } # 构件提取(简化版) def extract_components(file_url_id, target_types): logger.info(f"提取构件: {file_url_id}, 目标类型: {target_types}") # 设置环境变量以避免GUI依赖 os.environ["OPENCV_IO_ENABLE_OPENEXR"] = "1" os.environ["CV_IO_ENABLE_OPENEXR"] = "1" return { "document_id": file_url_id, "items": [ { "id": "B1", "type": "beam", "grid": "2-3/B-C", "elevation": "+5.400", "size": { "width": 300, "height": 500 }, "rebar_spec": "上部 2Φ20@200, 下部 2Φ18@200" } ] } 将 代码修改,使用pymupsd依赖包,不使用openGL,将修改完的完整代码发给我
最新发布
08-30
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值