2 คะแนน โดย GN⁺ 2024-05-03 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • ShapeUp ถือกำเนิดจากโจทย์ของ Wheel Reinvention Jam ที่ให้ “มองซอฟต์แวร์เดิมอีกครั้งด้วยมุมมองใหม่” และถูกทำจนเสร็จเป็น 3D โมเดลเลอร์ที่มีทั้งเดโมรันบนเบราว์เซอร์และการส่งออก .obj
  • หัวใจสำคัญที่ทำให้สร้างเครื่องมือ 3D ได้ภายในหนึ่งสัปดาห์คือ ray marched SDF ซึ่งทำให้สร้างฉากที่มีสี เงานุ่ม และ ambient occlusion ได้เร็วกว่าตัวเรนเดอร์แบบอิงสามเหลี่ยม
  • การพัฒนาถูกทำให้เรียบง่ายโดยยึด ไฟล์ C ไฟล์เดียว เป็นหลัก และเก็บโมเดลไว้ในอาร์เรย์แบบคงที่ที่บรรจุ Shape ได้สูงสุด 100 ชิ้นเพื่อลดภาระการจัดการหน่วยความจำ
  • raylib ช่วยเปิดหน้าต่าง OpenGL ได้อย่างรวดเร็ว แต่เพราะ API ที่ยึด int เป็นหลัก การไม่ตรวจสอบพารามิเตอร์ การพึ่งพา GLFW และข้อจำกัดของ raygui จึงต้องเขียน OpenGL ตรง ๆ หรือสร้างฟังก์ชันที่ต้องใช้ขึ้นมาใหม่
  • ผลลัพธ์สุดท้ายมีขนาด C 2024 บรรทัด และ GLSL 250 บรรทัด รวมราว 2300 บรรทัด พร้อมรองรับการเปิด/บันทึกไฟล์ การรันหลายแพลตฟอร์ม และการส่งออก .obj

ShapeUp เปลี่ยนมาเป็น 3D โมเดลเลอร์ได้อย่างไร

  • Wheel Reinvention Jam คือ อีเวนต์เขียนโปรแกรมหนึ่งสัปดาห์ ที่ชวนให้กลับมามองระบบซอฟต์แวร์เดิมด้วยมุมมองใหม่
  • เป้าหมายแรกเริ่มมาจากความไม่พอใจกับ TypeScript compiler ที่ช้า จึงตั้งใจจะสร้าง TypeScript subset ที่เร็วกว่า tsc
    • เมื่อใช้ตัวแยกวิเคราะห์ TypeScript ของ esbuild หรือ Bun เป็นจุดเริ่มต้น ก็ดูเหมือนจะเป็นไปได้
    • แต่เดโมที่สำเร็จจะมีแค่ “คำสั่งในเทอร์มินัลอันหนึ่งจบเร็วกว่าคำสั่งอีกอัน” ซึ่งไม่น่าดึงดูดในเชิงภาพ สุดท้ายจึงเปลี่ยนทิศไปทำ 3D
  • ShapeUp ถูกสร้างให้เป็น 3D โมเดลเลอร์ที่แก้ไขรูปทรงด้วยเมาส์
    • แม้จะเคยมีประสบการณ์เขียน SDF shader มาก่อน แต่การทำโมเดลโดยต้องแก้โค้ดเองไม่ใช่วิธีที่เป็นธรรมชาติ
    • เป้าหมายคือทำให้สามารถ แก้ไขรูปทรงแบบอิง SDF ได้ด้วยเมาส์

ทำไม SDF จึงทำให้โปรเจ็กต์หนึ่งสัปดาห์เป็นไปได้

  • พื้นฐานการเรนเดอร์ของ ShapeUp คือ ray marched signed distance fields (SDFs)
  • ฉากแบบ SDF สามารถทำได้เร็วกว่าเรนเดอร์แบบอิงสามเหลี่ยม แม้จะมีทั้งสี เงานุ่ม และ ambient occlusion
  • ตัวอย่างของ Inigo Quilez ที่สร้างคาแรกเตอร์สไตล์ Pixar ด้วย SDF ภายในช่วงเวลาสั้น ๆ เป็นจุดอ้างอิงด้านเทคนิค
  • ShapeUp จัดการงานโมเดลด้วย SDF ผ่านการควบคุมรูปทรงโดยตรง แทนการแก้ไขโค้ด

การเขียนด้วย C และโครงสร้างข้อมูล

  • ShapeUp เขียนด้วย C และใช้ raylib เพื่อสร้างหน้าต่าง OpenGL
  • เหตุผลที่เลือก C คือคอมไพล์เร็ว ไวยากรณ์ไม่ซ่อนพฤติกรรมที่ซับซ้อน คุ้นเคย และสามารถคอมไพล์ได้ทั้งแบบเนทีฟและ WebAssembly
  • โมเดลประกอบขึ้นจากชุดของโครงสร้าง Shape
    • Shape แต่ละชิ้นมีตำแหน่ง ขนาด มุม รัศมีมุม ระดับ blob สี แกนสำหรับ mirror และสถานะว่าทำหน้าที่ subtract หรือไม่
  • รายการ Shape ถูกจัดการด้วยอาร์เรย์แบบคงที่แทนการจัดสรรแบบไดนามิก
    • MAX_SHAPE_COUNT คือ 100
    • ใช้ Shape shapes[MAX_SHAPE_COUNT], shape_count, selected_shape ในการเก็บสถานะ
    • วิธีนี้ตัดความเป็นไปได้ของการจัดสรรล้มเหลวและหน่วยความจำรั่ว
  • ข้อจำกัดที่ 100 Shape ไม่ได้เป็นปัญหาใหญ่ในการใช้งานจริง
    • เพราะยังไม่มีเวลา optimize ตัวเรนเดอร์ จึงทำให้เฟรมเรตตกก่อนจะถึง 100 ชิ้น
    • ถ้ามีเวลา ผู้เขียนตั้งใจจะแบ่งโมเดลออกเป็นก้อนอิฐเล็ก ๆ แล้วทำ ray marching ภายในแต่ละก้อน

วิธีใช้หน่วยความจำ

  • ShapeUp ใช้การจัดสรรหน่วยความจำแบบไดนามิกเพียง 3 จุด
    • การบันทึก: จัดสรรบัฟเฟอร์เพื่อเก็บเอกสารทั้งหมด
    • การส่งออก .OBJ: จัดสรรบัฟเฟอร์เพื่อเก็บ vertex ทั้งหมด
    • การสร้าง GLSL shader: จัดสรรบัฟเฟอร์สำหรับซอร์สของ shader
  • ในแต่ละกรณีจะ free เพียงครั้งเดียวตอนจบฟังก์ชัน
  • จะเลือก malloc ให้ Shape ทีละตัวแล้วเก็บพอยน์เตอร์ไว้ใน dynamic array ก็ได้ แต่โปรเจ็กต์นี้ไม่จำเป็นต้องใช้โครงสร้างแบบนั้น
  • C มีข้อดีตรงที่ควบคุมการจัดวางหน่วยความจำได้โดยตรง
  • ถ้าจำเป็นต้องใช้ dynamic array หรือ hash map ก็สามารถใช้เครื่องมืออย่าง stb_ds.h ได้

วิธีทำ UI

  • UI ถูกสร้างด้วยแนวทาง immediate mode user interface (IMGUI)
  • จุดเด่นของ IMGUI คือ debug ง่าย และสามารถกำหนดตำแหน่งองค์ประกอบด้วยภาษาโปรแกรมจริง ๆ แทน CSS, constraints หรือ SwiftUI
  • องค์ประกอบที่โฟกัสอยู่หรือการกระทำของเมาส์ถูกติดตามด้วย enum Control
    • สถานะการควบคุมอย่างตำแหน่ง ขนาด มุม สี การย้าย การหมุน การสเกล การหมุนกล้อง และระดับ blob ถูกแทนด้วยค่า enum
    • focused_control และ mouse_action ใช้เก็บสถานะ UI ปัจจุบัน

จุดที่ติดขัดกับ raylib และ raygui

  • raylib มีประโยชน์สำหรับการเปิดหน้าต่าง OpenGL อย่างรวดเร็ว แต่เมื่อเวลาผ่านไปกลับกลายเป็นปัจจัยที่ทำให้การพัฒนาช้าลง
  • ส่วนที่น่าอึดอัดที่สุดของ API ของ raylib คือ การขาดข้อมูลชนิดข้อมูล
    • แม้ในจุดที่ควรคาดหวัง enum type ก็ยังใช้ int ทำให้คอมไพเลอร์ช่วยตรวจสอบชนิดไม่ได้
    • เพียงดูจากฟังก์ชันซิกเนเจอร์ก็ไม่ค่อยรู้ว่าพารามิเตอร์แต่ละตัวหมายถึงอะไร
    • ตัวอย่างเช่น IsGestureDetected(unsigned int gesture) ทำให้ gesture ดูเหมือน registered gesture ID แต่จริง ๆ แล้วเป็น enum Gesture
    • เนื่องจากเอกสารอิงไฟล์ header เป็นหลัก หากอยากรู้ว่า int ตัวไหนจริง ๆ คือ enum ก็ต้องไปดู implementation
  • การออกแบบที่ไม่ตรวจสอบพารามิเตอร์ขั้นพื้นฐานยิ่งทำให้ปัญหารุนแรงขึ้น
    • LoadFileData(const char *fileName, int * dataSize) จะ segfault ถ้า dataSize เป็น NULL
    • ใน header ไม่ได้บอกว่า dataSize เป็น output parameter หรือห้ามเป็น null
    • การไม่มีการตรวจสอบทำให้ไล่หาปัญหาง่าย ๆ ได้ยาก และบางกรณีก็อาจเกิดพฤติกรรมผิดปกติแบบเงียบ ๆ
  • การจัดการ dependency ก็ไม่เป็นไปตามที่คาดหวัง
    • มีปัญหาที่ raylib ไม่ได้หลบหรือส่งแพตช์แก้ issue ของ GLFW
    • สำหรับผู้ใช้ปลายทาง สิ่งสำคัญกว่าวิธีสร้างหน้าต่างภายในคือฟังก์ชันของ raylib ต้องทำงานได้ถูกต้อง
  • ไลบรารี UI อย่าง raygui มีข้อจำกัดมากเกินไปสำหรับการใช้ในโปรเจ็กต์นี้
    • ไม่สามารถแสดงตัวเลขทศนิยมได้ จึงต้องสร้างฟิลด์ข้อความแบบ float เอง
    • จัดการ routing ของ mouse event สำหรับองค์ประกอบที่ซ้อนกันหรือถูกตัดไม่ได้
    • ไม่รองรับมุมโค้งมนที่พบได้บ่อยใน UI
    • ทำสไตล์ให้ออกมาดูดีได้ยาก
  • บั๊กก็รบกวนการทำงานเช่นกัน
    • บั๊กของเครื่องมือ raygui ทำให้เปลี่ยนฟอนต์เริ่มต้นที่ถูกตกแต่งมากเกินไปไม่ได้
    • ฟังก์ชันวาดอย่าง DrawCircle(...) ไม่ได้แชร์ vertex ระหว่างสามเหลี่ยม จึงเกิดช่องว่างระดับพิกเซลจากความคลาดเคลื่อนของ floating point เมื่อเมทริกซ์ปัจจุบันมีการสเกลหรือหมุน
  • แม้จะรายงาน issue ที่พบอยู่ช่วงหนึ่ง แต่ส่วนใหญ่ถูกปิดด้วยสถานะ “wont fix” จึงเลิกรายงานในภายหลัง
  • วิธีเลี่ยงคือเรียกใช้ฟังก์ชัน OpenGL โดยตรง หรือสร้างความสามารถที่ต้องใช้ขึ้นมาเองตั้งแต่ต้น
  • ต่อจากนี้มีแผนจะใช้ sokol แทน raylib

4 อย่างที่ต้องทำให้เสร็จภายใน 6 วัน

  • ภายใน 6 วัน ShapeUp ต้องทำส่วนใหญ่ ๆ ให้เสร็จ 4 ส่วน
    • ส่วนติดต่อผู้ใช้: 3D gizmo, คีย์ลัด, แถบด้านข้าง, game controller
    • ตัวสร้าง GLSL shader และตัวเรนเดอร์แบบ ray marching
    • การเลือกด้วยเมาส์บน GPU
    • marching cubes สำหรับการส่งออก
  • ความยากไม่ได้อยู่ที่แต่ละฟังก์ชันเพียงอย่างเดียว แต่อยู่ที่การ รักษาลำดับความสำคัญ
  • ปัญหาที่ยุ่งยากหรือใช้เวลานานจะถูกเลี่ยงด้วยการเปลี่ยนแบบ หรือแก้ด้วยวิธีง่าย ๆ ที่ใช้ได้ใน 90% ของกรณี
  • บางฟังก์ชันก็ได้คำตอบหลังจากปล่อยทิ้งไว้หนึ่งวัน
  • วิธีทำงานคือรักษา 3D โมเดลเลอร์ที่ใช้งานได้ตลอดเวลา แล้วค่อย ๆ ปรับปรุงเพิ่มเท่าที่เวลาจะอำนวย
    • ไม่ใช่การสร้างแบบที่กลายเป็นพีระมิดเฉพาะตอนเสร็จสมบูรณ์ แต่เป็นการทำให้ไม่ว่าจะหยุดตรงขั้นไหนก็ยังเป็นพีระมิดขนาดเล็กที่สมบูรณ์อยู่

ผลลัพธ์สุดท้าย

  • เมื่อครบหนึ่งสัปดาห์ ShapeUp สามารถสร้างโมเดล 3D ที่มีความหมายและส่งออกเป็นไฟล์ .obj ได้
  • รองรับการทำงานหลายแพลตฟอร์ม และมีทั้งการเปิดไฟล์กับบันทึกไฟล์
  • ขนาดโค้ดคือ C 2024 บรรทัด และ GLSL 250 บรรทัด
  • การสร้าง 3D โมเดลเลอร์ที่พอใช้งานได้ด้วยโค้ดราว 2300 บรรทัดถือเป็นผลลัพธ์ที่น่าสนใจ
  • แม้ตัวโปรเจ็กต์เองจะค่อนข้างเรียบง่าย แต่สิ่งสำคัญคือวิจารณญาณในการเลือกว่าจะสร้างอะไร ความรู้ที่ทำให้สร้างได้ และวินัยในการทำให้เสร็จภายในหนึ่งสัปดาห์

1 ความคิดเห็น

 
GN⁺ 2024-05-03
ความคิดเห็นจาก Hacker News
  • เห็นด้วยกับผู้เขียนอย่างเต็มที่เรื่องข้อจำกัดของ Raylib ตอนนี้กำลังทำเกมแนวทาวเวอร์ดีเฟนส์ที่เริ่มจาก Raylib อยู่ และกำลังเจอข้อจำกัดเดียวกันกับปัญหาอื่น ๆ อีกมาก
    เช่น การสลับโหมดเต็มหน้าจอ ทำงานไม่สม่ำเสมอในแต่ละแพลตฟอร์ม, ไม่สามารถไล่รายการโหมดหน้าจอได้, สลับเปิด/ปิดฟีเจอร์การเรนเดอร์ระหว่างรันได้ยาก, ปัญหาการบันทึก shader ที่คอมไพล์แล้ว ฯลฯ
    ถึงอย่างนั้นก็ยังขอบคุณงานที่ Ray ทุ่มเทให้ไลบรารีนี้ และตั้งใจจะสนับสนุนต่อไป Raylib ยอดเยี่ยมสำหรับการทำ prototype อย่างรวดเร็ว แต่ถ้าจะไปไกลกว่านั้นโดยไม่ยอมรับข้อจำกัดหนัก ๆ ก็ไม่ง่าย
    ได้เรียนรู้อะไรแน่นอน แต่ตอนนี้การพัฒนาไปไกลเกินกว่าจะรื้อโค้ดที่เกี่ยวกับ Raylib ทั้งหมดแล้วเปลี่ยนเป็นอย่าง SDL

    • รายละเอียดที่ว่า Raylib ไม่ได้มาจาก ray tracing แต่มาจากชื่อผู้สร้างคือ Ray นั้นน่าสนุกดี
      Things Unexpectedly Named After People: https://notes.rolandcrosby.com/posts/unexpectedly-eponymous/
    • Raylib เริ่มต้นใช้ง่าย แต่พอโปรเจกต์ซับซ้อนขึ้นหน่อยก็เริ่มย้อนมากัด ในทางกลับกัน SDL ใช้เวลาตั้งค่าเริ่มต้นมากกว่า แต่ยิ่งโปรเจกต์ใหญ่ก็ยิ่งขยายต่อได้ดีมาก คุณภาพโค้ดก็ดีเป็นพิเศษ
    • Raylib มีปัญหาอีกมากที่คงไม่ได้แก้ในอนาคต แต่จะโทษ Raylib อย่างเดียวเรื่อง เต็มหน้าจอ ก็คงยาก โหมดเต็มหน้าจอของ Windows พังจนแทบใช้ไม่ได้มาหลายสิบปีแล้ว และแพลตฟอร์มอื่นก็น่าจะคล้ายกัน
      กลยุทธ์ยุคนี้คือใช้โหมดหน้าต่างไร้ขอบไปเลย แล้วทำเหมือนว่าไม่มีโหมดเต็มหน้าจอจริง ๆ
    • รู้สึกคล้ายกัน ประมาณ 2 เดือนก่อนเริ่มโปรเจกต์และเลือก Raylib ของพื้นฐานทำให้เดินหน้าได้ง่ายจริง ๆ แต่ยิ่งใช้ก็ยิ่งเจอความไม่สะดวกเล็ก ๆ แบบสุ่มอยู่เรื่อย ๆ ตอนนี้ลงทุนกับโปรเจกต์ไปมากเกินกว่าจะย้อนเลิกใช้ Raylib แล้ว
      ปัญหาใหญ่สุดตอนนี้คือ การจัดการฟอนต์และการเรนเดอร์ข้อความ ดูเหมือนอาจต้องเปลี่ยนจากฟอนต์ TTF ไปใช้ฟอนต์บิตแมปที่เตรียมไว้ล่วงหน้า ซึ่งน่าจะลำบากพอสมควรตอนทำ localization ภายหลัง
      ฟีเจอร์สองอย่างที่คิดถึงที่สุดหลังย้ายมาจาก Love2D คือการเรนเดอร์ข้อความหลายสีได้ง่าย และการตัด texture แล้วทำซ้ำหรือ tile ได้ง่าย ใน Raylib ต้องแบ่งข้อความเองตาม markup สี ใส่ออฟเซ็ตความกว้าง แล้วเรียกฟังก์ชันวาดให้แต่ละชิ้นโดยยังต้องคำนึงถึงการขึ้นบรรทัดด้วย
      ถ้าวาดข้อความบนหน้าจอเยอะ ๆ FPS ก็ดูเหมือนตกลงมาก อาจเป็นเพราะ batching ของ draw call สำหรับข้อความแตกก็ได้ เมื่อก่อนเคยมีฟังก์ชันวาด tile texture แต่ถูกเอาออกไปด้วยเหตุผลบางอย่าง
    • เห็นสิ่งนี้แล้วทำให้อยากลองดู raylib มีตัวอย่างน่ารัก ๆ ที่รันด้วย WebAssembly: https://www.raylib.com/examples.html
      สิ่งที่ขัดใจเสมอเกี่ยวกับ Wasm และกราฟิก 3D/2D บนเบราว์เซอร์คือมักเห็นปัญหาเล็ก ๆ อย่างการเลื่อนหน้าจอ ลองดูตัวอย่าง “Background scrolling & parallax” ที่นี่: https://www.raylib.com/examples.html
      ทดสอบกับหลายอุปกรณ์แล้ว ถ้าตาผมไม่ได้เพี้ยนไปเอง มันไม่ใช่ การเลื่อนที่ลื่นไหล แน่นอน นึกไม่ออกเลยว่าในปี 2024 การเลื่อน 2D ให้ลื่นยังไม่ใช่ปัญหาที่แก้จบแล้วได้อย่างไร
  • “เก็บ Shape ไว้ในอาร์เรย์ที่จัดสรรแบบ static ไม่มีการจัดสรรล้มเหลว ไม่มี leak ไม่มีส่วนเกิน รักเลย ข้อจำกัด Shape 100 ชิ้นไม่ได้เป็นข้อจำกัดจริง ๆ เพราะแทบไม่มีเวลา optimize renderer ดังนั้น frame rate คงตกก่อนจะไปถึง 100 ชิ้นอยู่แล้ว”
    เป็นตัวอย่างที่ดีที่สุดอย่างหนึ่งที่เพิ่งเห็นของ การหลีกเลี่ยง premature optimization

    • ผมว่ากลับกันมากกว่า คือหลีกเลี่ยง abstraction และ generalization ที่ทำเร็วเกินไป
    • เป็นตัวอย่างชั้นดีที่แสดงความต่างระหว่างคนที่ลงมือทำจริง กับคนที่นั่งเถียงกันอย่างเดียวว่าจะทำอย่างไร
  • เป็นบทความที่น่าสนใจมาก และชอบที่เล่าถึงการตัดสินใจหลายอย่าง เช่น วิธีจัดการหน่วยความจำกับปัญหาที่เจอใน raylib พอดีกำลังทบทวน C ใหม่ขณะเข้าสู่พาร์ต 2 ของ Crafting Interpreters เลยดีที่ได้ระลึกอีกครั้งว่า C ทำอะไรได้ดี

  • เดโมแบบเรียลไทม์ ในวิดีโอดีมาก เอาแค่ทำวิดีโอนั้น ถ้าเป็นผมลองทำเองก็คงทำไม่ทันในหนึ่งสัปดาห์ด้วยซ้ำ ไม่ต้องพูดถึงการทำแอป

    • การทำวิดีโอใช้เวลานานกว่าทำแอปอีก ไม่รู้ว่า YouTuber ทำกันได้สม่ำเสมอขนาดนั้นได้อย่างไร
  • นานมาแล้วเคยทำระบบปฏิบัติการสำหรับโทรศัพท์ตั้งโต๊ะ มี RAM แค่ 64K จึงไม่มี การจัดการหน่วยความจำแบบ dynamic เลย และใช้ตัวแปร static จำนวนมากให้คอมไพเลอร์จัดวางทั้งหมดตอนคอมไพล์
    เรามักลืมไปง่าย ๆ ว่าแอปพลิเคชันจำนวนมากอาจไม่จำเป็นต้องมีการจัดการหน่วยความจำแบบ dynamic เลย แค่จัดสรร buffer ขนาดคงที่ไว้ไม่กี่ชุด แล้วจัดการกรณียกเว้นเมื่อ buffer เต็มให้เรียบร้อยก็มักเพียงพอ
    ในบริบทแบบนั้น C จริง ๆ แล้วปลอดภัยกว่ามาก ไม่มี memory leak และสิ่งที่ต้องกังวลมีแค่ buffer overflow ถ้าตัวแปรทั้งหมดถูกจัดสรรแบบ static ก็จัดการได้ด้วยการใช้ sizeof อย่างระมัดระวัง
    ไม่ได้หมายความว่า Rust กับ Go ในยุคนี้ไม่ใช่ตัวเลือกที่ยอดเยี่ยม แต่ C แบบเก่า ๆ ที่เรียบง่ายก็ยังทำงานได้ดี และไม่จำเป็นต้องซับซ้อนเหมือนฝันร้าย

  • อาจนอกประเด็นไปหน่อย แต่ดีใจที่ได้เห็น อินเทอร์เฟซ WebAssembly ที่ข้อความไม่ดูพร่ามัวเป็นครั้งแรก จริง ๆ คือครั้งแรกเลย
    ถ้าขยายไปถึงโปรแกรมและระบบปฏิบัติการบางตัว เช่น Windows ก็เกิดปัญหาโดยรวมในช่วงไม่กี่ปีที่ผ่านมา เมื่อวิธี rasterize ข้อความแบบหนึ่งกลายเป็นกระแสร่วมและค่าเริ่มต้น
    น่าเสียดายที่ผู้ใช้มักปิด anti-aliasing เพื่อให้ได้ข้อความคมชัดไม่ได้ และแม้ในกรณีหายากที่มีตัวเลือก อินเทอร์เฟซอย่างเมนูก็ยังถูกใช้ anti-aliasing อยู่ดี

    • ข้อความคมชัดนั้นไม่ได้ประทับใจเท่าไร ตัวอักษรไม่มีเส้นโค้งและไม่มี smoothing ไม่ว่าความละเอียดไหนก็น่าจะดูเป็น ข้อความเหลี่ยมเป็นบล็อก ที่คมชัด
    • สงสัยว่ามีความเชื่อมโยงอะไรระหว่าง WebAssembly กับ rasterization ดูน่าสนใจจริง ๆ
  • ชอบโปรเจกต์แบบนี้มาก ยังชอบ ความเป็นระดับต่ำของ C อยู่ ตอนนี้ใช้ Rust กับ Elixir/Erlang เยอะ แต่ก็มักคิดถึงความเรียบง่ายและความชัดเจนของ C
    เพราะงั้นเลยใช้ Zig เยอะด้วย เป็นภาษาที่รักษาปรัชญาของ C ไว้มาก แต่ปรับปรุงได้ดีมาก

    • Erlang ก็เป็นภาษาที่ค่อนข้างเรียบง่ายเหมือนกัน
  • เห็นด้วยจริง ๆ กับการประเมินของเขาเกี่ยวกับ C โดยเฉพาะตรงที่ว่า “ไวยากรณ์ไม่ได้ซ่อนพฤติกรรมที่ซับซ้อนไว้ มันเรียบง่ายพอจนไม่ต้องคอยค้นหาอยู่เรื่อย ๆ” และยิ่งไปกว่านั้น แม้เวลาต้องค้นหาอะไรเกี่ยวกับ C ก็ยังง่ายและได้ประโยชน์มาก
    ภาษาที่เรียบง่ายและเก่าแก่ ก็มีข้อดีในแบบของมัน

  • ถ้าแยกจัดสรรแต่ละ Shape ด้วย malloc แล้วเก็บพอยน์เตอร์เหล่านั้นไว้ใน dynamic array ก็แน่นอนว่าจะทำให้ตัวเองลำบากขึ้นได้ มีการพูดทำนองว่าถ้าใช้ภาษาอย่าง C# จะถูกบังคับให้ใช้โครงสร้างการจัดสรรแบบนั้น แต่สงสัยว่าอะไรคือสิ่งที่ห้ามไม่ให้ใช้ อาร์เรย์ขนาดคงที่ของ struct ใน C# เหมือนที่ผู้เขียนทำใน C

    • ไม่มีอะไรห้ามเลย ใน C# การใช้ อาร์เรย์ของ struct แบบนี้ก็ไม่ใช่เรื่องแปลก
  • อยากให้มีใครสักคนสานต่อโปรเจกต์นี้ ถ้าขัดเกลาเพิ่มอีกไม่กี่เดือน มันอาจเป็นทางเลือกที่จริงจังแทน Blender หรือ FreeCAD สำหรับการใช้งานเฉพาะทางบางอย่างได้ และเส้นโค้งการเรียนรู้ก็ดูจะนุ่มนวลกว่ามาก

    • ลองดู MagicaCSG ด้วยก็ได้ ซึ่งเป็นเวอร์ชันที่ประณีตกว่าและยังฟรีอยู่: https://ephtracy.github.io/index.html?page=magicacsg#ss-caro...
    • แก้ไข: อ้อ โปรแกรมนี้รองรับการส่งออกเมชด้วย marching cubes อยู่แล้ว ดูวิดีโอ YouTube บนไซต์ได้เลย ผมไม่รู้เรื่องนั้นมาก่อน
      อย่างไรก็ตาม โดยพื้นฐานแล้วมันทำงานด้วย SDF ดังนั้นประสบการณ์การโมเดลจึงต่างจากเมชแบบดั้งเดิมที่ใช้สามเหลี่ยม จุดยอด ฯลฯ และข้อมูลที่จัดเก็บก็ต่างกันด้วย
      การแปลง SDF เป็นเมชทำได้ด้วยวิธีอย่าง marching cubes แต่ข้อมูลแบบนั้นมีโอกาสสูงที่จะต้องนำไปจัดระเบียบต่อในแอปแนว Blender อยู่ดี
      ถ้า renderer ก็อิง SDF ด้วย SDF ก็ยอดเยี่ยมมาก แต่ส่วนใหญ่ไม่ได้เป็นแบบนั้น
      ถ้ารู้อยู่แล้วก็ขอโทษด้วย
    • ถ้าชอบ SDF Womp ก็เป็นจุดเริ่มต้นที่ค่อนข้างดี Tinkercad ก็ใช้เป็น CAD สำหรับผู้เริ่มต้นได้ค่อนข้างดีเหมือนกัน
    • ลองดู Dune3D และ Salome-Platform ด้วยก็ได้
    • อาจเป็นทางเลือกแทน Blender ได้ แต่คงไม่ใช่ทางเลือกแทน งาน CAD อย่างน่าเสียดาย