使用C语言绘制一个笑脸smile

其他 专栏收录该内容
1 篇文章 0 订阅

首先我们绘制一个简单的例子

#include <math.h>
#include <stdio.h>

int main() {
  double a, b;
  for (b = 1; b >= -1; b -= 0.05, putchar('\n'))
    for (a = -1; a <= 1; a += 0.025)
      putchar(" *"[ a * b + b * b < 1 && fabs(atan2(b, a)) > 0.5 && a * a + pow(b - 0.5, 2) > 0.02]);
}

运行后,可以在控制台显示出一个笑脸~~~

# if you do not have gcc, run `brew install gcc` to install 

gcc test1.c && ./a.out
gcc test2.c && ./a.out

然后我们可以循环生成多个笑脸(当然可以再加一个循环生成三重笑脸)

#include <math.h>
#include <stdio.h>

int func(double x, double y, int d) {
  return
    pow(x - 0.5, 2) + pow(y - 0.5, 2) < 0.25 && fabs(atan2(y - 0.5, x - 0.5)) > 0.5 && pow(x - 0.5, 2) + pow(y - 0.75, 2) > 0.005 && (d == 0 || f(fmod(x * 8, 1), fmod(y * 8, 1), d - 1));
}

int main() {
  double x, y;
  for (y = 1; y >= 0; y -= 1.0 / 160.0, putchar('\n'))
    for (x = 0; x <= 1; x += 1.0 / 320.0)
      putchar(" *"[func(x, y, 1)]);
        
}

后面是我们的终极3D笑脸

#include <math.h>
#include "svpng.inc"

typedef struct { float x, y, z; } V;
V make(float x, float y, float z) { V r = { x, y, z }; return r; }
V add(V a, V b) { return make(a.x + b.x, a.y + b.y, a.z + b.z); }
V sub(V a, V b) { return make(a.x - b.x, a.y - b.y, a.z - b.z); }
V mul(V v, float s) { return make(v.x * s, v.y * s, v.z * s); }
float dot(V a, V b) { return a.x * b.x + a.y * b.y + a.z * b.z; }
float len(V v) { return sqrtf(dot(v, v)); };
V cross(V a, V b) { return make(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x); }
V norm(V v) { return mul(v, 1.0f / len(v)); }
float min(float a, float b) { return a < b ? a : b; }
float max(float a, float b) { return a > b ? a : b; }

float map(V p) {
  V m1 = { cosf(1), 0, sinf(1) }, m2 = { cosf(1), 0, -sinf(1)};
  return min(max(len(p) - 1.0f, min(dot(p, m1), dot(p, m2))), p.z + 1.0f);
}

V normal(V p) {
  float e = 1e-6f;
  V dx = { e, 0, 0 }, dy = {0, e, 0}, dz = {0, 0, e };
  return norm(make(
    map(add(p, dx)) - map(sub(p, dx)),
    map(add(p, dy)) - map(sub(p, dy)),
    map(add(p, dz)) - map(sub(p, dz))));
}

V albedo(V p) {
  if (p.z + 1 < 1e-4f)
    return make(1, 1, 1); // ground
  else if (p.x * p.x + powf(p.z - 0.5, 2) < 0.02f)
    return make(0, 0, 0); // eye
  else
    return make(1, 1, 0); // main
}

#define S 1024
unsigned char img[S * S * 3], *c = img;

int main() {
  V eye = { 2, 3, 1 }, at = { 0, 0, 0 }, up = { 0, 0, 1 };
  V vz = norm(sub(at, eye)), vx = cross(up, vz), vy = cross(vz, vx);
  int x, y, i;
  for (y = S - 1; y >= 0; y--)
    for (x = 0; x < S; x++, c += 3) {
      float sx = ((float)x / S - 0.5f) * 3.0f;
      float sy = ((float)y / S - 0.5f) * 3.0f;
      V o = add(add(eye, mul(vx, sx)), mul(vy, sy));
      float t = 0;
      do {
        V p = add(o, mul(vz, t));
        float sd = map(p);
        if (sd < 1e-4f) {
          V n = normal(p), alb = albedo(p);
          float ao = 1, s = 0.5f;
          for (i = 1; i < 5; i++) {
            float d = i * 0.1f;
            ao = max(ao - (d - map(add(p, mul(n, d)))) * s, 0.1f);
            s *= 0.95f;
          }
          V r = mul(alb, (dot(n, norm(make(0, 1, 1))) * 0.5f + 0.5f) * ao * 255);
          c[0] = (unsigned char)r.x;
          c[1] = (unsigned char)r.y;
          c[2] = (unsigned char)r.z;
          break;
        }
        t += sd;
      } while (t < 100);
    }
  svpng(fopen("pacman.png", "wb"), S, S, img, 0);
}

是不是很厉害!

评论 27 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:终极编程指南 设计师:CSDN官方博客 返回首页

打赏作者

Michael18811380328

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值