首页 文章 精选 留言 我的

精选列表

搜索[WebGL崩溃],共6152篇文章
优秀的个人博客,低调大师

想让DBA瞬间崩溃,那就让他去做SQL性能优化

摘要:很多大数据计算都是用 SQL 实现的,跑得慢时就要去优化 SQL,但常常碰到让人干瞪眼的情况。 本文分享自华为云社区《做 SQL 性能优化真是让人干瞪眼》,作者: 石臻臻的杂货铺 。 很多大数据计算都是用 SQL 实现的,跑得慢时就要去优化 SQL,但常常碰到让人干瞪眼的情况。比如,存储过程中有三条大概形如这样的语句执行得很慢: select a,b,sum(x) from T group by a,b where …; select c,d,max(y) from T group by c,d where …; select a,c,avg(y),min(z) from T group by a,c where …; 这里的 T 是个有数亿行的巨大表,要分别按三种方式分组,分组的结果集都不大。 分组运算要遍历数据表,这三句 SQL 就要把这个大表遍历三次,对数亿行数据遍历一次的时间就不短,何况三遍。 这种分组运算中,相对于遍历硬盘的时间,CPU 计算时间几乎可以忽略。如果可以在一次遍历中把多种分组汇总都计算出来,虽然 CPU 计算量并没有变少,但能大幅减少硬盘读取数据量,就能成倍提速了。 如果 SQL 支持类似这样的语法: from T -- 数据来自 T 表 select a,b,sum(x) group by a,b where … -- 遍历中的第一种分组 select c,d,max(y) group by c,d where … -- 遍历中的第二种分组 select a,c,avg(y),min(z) group by a,c where …; -- 遍历中的第三种分组 能一次返回多个结果集,那就可以大幅提高性能了。 可惜, SQL 没有这种语法,写不出这样的语句,只能用个变通的办法,就是用 group a,b,c,d 的写法先算出更细致的分组结果集,但要先存成一个临时表,才能进一步用 SQL 计算出目标结果。SQL 大致如下: create table T_temp as select a,b,c,d, sum(case when … then x else 0 end) sumx, max(case when … then y else null end) maxy, sum(case when … then y else 0 end) sumy, count(case when … then 1 else null end) county, min(case when … then z else null end) minz group by a,b,c,d; select a,b,sum(sumx) from T_temp group by a,b where …; select c,d,max(maxy) from T_temp group by c,d where …; select a,c,sum(sumy)/sum(county),min(minz) from T_temp group by a,c where …; 这样只要遍历一次了,但要把不同的 WHERE 条件转到前面的 case when 里,代码复杂很多,也会加大计算量。而且,计算临时表时分组字段的个数变得很多,结果集就有可能很大,最后还对这个临时表做多次遍历,计算性能也快不了。大结果集分组计算还要硬盘缓存,本身性能也很差。 还可以用存储过程的数据库游标把数据一条一条 fetch 出来计算,但这要全自己实现一遍 WHERE 和 GROUP 的动作了,写起来太繁琐不说,数据库游标遍历数据的性能只会更差! 只能干瞪眼! TopN 运算同样会遇到这种无奈。举个例子,用 Oracle 的 SQL 写 top5 大致是这样的: select * from (select x from T order by x desc) where rownum<=5 表 T 有 10 亿条数据,从 SQL 语句来看,是将全部数据大排序后取出前 5 名,剩下的排序结果就没用了!大排序成本很高,数据量很大内存装不下,会出现多次硬盘数据倒换,计算性能会非常差! 避免大排序并不难,在内存中保持一个 5 条记录的小集合,遍历数据时,将已经计算过的数据前 5 名保存在这个小集合中,取到的新数据如果比当前的第 5 名大,则插入进去并丢掉现在的第 5 名,如果比当前的第 5 名要小,则不做动作。这样做,只要对 10 亿条数据遍历一次即可,而且内存占用很小,运算性能会大幅提升。 这种算法本质上是把 TopN 也看作与求和、计数一样的聚合运算了,只不过返回的是集合而不是单值。SQL 要是能写成这样:select top(x,5) from T 就能避免大排序了。 然而非常遗憾,SQL 没有显式的集合数据类型,聚合函数只能返回单值,写不出这种语句! 不过好在全集的 TopN 比较简单,虽然 SQL 写成那样,数据库却通常会在工程上做优化,采用上述方法而避免大排序。所以 Oracle 算那条 SQL 并不慢。 但是,如果 TopN 的情况复杂了,用到子查询中或者和 JOIN 混到一起的时候,优化引擎通常就不管用了。比如要在分组后计算每组的 TopN,用 SQL 写出来都有点困难。Oracle 的 SQL 写出来是这样 select * from (select y,x,row_number() over (partition by y order by x desc) rn from T) where rn<=5 这时候,数据库的优化引擎就晕了,不会再采用上面说的把 TopN 理解成聚合运算的办法。只能去做排序了,结果运算速度陡降! 假如 SQL 的分组 TopN 能这样写: select y,top(x,5) from T group by y 把 top 看成和 sum 一样的聚合函数,这不仅更易读,而且也很容易高速运算。 可惜,不行。还是干瞪眼! 关联计算也是很常见的情况。以订单和多个表关联后做过滤计算为例,SQL 大体是这个样子: select o.oid,o.orderdate,o.amount from orders o left join city ci on o.cityid = ci.cityid left join shipper sh on o.shid=sh.shid left join employee e on o.eid=e.eid left join supplier su on o.suid=su.suid where ci.state='New York' and e.title = 'manager' and ... 订单表有几千万数据,城市、运货商、雇员、供应商等表数据量都不大。过滤条件字段可能会来自于这些表,而且是前端传参数到后台的,会动态变化。 SQL 一般采用 HASH JOIN 算法实现这些关联,要计算 HASH 值并做比较。每次只能解析一个 JOIN,有 N 个 JOIN 要执行 N 遍动作,每次关联后都需要保持中间结果供下一轮使用,计算过程复杂,数据也会被遍历多次,计算性能不好。 通常,这些关联的代码表都很小,可以先读入内存。如果将订单表中的各个关联字段预先做序号化处理,比如将雇员编号字段值转换为对应雇员表记录的序号。那么计算时,就可以用雇员编号字段值(也就是雇员表序号),直接取内存中雇员表对应位置的记录,性能比 HASH JOIN 快很多,而且只需将订单表遍历一次即可,速度提升会非常明显! 也就是能把 SQL 写成下面的样子: select o.oid,o.orderdate,o.amount from orders o left join city c on o.cid = c.# -- 订单表的城市编号通过序号 #关联城市表 left join shipper sh on o.shid=sh.# -- 订单表运货商号通过序号 #关联运货商表 left join employee e on o.eid=e.# -- 订单表的雇员编号通过序号 #关联雇员表 left join supplier su on o.suid=su.# -- 订单表供应商号通过序号 #关联供应商表 where ci.state='New York' and e.title = 'manager' and ... 可惜的是,SQL 使用了无序集合概念,即使这些编号已经序号化了,数据库也无法利用这个特点,不能在对应的关联表这些无序集合上使用序号快速定位的机制,只能使用索引查找,而且数据库并不知道编号被序号化了,仍然会去计算 HASH 值和比对,性能还是很差! 有好办法也实施不了,只能再次干瞪眼! 还有高并发帐户查询,这个运算倒是很简单: select id,amt,tdate,… from T where id='10100' and tdate>= to_date('2021-01-10', 'yyyy-MM-dd') and tdate<to_date('2021-01-25', 'yyyy-MM-dd') and … 在 T 表的几亿条历史数据中,快速找到某个帐户的几条到几千条明细,SQL 写出来并不复杂,难点是大并发时响应速度要达到秒级甚至更快。为了提高查询响应速度,一般都会对 T 表的 id 字段建索引: create index index_T_1 on T(id) 在数据库中,用索引查找单个帐户的速度很快,但并发很多时就会明显变慢。原因还是上面提到的 SQL 无序理论基础,总数据量很大,无法全读入内存,而数据库不能保证同一帐户的数据在物理上是连续存放的。硬盘有最小读取单位,在读不连续数据时,会取出很多无关内容,查询就会变慢。高并发访问的每个查询都慢一点,总体性能就会很差了。在非常重视体验的当下,谁敢让用户等待十秒以上?! 容易想到的办法是,把几亿数据预先按照帐户排序,保证同一帐户的数据连续存储,查询时从硬盘上读出的数据块几乎都是目标值,性能就会得到大幅提升。 但是,采用 SQL 体系的关系数据库并没有这个意识,不会强制保证数据存储的物理次序!这个问题不是 SQL 语法造成的,但也和 SQL 的理论基础相关,在关系数据库中还是没法实现这些算法。 那咋办?只能干瞪眼吗? 不能再用 SQL 和关系数据库了,要使用别的计算引擎。 开源的集算器 SPL 基于创新的理论基础,支持更多的数据类型和运算,能够描述上述场景中的新算法。用简单便捷的 SPL 写代码,在短时间内能大幅提高计算性能! 上面这些问题用 SPL 写出来的代码样例如下: 一次遍历计算多种分组 用聚合的方式计算 Top5 全集 Top5(多线程并行计算) 分组 Top5(多线程并行计算) 用序号做关联的 SPL 代码: 系统初始化 查询 高并发帐户查询的 SPL 代码: 数据预处理,有序存储 帐户查询 除了这些简单例子,SPL 还能实现更多高性能算法,比如有序归并实现订单和明细之间的关联、预关联技术实现多维分析中的多层维表关联、位存储技术实现上千个标签统计、布尔集合技术实现多个枚举值过滤条件的查询提速、时序分组技术实现复杂的漏斗分析等等。 正在为 SQL 性能优化头疼的小伙伴们,来和我们一起探讨吧: SPL下载地址:http://c.raqsoft.com.cn/article/1595816810031 SPL开源地址:https://github.com/SPLWare/esProc 点击关注,第一时间了解华为云新鲜技术~

优秀的个人博客,低调大师

拜登崩溃了,俄罗斯原来是个“高级黑”……

最新消息显示,美国和英国正式将俄罗斯对外情报局(SVR)认定为SolarWinds 黑客入侵事件的幕后黑手。为此,美国财政部已对俄罗斯实施全面制裁,包括制裁了六家俄方企业,并计划驱逐俄罗斯驻华盛顿大使馆的 10 名官员。 近年来,软件供应链攻击安全问题频频发生。调查显示,这些攻击造成的企业损失平均超过100万美元,因此,防御供应链攻击是十分必要的。现在我们来盘点下SolarWinds 供应链攻击的事件始末、影响,以及带给企业的一些思考。 什么是软供应链攻击? 想知道供应链攻击,就得先了解下什么是供应链。 供应链是指生产及流通过程中,涉及将产品或服务提供给最终用户活动的上游与下游企业所形成的网链结构。整个过程涉及原料供货商、供应商、制造商、仓储商、运输商、分销商、零售商以及终端客户。 供应链结构基本呈“线性”模式,所以当供应链上游出现干扰时,必将影响下游。也就是说,当恶意攻击者在受信任的第三方合作伙伴或提供商的软件上安装恶意软件,就有可能依赖供应链上的信任关系逃避传统安全产品的检查,潜入目标网络,实施非法攻击。这类型的攻击就是供应链攻击。 SolarWinds 黑客入侵事件就属于典型的供应链攻击。 SolarWinds是美国知名的基础网络管理软件供应商,全球大概有33,000名客户使用其旗下的Orion网络监控软件。恶意攻击者将恶意代码隐藏在Orien软件更新包中,通过受信任的供应链自动分发给下游的33,000名客户。一旦用户更新该软件,恶意代码就会以与应用相同的信任和权限运行,攻击者进而获得用户系统的访问权。 通过这种方式,黑客“隔山打牛”完成了对Orion客户——美国五角大楼和国土安全部、能源部、财政部、微软、Fireeye和其他组织的攻击。 愈演愈烈的软供应链攻击 目前,供应链攻击的频率和成熟度在不断提高。根据行业估计,供应链攻击现在占所有网络攻击的50%,去年同比激增了 78%。多达三分之二的公司经历了至少一次供应链攻击事件。同时,80%的IT专业人士认为软件供应链攻击将是他们的企业在未来三年面临的最大网络威胁之一。 以下是供应链攻击的常用攻击方式: 损害软件更新服务器。黑客通过入侵公司用来分发软件更新的服务器,窃取或伪造证书签名的软件更新,将恶意软件带进攻击目标。一旦应用程序自动更新,就会迅速感染大量系统。 获得对软件基础结构的访问权限。黑客使用社会工程学技术渗透到开发基础架构中,破坏构建环境和服务器,从而在软件编译和签名之前将恶意代码注入软件。而一旦软件进行了数字签名,就很难检测出恶意代码。 攻击第三方代码库。恶意软件还通过第三方代码(例如源代码存储库、软件开发工具包和开发人员在其应用程序中使用的框架)传递。如果网络罪犯访问该存储库,则他们可以像授权开发人员一样更改代码,这提供了将恶意代码添加到产品核心的机会。 其中,源代码存储库成为下一代软件供应链攻击的主要媒介。Synopsys在《2020软件供应链报告》中指出,当前超过90%的现代应用融入了开源组件,其中11%OSS组件中存在已知漏洞。而同时,针对开源项目的网络攻击数量同比增加了430%。下一代软供应链攻击方式正在兴起。 企业该如何应对供应链攻击 供应链攻击,已经成为APT攻击中的常用攻击手段,该攻击方法存在以下特点: 攻击面广,危害极大。由于软件供应链是一个完整的流动过程,因此在软件供应链上发生的攻击具有扩散性。一旦突破供应链的上游一环,便会“伤及一片”,对大量的软件供应商和最终用户造成影响。 潜伏周期长,检测困难。因为恶意代码是跟随”可信任”的软件更新进入到内网环境中,所以具有高度隐藏性。它可以欺骗并绕过外部防护,然后在目标网络环境中建立高权限账户,不断地访问并攻击新的目标。而且,不少软件供应链攻击者不直接攻击供应商,而是利用供应商来规避公司的网络安全机制检测风险。因此,想要从根源上就检测出攻击行为十分困难。 面对越来愈频繁的供应链攻击,需要上下游企业的共同努力,通过共同建立联防联控体系,提升遭受供应链攻击时的响应处置和恢复能力。 (1) 对于上游的软件供应商和开发人员 我们建议: 构建安全的软件更新程序,强化软件开发生命周期管理。 制定针对供应链攻击的事件响应流程,及时准确地通知客户。 加强员工安全意识培训,避免被攻击者钓鱼攻击。 建立“快速升级态势”,快速响应新的零日漏洞。 (2) 对于下游的厂商 我们建议: 应用零信任原则强化内部环境,包括加强账号验证、令牌验证、访问源校验等,持续性验证访问用户身份,收敛攻击暴露面,降低攻击成功概率。这样,即使恶意代码进入了内部环境,也无法越权访问。 采取部署蜜罐等基于行为的攻击检测解决方案,抵御复杂的供应链攻击,提高防御速度。一旦攻击者进行横向渗透,遍布全网的蜜罐就能快速感知。同时,蜜罐会将数据集中到本地威胁情报上,利用大数据分析和机器学习技术,生成完整的攻击者“画像”,从而主动防御新的攻击。这样,即使供应链攻击者更新源代码,也能快速发现。 建立纵深防御体系,联动威胁情报产品,快速拦截攻击,全局视角提升对威胁的发现识别、理解分析、响应处置。 【责任编辑:赵宁宁 TEL:(010)68476606】

优秀的个人博客,低调大师

Android Studio中两个让初学者崩溃菜单

在Android Studio中如何调整字体大小 在Android Studio中如何删除项目 相信刚开始用Android Studio的开发者都没有少被这两个问题折磨 本人以前都是用Eclipse做安卓程序开发的,前两天心血来潮决定抛弃Eclipse转而使用使用谷歌的开发工具Android Studio。刚下载安装好Android Studio时候本人一阵激动,立刻生成了HelloWorld发现代码字体很小,看着难受,就想通过偏好设置(Preference)设置一下字体,找了半天发现没有这个菜单,后发才发现在Android Studio中调整代码字体菜单不是一般的恶搞。我记录下来给后来者 Android Studio 中调整字体大小 首先要到这里 点击之后就会看到 直接点击【OK】保存之后,再去这个地方 点击Setting之后就会看到这个画面: 就会看到跟Eclipse中类似的功能了,可以各种设置。 怎么删除项目 删除一个项目要首先到File->ProjectSturcture 打开是这个样子的 选择你要删除的项目,然后点击上面的【—】即可。

优秀的个人博客,低调大师

Android 异常信息打印(适用于捕获应用崩溃信息收集)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qingfeng812/article/details/52448289 方法里面用到的工具类(设备信息,内存信息,用户信息,版本信息),请自行查找; public static String getExceptionMsg(Context ct, Throwable ex) { StringBuffer sb = new StringBuffer(); sb.append("----------------------异常信息输出-------------------------------------\n"); Writer writer = new StringWriter(); PrintWriter printWriter = new PrintWriter(writer); ex.printStackTrace(printWriter); Throwable cause = ex.getCause(); while (cause != null) { cause.printStackTrace(printWriter); cause = cause.getCause(); } printWriter.close(); String result = writer.toString(); String phone = CommonUtil.getSharedPreferences(ct, "user_phone"); String password = CommonUtil.getSharedPreferences(ct, "user_password"); String master_ch = CommonUtil.getSharedPreferences(ct, "Master_ch"); String company = CommonUtil.getSharedPreferences(ct, "erp_commpany"); sb.append(result); sb.append("\n----------------------用户信息输出-------------------------------------"); sb.append("\n phone:" + phone); sb.append("\n password:" + password); sb.append("\n master_ch:" + master_ch); sb.append("\n company:" + company); sb.append("\n----------------------设备信息输出-------------------------------------"); //获取设备大小 String deviceInfo = CommonUtil.getDeviceInfo(ct); System.out.println("deviceInfo=" + deviceInfo); sb.append("\n" + deviceInfo); sb.append("\n手机型号:" + CommonUtil.getDeviceModel()); sb.append("\n手机生产厂商:" + CommonUtil.getDeviceManufacturer()); //获取应用程序内存使用情况 sb.append("\n----------------------内存信息输出-------------------------------------\n"); sb.append(CommonUtil.getMemory()); //获取应用程序的当前版本号 sb.append("\n----------------------版本信息输出-------------------------------------\n"); sb.append("\n应用版本号:" + CommonUtil.ApkVersionCode(ct)); return sb.toString(); }

优秀的个人博客,低调大师

基于ThingJS开发的WebGL H5停车场三维可视化管理Demo

前言 随着社会的发展,城市中的汽车越来越多。车辆集中存放管理的场所被人类提出车辆进出的秩序、车辆存放的安全性、车辆存放管理的有偿性等要求。停车场系统应用现代机械电子及通讯科学技术,集控制硬件、软件于一体。随着科技的发展,停车场管理系统也日新月异,目前最为专业化的停车场系统为免取卡停车场。下面我们就用ThingJs平台来搭建一个3d可视化的停车场管理系统。 点击查看:DEMO 效果 停车场总览 车辆信息 车辆行动轨迹监控 车位信息展示 下面我们就用ThingJs平台来搭建一个3d可视化的停车场管理系统。 第一步 使用CampusBuilder来搭建一个模拟停车场。CampusBuider很好用在以往的文章中也多次提及过,丰富的模型库任你选择快速搭建3D场景。 第二步 初始化摄像机的位置并添加鼠标滑过,左键单击,右键单击,左键双击等事件。鼠标滑过,车勾边变

优秀的个人博客,低调大师

基于 WebGL(ThingJS)的室内平面图 2D/3D 导航 DEMO(Part 1)

前言 利用CampusBuilder来搭建自己的虚拟世界过程有这样一个问题:如何快速聚焦到虚拟场景的某一位置。当然我们可以创建几个按钮对应查找我们需要去的位置(参照物)并聚焦,但是按钮并不是很炫酷也不能很好的反馈给我们一些信息。接下来我们就用平面导航图来解决这一问题。 实现 第一步,使用CampusBuilder搭建模拟场景,CampusBuilder操作简单,分分钟就可以上手。这里为每一个房间都创建一个小球作为视点参照物体并勾选预览时隐藏,这样不会对我们的场景造成影响,也便于我们聚焦到指定房间。注意:要将我们每个房间中的设备框选之后组合在一起,为下一阶段的做准备。 第二步,把我们编辑好的场景加载到ThingJS中。 //加载场景代码 var app = new THING.App({ // 场景地址 "url": "http:/

优秀的个人博客,低调大师

基于WebGL架构的3D可视化平台—实现汽车行走路线演示

小车行走路线演示New VS Old 刚接触ThingJS的时候,写的一个小车开进小区的演示,今天又看了教程中有movePath这个方法就重新写了一遍,其中也遇到了一些问题,尤其突出的问题就是小车过弯的尴尬表现。 先给大家看看Old版本,Old版演示地址。 再看看New版本,AE86过弯不再笨拙顺畅无比,New版演示地址。 第二张效果图上可以看到由点连起来的路线,我的AE86也是严格按照路线行进的,相比于Old版本过弯的时候舒畅多了。Old版本是用setTimout(),rotateY(),moveTo()方法设置了几个点跑出来的。New版本放弃了这种办法,这种过弯实在让人看着不舒服,也不符合现实世界(排除醉酒驾驶司机)。下面就说一下New版本。 第一步,进入ThingJS在线开发,将场景地址替换成我们今天要用的,也可以自己去搭一个场景,campusBuilder下载地址。 /** * 说明:创建App,url为场景地址(可选) */ var app = new THING.App({ //场景地址 url: 'http://www.thingjs.com/./uploads/wechat/oLX7p05lsWJZUIxnIWsNXAzJ40X8/scene/2018-10-30-17-20-23' }); 第二步,在模型库里挑选一个你喜欢的车,种类丰富任你选择。 app.create({ type: 'Car', name: 'Car01', angle: 90, // 旋转 //这里我选了一台黑车,没找到AE86 url: 'http://model.3dmomoda.cn/models/c6ed424627234a298c1921950eb8534c/0/gltf/', //位置 position: [-32, 0, 26.2], complete: function () { console.log('Black Car !'); } }); 第三步,创建小车的行进路线和演示按钮。 app.on('load', function () { // 创建blackCar行进路线 var points = []; for (var x = -32, y = 0, z = 26.2 ; x <= 28; x += 4) { points.push([x, y, z]); } var radius = 1.75; for (var degree = 0, y = 0; degree <= 180; degree += 20) { var x = Math.sin(degree * 2 * Math.PI / 360) * radius + 28.5; var z = Math.cos(degree * 2 * Math.PI / 360) * radius + 24.45; points.push([x, y, z]); } for (var x = 27.5, y = 0, z = 22.7 ; x >= -6; x -= 4) { points.push([x, y, z]); } for (var degree = 0, y = 0; degree >= -90; degree -= 20) { var x = Math.sin(degree * 2 * Math.PI / 360) * radius -5.5; var z = Math.cos(degree * 2 * Math.PI / 360) * radius + 20.95; points.push([x, y, z]); } for (var x = -7.2, y = 0, z = 20.25 ; z >= 6; z -= 2) { points.push([x, y, z]); } //创建轨迹线 line = app.create({ type: 'Line', color: 0xFFFF00, // 轨迹线颜色 dotSize: 2, // 轨迹点的大小 points: points, }) THING.widget.Button('车辆路线', play); }); 最后一步,让小车动起来创建play()方法。 function play() { var car = app.query('Car01')[0]; car.movePath({ 'path': line.points, // 轨迹路线 'time': 10000, // 移动时间 'orientToPath': true, }); app.camera.lookAt(car); // app.camera.followObject({ // object:car, // }); } 做到这里小车已经可以动起来了,但是这个视角并不好,下面介绍一下摄像机中的followObject(params)。API地址 创建一个Car类继承THING.BaseObject,将物体类型转换成Car类型 //创建Car类 class Car extends THING.BaseObject{ constructor(app) { super(app); } } THING.Utils.addCastType('Car', /Car/); THING.factory.registerClass('Car', Car); //加到play() app.camera.followObject({ object:car, }); 下图是加了摄像机跟随物体的效果短短80行代码,其中我也遇到了不少问题划重点的就是app.camera.followObject()中object的类型问题,还有就是模型库里有一些车的模型比较奇怪,比如下图。以下是完整代码 //加载场景代码 var app = new THING.App({ // 场景地址 "url": "http://www.thingjs.com/./uploads/wechat/oLX7p05lsWJZUIxnIWsNXAzJ40X8/scene/2018-10-30-17-20-23", //背景设置 }); // 创建Car app.create({ type: 'Car', name: 'Car01', angle: 90, // 旋转 url: 'http://model.3dmomoda.cn/models/c6ed424627234a298c1921950eb8534c/0/gltf/', //位置 position: [-32, 0, 26.2], complete: function () { console.log('Black Car !'); } }); //创建Car类 class Car extends THING.BaseObject{ constructor(app) { super(app); } } THING.Utils.addCastType('Car', /Car/); THING.factory.registerClass('Car', Car); person.on('load',function()) app.on('load', function () { // 创建blackCar行进路线 var points = []; for (var x = -32, y = 0, z = 26.2 ; x <= 28; x += 4) { points.push([x, y, z]); } var radius = 1.75; for (var degree = 0, y = 0; degree <= 180; degree += 20) { var x = Math.sin(degree * 2 * Math.PI / 360) * radius + 28.5; var z = Math.cos(degree * 2 * Math.PI / 360) * radius + 24.45; points.push([x, y, z]); } for (var x = 27.5, y = 0, z = 22.7 ; x >= -6; x -= 4) { points.push([x, y, z]); } for (var degree = 0, y = 0; degree >= -90; degree -= 20) { var x = Math.sin(degree * 2 * Math.PI / 360) * radius -5.5; var z = Math.cos(degree * 2 * Math.PI / 360) * radius + 20.95; points.push([x, y, z]); } for (var x = -7.2, y = 0, z = 20.25 ; z >= 6; z -= 2) { points.push([x, y, z]); } //创建轨迹线 line = app.create({ type: 'Line', color: 0xFFFF00, // 轨迹线颜色 dotSize: 2, // 轨迹点的大小 points: points, }) THING.widget.Button('车辆路线', play); }); function play() { var car = app.query('Car01')[0]; car.movePath({ 'path': line.points, // 轨迹路线 'time': 10000, // 移动时间 'orientToPath': true, }); //app.camera.lookAt(car); app.camera.followObject({ object:car, }); } --------------------- 作者:extends Thread 来源:CSDN 原文:https://blog.csdn.net/nioooom/article/details/84069266 版权声明:本文为博主原创文章,转载请附上博文链接!

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册