七夕,当爱神丘比特遇上牛郎和织女

举报
天元浪子 发表于 2022/08/05 00:41:49 2022/08/05
【摘要】 七夕是中国民间的传统节日,不同时代、不同地域的人们给这个节日赋予了不同的含义。在漫长的演变过程中,七夕成了牛郎织女相会的日子。正因为这个美丽的爱情传说,七夕被视为中国最具浪漫色彩的、象征爱情的节日。在西风...

七夕是中国民间的传统节日,不同时代、不同地域的人们给这个节日赋予了不同的含义。在漫长的演变过程中,七夕成了牛郎织女相会的日子。正因为这个美丽的爱情传说,七夕被视为中国最具浪漫色彩的、象征爱情的节日。在西风东渐的背景下,七夕又成了中国的“情人节”。

既然是情人节,浪漫的程序员总喜欢搞点花样出来,为紧张且平淡的生活添点色彩。今天给各位带来的是3D动画版的丘比特爱情之剑:一只金色的丘比特爱情之剑以慢镜头方式缓缓刺中一个脉动的红心,红心的主人将会无法控制地爱上TA所看到第一个人。我猜,当初牛郎和织女一定是被丘比特的爱情之剑射中以后才相爱的,毕竟,他们都生活在天上——西方文化中,木星(Jupiter)就是小爱神丘比特,金星(Venus)则是大爱神维纳斯。

在丘比特的爱情之剑出场前,先用matplotlib绘制一颗2D的红心热热身。

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(-np.pi/2, np.pi/2, 1000)
y1 = np.power(np.cos(x),0.5) * np.cos(200*x) + np.power(np.absolute(x),0.5) - 0.7
y2 = np.power(4-np.power(x, 2), 0.01)

plt.plot(x, y1*y2, c='r')
plt.show()

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在这里插入图片描述

上下波动的曲线形成的心形

放大一点看的话,就会发现上面这颗红心其实是一条连续上下波动的曲线。下面的红心,是一个真正封闭的心形,只不过是由四条曲线首尾相连组成的。

import numpy as np
import matplotlib.pyplot as plt

x1 = np.linspace(0, 2, 300)
x2 = np.linspace(0, -2, 300)

y11 = (np.power(x1, 2/3) + np.power(np.power(x1, 4/3)-4*np.power(x1, 2)+4, 0.5))/2 - 0.12
y12 = (np.power(x1, 2/3) - np.power(np.power(x1, 4/3)-4*np.power(x1, 2)+4, 0.5))/2
y21 = (np.power(-x2, 2/3) + np.power(np.power(-x2, 4/3)-4*np.power(-x2, 2)+4, 0.5))/2 - 0.12
y22 = (np.power(-x2, 2/3) - np.power(np.power(-x2, 4/3)-4*np.power(-x2, 2)+4, 0.5))/2

plt.plot(x1, y11, c='r')
plt.plot(x1, y12, c='r')
plt.plot(x2, y21, c='r')
plt.plot(x2, y22, c='r')
plt.show()

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

在这里插入图片描述

四条曲线首尾相连组成的心形

那么,可以用一笔画一个心形吗?当然可以,极坐标方程 r = arccos(sinθ)就是一条心形线,只是形状不够完美而已。

import numpy as np
import matplotlib.pyplot as plt

theta = np.linspace(0, 2*np.pi, 1000)
x = np.arccos(np.sin(theta)) * np.cos(theta)
y = np.arccos(np.sin(theta)) * np.sin(theta)

plt.plot(x, y, c='r')
plt.show()

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在这里插入图片描述

心形线

是时候展示3D版的红心了。运行下面的代码,除了需要numpy模块,还需要安装wxgl模块——基于PyOpenGL的三维数据绘图工具包。

pip install wxgl

关于wxgl模块的更多详情,请点击十分钟玩转3D绘图:WxGL完全手册,这里是中文文档

下面是3D版的红心的绘制代码,

import numpy as np
import wxgl.glplot as glt

a = np.linspace(0, 2*np.pi, 500)
b = np.linspace(0.5*np.pi, -0.5*np.pi, 500)
lons, lats = np.meshgrid(a, b)
w = np.sqrt(np.abs(a - np.pi)) * 2
x = 2 * np.cos(lats) * np.sin(lons) * w
y = -2 * np.cos(lats) * np.cos(lons) * w
z = 2 * np.sin(lats)

glt.mesh(x, y, z, color='crimson') # crimson - 绯红
glt.show()

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

是不是很简单?wxgl的使用风格几乎和matplotlib完全一致。拖动鼠标,就可以看到这个3D版的红心的前后左右了。

在这里插入图片描述

3D红心

接下来,这段代码将红心数据的生成封装了一个函数,然后调用自定义的模型变换函数,这颗红心就跳动起来了。

import numpy as np
import wxgl.glplot as glt

def red_heart(r, slices=100, thick=2.0, shift=(0,0,0)):
    """返回红心顶点数据"""
    
    a = np.linspace(0, 2*np.pi, slices)
    b = np.linspace(0.5*np.pi, -0.5*np.pi, slices)
    lons, lats = np.meshgrid(a, b)
    w = np.sqrt(np.abs(a - np.pi)) * thick
    x = r * np.cos(lats) * np.sin(lons) * w + shift[0]
    y = -r * np.cos(lats) * np.cos(lons) * w + shift[1]
    z = r * np.sin(lats) + shift[2]
    
    return x, y, z

def heart_beat(t):
    """心跳函数"""
    
    t %= 1000
    if t < 300:
        scale = 1 + t/3000
    elif t > 700:
        scale = 1 + (1000-t)/3000
    else:
        scale = 1.1
    
    return (scale,)

glt.mesh(*red_heart(2), color='crimson', transform=heart_beat)
glt.show()

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

点击左侧工具条上的播放按钮,这颗红心就会按照60次/秒的心率跳动起来。熟悉了wxgl的使用,不难读懂下面这个完整的丘比特爱情之箭的代码。

import numpy as np
import wxgl
import wxgl.glplot as glt

def red_heart(r, slices=100, thick=2.0, shift=(0,0,0)):
    """返回红心顶点数据"""
    
    a = np.linspace(0, 2*np.pi, slices)
    b = np.linspace(0.5*np.pi, -0.5*np.pi, slices)
    lons, lats = np.meshgrid(a, b)
    w = np.sqrt(np.abs(a - np.pi)) * thick
    x = r * np.cos(lats) * np.sin(lons) * w + shift[0]
    y = -r * np.cos(lats) * np.cos(lons) * w + shift[1]
    z = r * np.sin(lats) + shift[2]
    
    return x, y, z

def heart_beat(t):
    """心跳函数"""
    
    t %= 1000
    if t < 300:
        scale = 1 + t/3000
    elif t > 700:
        scale = 1 + (1000-t)/3000
    else:
        scale = 1.1
    
    return (scale,)

def arrow_fly(t):
    """丘比特之箭飞行函数"""
    
    t %= 4000
    if t > 2000:
       return ((0,-2,40-t/100),)
    else:
       return ((0,-2,0),)

def heart_fly(t):
    """丘比特之箭飞行函数"""
    
    t %= 4000
    if t > 2000:
       return ((0,0,1,90), (0,-2,40-t/100))
    else:
       return ((0,0,1,90), (0,-2,0))

glt.figure(azim=50, elev=16, style='gray') # 设置初始方位角、高度角、背景色
glt.mesh(*red_heart(2), color='crimson', transform=heart_beat) # 绘制跳动的红心

x, y, z = red_heart(0.2, thick=3.0, shift=(0,-8,0)) # 生成心形箭头顶点数据
glt.mesh(x, -z, y, color='crimson', transform=heart_fly) # 绘制心形箭头

light = wxgl.SunLight(roughness=0, metalness=0, shininess=0.5) # 箭杆灯光
glt.cylinder((0,0,-8), (0,0,9), 0.1, color='goldenrod', transform=arrow_fly, light=light) # 绘制箭杆

vs = [(-1,1,11), (1,-1,11), (1,-1,6), (-1,1,6),(-1,-1,11), (1,1,11), (1,1,6), (-1,-1,6)] # 箭尾顶点数据
texture = wxgl.Texture(r'res\feather.png') # 箭尾羽毛纹理
texcoord = [(0,1), (0,0), (1,0), (1,1),(0,1), (0,0), (1,0), (1,1)] # 箭尾纹理坐标
light = wxgl.BaseLight() # 箭尾灯光
glt.quad(vs, texture=texture, texcoord=texcoord, transform=arrow_fly, light=light) # 绘制箭尾

glt.show()

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64

wxgl的工具条提供了录制gif和MP4文件的功能,下面的gif就是使用wxgl自带的录制功能生成的。

在这里插入图片描述

丘比特之爱情金箭

代码中用到了羽毛的纹理,请下载这个图片,并保存到代码指定的位置。
在这里插入图片描述

箭尾羽毛的纹理图片

文章来源: xufive.blog.csdn.net,作者:天元浪子,版权归原作者所有,如需转载,请联系作者。

原文链接:xufive.blog.csdn.net/article/details/126141038

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。