Blender中的3D杯子

在画室刚开始学画静物,临摹一个杯子的时候,我卡在了杯子的把手上。当时我曾想着要在Blender中做一个杯子,好好观察解析一下把手的结构。但是直到最近我才有时间把这杯子做出来:

这杯子是我参考一个YouTube视频做出来的:Blender Beginner Tutorial – Part 5: Modelling

通过这个视频我还理解了Subdivision Modifier的原理,并学会了用Loop Cut和Inset Faces将subdivision构造的曲面局限在某个区域,并消除subdivision带来的一些artifact。

来张素描原画和3D模型的对比,附上3D模型的结构解析:

继续阅读Blender中的3D杯子

如何将图片中不想要的部分P掉

以前一直不知道那些玩PS的人是如何将图片中不想要的部分P掉的。偶尔遇到这种需求的时候,我都是手工选中并复制需要抹掉的部分周围的区域,然后粘贴覆盖要抹掉的区域,不断重复这个过程直到不想要的部分全部被覆盖;最后为了避免粘贴的像素和四周形成明显的交界,我会使用虚化或喷漆之类的工具涂抹交界区域,尽量使被抹掉的区域和四周的区域融合在一起。这种方法在处理背景比较简单(比如接近纯色且没什么花纹)的图片时还能凑合用,但只要背景稍微有点复杂就不能胜任了,因为无法让粘贴的像素和四周区域自然融合;而且这种方法费时费力,有时候还要一个像素一个像素地操作,直觉上感觉就不是正确的方法,至少不是最佳实践。

前段时间偶然在一节Photoshop课程上得知了一个方法,就是Photoshop的内容识别填充功能(Content Aware Fill)。只要用选择工具将想要去掉的部分圈中,然后点几下鼠标就可以将不想要的部分P掉了。

GIMP也有类似的功能。在菜单栏中的 工具 -> 涂画工具 中有一个GIMP自带的“复原”(Heal)工具,在工具栏上是一个止血贴图标:

继续阅读如何将图片中不想要的部分P掉

WordPress官方的代码审查意见

在向WordPress官方首次提交插件代码的时候,我收到了对方的反馈邮件。WordPress官方在邮件中对我的代码提出了一些审查意见,其中的内容挺值得学习的,因此在这里分享一下。其实大致意思就两点:一是后端不要信任前端发来的数据,要多做检查和处理,这是做后端的常识;二是尽量使用WordPress已有的API而不要自己直接调用curl。

原文如下:

There are issues with your plugin code.

Please read this ENTIRE email, address all listed issues, and reply to this email with your corrected code attached. It is required for you to read and reply to these emails, and failure to do so will result in significant delays with your plugin being accepted.

Also please remember in addition to code quality, security and functionality, we require all plugins adhere to our guidelines. If you have not yet, please read them:

* https://developer.wordpress.org/plugins/wordpress-org/detailed-plugin-guidelines/

## Please sanitize, escape, and validate your POST calls

When you include POST/GET/REQUEST calls in your plugin, it’s important to sanitize, validate, and escape them. The goal here is to prevent a user from accidentally sending trash data through the system, as well as protecting them from potential security issues.

SANITIZE: All instances where generated content is inserted into the database, or into a file, or being otherwise processed by WordPress, the data MUST be properly sanitized for security. By sanitizing your POST data when used to make action calls or URL redirects, you will lessen the possibility of XSS vulnerabilities. You should never have a raw data inserted into the database, even by a update function, and even with a prepare()  call.

VALIDATE: In addition to sanitization, you should validate all your calls. If a $_POST  call should only be a number, ensure it’s an int()  before you pass it through anything. Even if you’re sanitizing or using WordPress functions to ensure things are safe, we ask you please validate for sanity’s sake. Any time you are adding data to the database, it should be the right data.

ESCAPE: Similarly, when you’re outputting data, make sure to escape it properly, so it can’t hijack admin screens. There are many esc_*()  functions you can use to make sure you don’t show people the wrong data.

In all cases, using stripslashes  or strip_tags  is not enough. You need to use the most appropriate method associated with the type of content you’re processing. Check that a URL is a URL and don’t just be lazy and use sanitize_text  please. The ultimate goal is that you should ensure that invalid and unsafe data is NEVER processed or displayed. Clean everything, check everything, escape everything, and never trust the users to always have input sane data.

Please review this document and update your code accordingly: http://codex.wordpress.org/Validating_Sanitizing_and_Escaping_User_Data

Example:

WordPress comes with an extensive HTTP API that should be used instead of creating your own curl calls. It’s both faster and more extensive. It’ll fall back to curl if it has to, but it’ll use a lot of WordPress’ native functionality first.

https://developer.wordpress.org/plugins/http-api/

—-

Please make sure you’ve addressed ALL issues brought up in this email.

译文:

继续阅读WordPress官方的代码审查意见

对一个项目同时使用svn和git两个远程仓库

以前曾经和朋友讨论过在一个项目中同时使用svn和git两个远程仓库的可能,如今真的遇到了这样的实际需求。

在开发WordPress插件External Media without Import的时候,因为希望插件能在WordPress官方渠道发布,所以需要在WordPress官方提供的svn远程仓库上托管这个项目。WordPress官方给我提供的svn仓库的地址是https://plugins.svn.wordpress.org/external-media-without-import/

但另一方面,考虑到github作为开源社区的人气,以及fork、pull request等代码贡献的便利性,我也想在github上托管这个项目。因此我在github上也创建了一个仓库:https://github.com/zzxiang/external-media-without-import.git

与此同时,我希望本地只需要维护一个项目文件夹,或者绝大部分操作只需要在一个文件夹中执行。这个文件夹由git管理,并可以方便地与WordPress的svn和github双方同步。不过后来经过一段时间摸索,我似乎只能做到让git和svn仓库的trunk分支同步,但这也足够了。

也就是说,我希望实现的应用场景如下图所示:

继续阅读对一个项目同时使用svn和git两个远程仓库

搭建本地WordPress开发调试环境

WordPress的运行环境是很传统的Apache + MySQL + PHP,其中PHP用的是PHP5,因此部署过程中应该不会有很难解决的问题,只不过步骤可能会比较繁琐。除此以外就是调试的配置需要摸索一阵子。

一开始我曾想过花钱买MAMP PRO来搭建WordPress的本地开发环境(MAMP免费版本只支持PHP7),图省事。但后来还是决定自己折腾,省下这笔钱。于是花了那么几天自己搭建了一套本地WordPress编码、运行和调试环境。除了Apache + MySQL + PHP之外,为了能在编辑器中单步调试,我还给PHP加装了Xdebug扩展,并给Vim编辑器加装了Vdebug插件。最终我将自己的WordPress站点从云主机拷贝到了本地,并在Vim中愉快地编写和调试里面的PHP代码:

让我哭笑不得的是,在我把环境搭建好一个月后写这篇文章的过程中,才发现其实Mac本身已经自带了Apache和PHP,并不用我自己去下载源代码再安装。

继续阅读搭建本地WordPress开发调试环境

让WordPress媒体库支持外链图片

最近有一个月左右没更新了,因为这个月的业余时间都在忙于一个WordPress插件:External Media without Import。

其实只是很小很简单的一个插件,代码不过短短几百行。不过这东西一旦被当成产品认真做起来,依然让我感到——每天在上班时间以外,应对完工作上的需求和bug之后,接着还要在业余时间认真做好另一个产品是多么劳心劳力。这是我正式发布并打算认真维护的第一个个人项目。为此我还自己设计制作了用于WordPress官方渠道的插件图标和Banner:

闲话少说,还是来介绍一下这个插件。先列出插件地址。

插件的WordPress官方渠道地址:

https://wordpress.org/plugins/external-media-without-import/

插件的Github地址:

https://github.com/zzxiang/external-media-without-import

继续阅读让WordPress媒体库支持外链图片

排查Mac中的Finder无限卡住的问题

某个周末,Mac突然抽风。Finder卡住,鼠标变成了风火轮一直在转。除了Finder以外的其它程序可以打开勉强使用,但那些程序打开没多久也会卡住。用活动监视器也无法让Finder强制退出;用命令行killall杀掉Finder进程也没用,它马上就会重启然后继续卡住。重启系统也没用。于是Finder就一直这样处于未响应状态,进而导致整个系统卡死:

继续阅读排查Mac中的Finder无限卡住的问题

Ionic中不合理的view层级导致afterEnter没有被调用

在公司的ionic项目中我们定义了如下状态:

其中views里面的root是在index.html里定义的ion-nav-view:

并且ABCtrl和ACDCtrl的代码中都注册监听了afterEnter事件。

按理说从状态A.B跳转到状态A.C.D时,ACDCtrl里的afterEnter会被执行,可实际运行的时候却没有。但是从E跳转到A.C.D则没有问题,ACDCtrl里的afterEnter会如期被调用。从E跳到A.B也没有问题,ABCtrl里的afterEnter也会执行。

公司项目的ionic lib版本是1.3.1:

本文末尾附上了我自己写的一个ionic小项目专用于重现这个问题。该项目的ionic lib版本是1.3.3:

于是我钻进了ionic的代码里研究了一番。

继续阅读Ionic中不合理的view层级导致afterEnter没有被调用